Skip to content

Commit b48f47d

Browse files
committed
feat(ui): add slides component
1 parent 10b957f commit b48f47d

17 files changed

Lines changed: 385 additions & 3 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"regenerator-runtime": "^0.13.9",
4545
"rfs": "^9.0.6",
4646
"rxjs": "^7.5.5",
47+
"swiper": "^8.3.1",
4748
"tslib": "^2.4.0"
4849
},
4950
"devDependencies": {

packages/site/src/app/styles/_app.scss

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,3 +334,14 @@ h3 {
334334
color: var(--d-color-primary-lighter);
335335
}
336336
}
337+
338+
.app-demo-slide {
339+
display: flex;
340+
align-items: center;
341+
justify-content: center;
342+
width: 100%;
343+
height: 100%;
344+
/* stylelint-disable-next-line declaration-property-value-allowed-list */
345+
color: #fff;
346+
background: rgb(54 77 121);
347+
}

packages/ui/src/components/_base-input/BaseInput.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,22 @@ export interface DBaseInputProps extends React.InputHTMLAttributes<any> {
1313
}
1414

1515
function BaseInput(props: DBaseInputProps, ref: React.ForwardedRef<any>): JSX.Element | null {
16-
const { dFormControl, dTag = 'input', dFor = true, ...restProps } = props;
16+
const {
17+
dFormControl,
18+
dTag = 'input',
19+
dFor = true,
20+
21+
id,
22+
...restProps
23+
} = props;
1724

1825
//#region Context
1926
const dPrefix = usePrefixConfig();
2027
const formContext = useContext(DFormContext);
2128
//#endregion
2229

2330
const uniqueId = useId();
24-
const id = `${dPrefix}base-input-${uniqueId}`;
31+
const _id = id ?? `${dPrefix}base-input-${uniqueId}`;
2532

2633
const supportForm = formContext && dFormControl;
2734

@@ -36,7 +43,7 @@ function BaseInput(props: DBaseInputProps, ref: React.ForwardedRef<any>): JSX.El
3643
...restProps,
3744
...attrs,
3845
ref: ref,
39-
id: props.id ?? id,
46+
id: _id,
4047
'aria-describedby': [props['aria-describedby'], dFormControl?.inputAttrs?.['aria-describedby']]
4148
.filter((describedby) => isString(describedby))
4249
.join(' '),

packages/ui/src/components/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ export { DSeparator } from './separator';
8282
export type { DSliderProps } from './slider';
8383
export { DSlider } from './slider';
8484

85+
export type { DSlidesProps, DSlideProps } from './slides';
86+
export { DSlides, DSlide } from './slides';
87+
8588
export type { DSwitchProps } from './switch';
8689
export { DSwitch } from './switch';
8790

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
group: Data Display
3+
title: Slides
4+
---
5+
6+
## API
7+
8+
### DTagProps
9+
10+
Extend `React.HTMLAttributes<HTMLDivElement>`.
11+
12+
<!-- prettier-ignore-start -->
13+
| Property | Description | Type | Default |
14+
| --- | --- | --- | --- |
15+
| dType | Set tag type | 'primary' \| 'fill' \| 'outline' | 'primary' |
16+
| dTheme | Set tag theme | 'primary' \| 'success' \| 'warning' \| 'danger' | - |
17+
| dColor | Custom tag color | string | - |
18+
| dSize | Set tag size | 'smaller' \| 'larger' | - |
19+
| dClosable | Whether the tag can be closed | boolean | false |
20+
| onClose | Callback when the close button is clicked | React.MouseEventHandler\<HTMLSpanElement\> | - |
21+
<!-- prettier-ignore-end -->
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
title: 走马灯
3+
---
4+
5+
## API
6+
7+
### DTagProps
8+
9+
继承 `React.HTMLAttributes<HTMLDivElement>`
10+
11+
<!-- prettier-ignore-start -->
12+
| 参数 | 说明 | 类型 | 默认值 |
13+
| --- | --- | --- | --- |
14+
| dType | 设置标签形态 | 'primary' \| 'fill' \| 'outline' | 'primary' |
15+
| dTheme | 设置标签主题 | 'primary' \| 'success' \| 'warning' \| 'danger' | - |
16+
| dColor | 自定义标签颜色 | string | - |
17+
| dSize | 设置标签尺寸 | 'smaller' \| 'larger' | - |
18+
| dClosable | 标签是否可关闭 | boolean | false |
19+
| onClose | 点击关闭按钮的回调 | React.MouseEventHandler\<HTMLSpanElement\> | - |
20+
<!-- prettier-ignore-end -->
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { SwiperSlideProps } from 'swiper/react';
2+
3+
import { useComponentConfig } from '../../hooks';
4+
import { registerComponentMate } from '../../utils';
5+
6+
export type DSlideProps = SwiperSlideProps;
7+
8+
const { COMPONENT_NAME } = registerComponentMate({ COMPONENT_NAME: 'DSlide' });
9+
export function DSlide(props: DSlideProps): JSX.Element | null {
10+
useComponentConfig(COMPONENT_NAME, props);
11+
return null;
12+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import type { SwiperProps, SwiperSlideProps } from 'swiper/react';
2+
3+
import { isUndefined } from 'lodash';
4+
import React from 'react';
5+
import {
6+
A11y,
7+
Autoplay,
8+
Controller,
9+
EffectCoverflow,
10+
EffectCube,
11+
EffectFade,
12+
EffectFlip,
13+
EffectCreative,
14+
EffectCards,
15+
HashNavigation,
16+
History,
17+
Keyboard,
18+
Lazy,
19+
Mousewheel,
20+
Navigation,
21+
Pagination,
22+
Parallax,
23+
Scrollbar,
24+
Thumbs,
25+
Virtual,
26+
Zoom,
27+
FreeMode,
28+
Grid,
29+
Manipulation,
30+
} from 'swiper';
31+
import 'swiper/css/bundle';
32+
import { Swiper, SwiperSlide } from 'swiper/react';
33+
34+
import { useComponentConfig, usePrefixConfig } from '../../hooks';
35+
import { LeftOutlined, RightOutlined } from '../../icons';
36+
import { getClassName, registerComponentMate } from '../../utils';
37+
38+
export type DSlidesProps = SwiperProps;
39+
40+
const { COMPONENT_NAME } = registerComponentMate({ COMPONENT_NAME: 'DSlides' });
41+
export function DSlides(props: DSlidesProps): JSX.Element | null {
42+
const {
43+
children,
44+
45+
navigation: _navigation,
46+
pagination: _pagination,
47+
direction = 'horizontal',
48+
49+
className,
50+
...restProps
51+
} = useComponentConfig(COMPONENT_NAME, props);
52+
53+
//#region Context
54+
const dPrefix = usePrefixConfig();
55+
//#endregion
56+
57+
const navigation = (() => {
58+
const configs = {
59+
nextEl: '.swiper-button-next',
60+
prevEl: '.swiper-button-prev',
61+
};
62+
if (_navigation === true || isUndefined(_navigation)) {
63+
return configs;
64+
}
65+
if (_navigation !== false) {
66+
return Object.assign(configs, _navigation);
67+
}
68+
return _navigation;
69+
})();
70+
71+
const pagination = (() => {
72+
const configs = {
73+
clickable: true,
74+
};
75+
if (_pagination === true || isUndefined(_pagination)) {
76+
return configs;
77+
}
78+
if (_pagination !== false) {
79+
return Object.assign(configs, _pagination);
80+
}
81+
return _pagination;
82+
})();
83+
84+
return (
85+
<Swiper
86+
{...restProps}
87+
className={getClassName(className, `${dPrefix}slides`, {
88+
[`${dPrefix}slides--vertical`]: direction === 'vertical',
89+
})}
90+
direction={direction}
91+
modules={[
92+
A11y,
93+
Autoplay,
94+
Controller,
95+
EffectCoverflow,
96+
EffectCube,
97+
EffectFade,
98+
EffectFlip,
99+
EffectCreative,
100+
EffectCards,
101+
HashNavigation,
102+
History,
103+
Keyboard,
104+
Lazy,
105+
Mousewheel,
106+
Navigation,
107+
Pagination,
108+
Parallax,
109+
Scrollbar,
110+
Thumbs,
111+
Virtual,
112+
Zoom,
113+
FreeMode,
114+
Grid,
115+
Manipulation,
116+
]}
117+
navigation={navigation}
118+
pagination={pagination}
119+
>
120+
{React.Children.map(children, (child) =>
121+
React.isValidElement(child)
122+
? React.createElement(SwiperSlide, {
123+
...(child.props as SwiperSlideProps),
124+
className: getClassName((child.props as SwiperSlideProps).className, `${dPrefix}slide`),
125+
})
126+
: child
127+
)}
128+
<button className="swiper-button-prev">
129+
<LeftOutlined />
130+
</button>
131+
<button className="swiper-button-next">
132+
<RightOutlined />
133+
</button>
134+
</Swiper>
135+
);
136+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
title:
3+
en-US: Basic
4+
zh-Hant: 基本
5+
---
6+
7+
# en-US
8+
9+
The simplest usage.
10+
11+
# zh-Hant
12+
13+
最简单的用法。
14+
15+
```tsx
16+
import { DSlides, DSlide } from '@react-devui/ui';
17+
18+
export default function Demo() {
19+
return (
20+
<DSlides style={{ height: 200 }}>
21+
<DSlide>
22+
<div className="app-demo-slide">Slide 1</div>
23+
</DSlide>
24+
<DSlide>
25+
<div className="app-demo-slide">Slide 2</div>
26+
</DSlide>
27+
<DSlide>
28+
<div className="app-demo-slide">Slide 3</div>
29+
</DSlide>
30+
<DSlide>
31+
<div className="app-demo-slide">Slide 4</div>
32+
</DSlide>
33+
</DSlides>
34+
);
35+
}
36+
```
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
title:
3+
en-US: Reference Swiper
4+
zh-Hant: 参考 Swiper
5+
---
6+
7+
# en-US
8+
9+
For more usage, refer to [Swiper](https://swiperjs.com/react).
10+
11+
# zh-Hant
12+
13+
更多用法参考 [Swiper](https://swiperjs.com/react)
14+
15+
```tsx
16+
import { DSlides, DSlide } from '@react-devui/ui';
17+
18+
export default function Demo() {
19+
return (
20+
<DSlides
21+
style={{ height: 200 }}
22+
direction={'vertical'}
23+
pagination={{
24+
dynamicBullets: true,
25+
}}
26+
>
27+
{Array(8)
28+
.fill(0)
29+
.map((n, i) => (
30+
<DSlide key={i}>
31+
<div className="app-demo-slide">Slide {i}</div>
32+
</DSlide>
33+
))}
34+
</DSlides>
35+
);
36+
}
37+
```

0 commit comments

Comments
 (0)