deepsea-components 5.15.21 → 5.15.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +23 -23
  2. package/dist/components/AutoFit.cjs +7 -7
  3. package/dist/components/AutoFit.js +7 -7
  4. package/dist/components/AutoScroll.cjs +7 -7
  5. package/dist/components/AutoScroll.js +7 -7
  6. package/dist/components/AutoSizeTextarea.cjs +4 -4
  7. package/dist/components/AutoSizeTextarea.js +4 -4
  8. package/dist/components/Flow.cjs +16 -16
  9. package/dist/components/Flow.js +16 -16
  10. package/dist/components/FormLabel.cjs +1 -1
  11. package/dist/components/FormLabel.js +1 -1
  12. package/dist/components/InfiniteScroll.cjs +13 -13
  13. package/dist/components/InfiniteScroll.js +13 -13
  14. package/dist/components/LoopSwiper.cjs +33 -33
  15. package/dist/components/LoopSwiper.js +33 -33
  16. package/dist/components/Scroll.cjs +13 -13
  17. package/dist/components/Scroll.js +13 -13
  18. package/dist/components/ScrollMask.module.cjs +2 -2
  19. package/dist/components/ScrollMask.module.js +2 -2
  20. package/dist/components/Skeleton.cjs +17 -17
  21. package/dist/components/Skeleton.js +17 -17
  22. package/dist/components/TransitionNum.cjs +1 -1
  23. package/dist/components/TransitionNum.js +1 -1
  24. package/dist/components/Trapezium.cjs +4 -4
  25. package/dist/components/Trapezium.js +4 -4
  26. package/package.json +4 -3
  27. package/src/components/AutoFit.tsx +104 -104
  28. package/src/components/AutoScroll.tsx +150 -150
  29. package/src/components/AutoSizeTextarea.tsx +50 -50
  30. package/src/components/CircleText.tsx +81 -81
  31. package/src/components/CopyButton.tsx +31 -31
  32. package/src/components/Echart.tsx +69 -69
  33. package/src/components/Flow.tsx +271 -271
  34. package/src/components/FormLabel.tsx +41 -41
  35. package/src/components/HlsPlayer.tsx +34 -34
  36. package/src/components/IconFileType.tsx +162 -162
  37. package/src/components/InfiniteScroll.tsx +163 -163
  38. package/src/components/InputFile.tsx +93 -93
  39. package/src/components/InputFileButton.tsx +122 -122
  40. package/src/components/LoopSwiper.tsx +125 -125
  41. package/src/components/ReadExcel.tsx +13 -13
  42. package/src/components/ReadSheet.tsx +17 -17
  43. package/src/components/Ring.tsx +30 -30
  44. package/src/components/Scroll.tsx +97 -97
  45. package/src/components/ScrollMask.module.css +87 -87
  46. package/src/components/ScrollMask.tsx +68 -68
  47. package/src/components/SectionRing.tsx +40 -40
  48. package/src/components/Skeleton.tsx +45 -45
  49. package/src/components/Title.tsx +27 -27
  50. package/src/components/TransitionBox.tsx +44 -44
  51. package/src/components/TransitionNum.tsx +54 -54
  52. package/src/components/Trapezium.tsx +60 -60
  53. package/src/components/Unify.tsx +38 -38
  54. package/src/components/WriteExcel.tsx +13 -13
  55. package/src/components/WriteSheet.tsx +25 -25
  56. package/src/utils/getReactVersion.ts +7 -7
  57. package/src/utils/index.ts +33 -33
  58. package/tsconfig.json +16 -16
@@ -1,271 +1,271 @@
1
- "use client"
2
-
3
- import { css } from "@emotion/css"
4
- import { clsx } from "deepsea-tools"
5
- import { CSSProperties, HTMLAttributes, Key, ReactNode, Ref, useEffect, useImperativeHandle, useRef, useState } from "react"
6
- import { useSize } from "soda-hooks"
7
-
8
- import { px, transformCSSVariable } from "@/utils"
9
-
10
- export interface FlowSizeData {
11
- /** 容器宽度 */
12
- width: number
13
- /** 容器高度 */
14
- height: number
15
- /** 元素宽度 */
16
- itemWidth: number
17
- /** 元素高度 */
18
- itemHeight: number
19
- /** 列间距 */
20
- columnGap: number
21
- /** 列数 */
22
- columnCount: number
23
- /** 行间距 */
24
- rowGap: number
25
- /** 行数 */
26
- rowCount: number
27
- /** 元素格数 */
28
- itemCount: number
29
- /** 最大行数 */
30
- maxRows: number | null
31
- /** 是否有元素被隐藏 */
32
- overflow: boolean
33
- }
34
-
35
- export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
36
- /** 元素宽度 */
37
- itemWidth: number
38
- /** 元素高度 */
39
- itemHeight: number
40
- /**
41
- * 列间距
42
- * 1. 如果是数字,表示列间距是固定的
43
- * 2. 如果是 auto,表示会在尽可能放进更多列的情况下,列间距是平均的
44
- * 2. 如果是数组,表示列间距是区间的,第一个元素是最小值,第二个元素是最大值
45
- */
46
- columnGap?: number | "auto" | [number | "auto", number | "auto"]
47
- /** 行间距 */
48
- rowGap?: number
49
- gap?: number
50
- /** 最大行数 */
51
- maxRows?: number | null
52
- /** 源数据 */
53
- data?: T[]
54
- /** 渲染 */
55
- render: (item: T, index: number, arr: T[]) => ReactNode
56
- /** key释放器,默认为 index */
57
- keyExactor?: (item: T, index: number, arr: T[]) => Key
58
- /**
59
- * 渲染的元素由两层容器包裹,外层容器类名
60
- */
61
- wrapperClassName?: string
62
- /**
63
- * 渲染的元素由两层容器包裹,外层容器样式
64
- */
65
- wrapperStyle?: CSSProperties
66
- /**
67
- * 渲染的元素由两层容器包裹,内层容器类名
68
- */
69
- containerClassName?: string
70
- /**
71
- * 渲染的元素由两层容器包裹,内层容器样式
72
- */
73
- containerStyle?: CSSProperties
74
- /** 节流时间,单位毫秒,默认200ms,传入 0 不节流 */
75
- throttle?: number
76
- /** 动画时间,单位毫秒,默认400ms,传入 0 不展示动画 */
77
- transitionDuration?: number
78
- /** 变化的回调函数 */
79
- onSizeChange?: (sizeData: FlowSizeData) => void
80
- element?: Ref<HTMLDivElement>
81
- }
82
-
83
- export function getGapRange(gap?: undefined | number | "auto" | (number | "auto")[]): [number, number | "auto"] {
84
- if (typeof gap === "number") return [gap, gap]
85
- if (Array.isArray(gap)) return [typeof gap[0] === "number" ? gap[0] : 0, gap[1]]
86
- return [0, "auto"]
87
- }
88
-
89
- export interface GapAndCount {
90
- count: number
91
- gap: number
92
- }
93
-
94
- export function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | "auto"): GapAndCount {
95
- const count = Math.floor((width + minGap) / (itemWidth + minGap)) || 1
96
- if (count === 1) return { count, gap: 0 }
97
- const averageGap = (width - itemWidth * count) / (count - 1)
98
- if (averageGap < minGap) return { count, gap: minGap }
99
- if (maxGap !== "auto" && averageGap > maxGap) return { count, gap: maxGap }
100
- return { count, gap: averageGap }
101
- }
102
-
103
- export interface ManualFlowProps<T> extends FlowProps<T> {
104
- /** 组件宽度,必须指定 */
105
- width: number
106
- }
107
-
108
- /** 手动组件,由外界指定宽度,性能更好 */
109
- export function ManualFlow<T>(props: ManualFlowProps<T>) {
110
- let {
111
- itemWidth,
112
- itemHeight,
113
- columnGap,
114
- rowGap,
115
- maxRows,
116
- data = [],
117
- render,
118
- keyExactor,
119
- className,
120
- style,
121
- wrapperClassName,
122
- wrapperStyle,
123
- throttle,
124
- transitionDuration,
125
- onSizeChange,
126
- containerClassName,
127
- containerStyle,
128
- gap = 0,
129
- width,
130
- element,
131
- ...rest
132
- } = props
133
- rowGap ??= gap
134
- columnGap ??= gap
135
- const [minColumnGap, maxColumnGap] = getGapRange(columnGap)
136
- const [{ count: columnCount, gap: columnGapSize }, setGapAndCount] = useState(() => getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap))
137
- const ele = useRef<HTMLDivElement>(null)
138
- const contentRows = Math.ceil(data.length / columnCount)
139
- const contentShownRows = typeof maxRows === "number" ? Math.min(contentRows, maxRows) : contentRows
140
- const height = contentShownRows > 0 ? contentShownRows * (itemHeight + rowGap) - rowGap : 0
141
-
142
- function getPosition(index: number) {
143
- const y = Math.floor(index / columnCount)
144
- const x = index - y * columnCount
145
- return {
146
- left: x * (itemWidth + columnGapSize),
147
- top: y * (itemHeight + rowGap!),
148
- }
149
- }
150
-
151
- function getHidden(index: number) {
152
- if (typeof maxRows !== "number") return false
153
- return index >= maxRows * columnCount
154
- }
155
-
156
- useImperativeHandle(element, () => ele.current!, [ele.current])
157
-
158
- useEffect(() => {
159
- function task() {
160
- setGapAndCount(getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap))
161
- }
162
- if (throttle === 0) return task()
163
- const timeout = setTimeout(task, throttle || 200)
164
- return () => clearTimeout(timeout)
165
- }, [width, itemWidth, throttle, minColumnGap, maxColumnGap])
166
-
167
- useEffect(() => {
168
- onSizeChange?.({
169
- width,
170
- height,
171
- itemWidth,
172
- itemHeight,
173
- columnGap: columnGapSize,
174
- columnCount,
175
- rowGap: rowGap!,
176
- rowCount: contentShownRows,
177
- overflow: data.length > contentShownRows * columnCount,
178
- itemCount: data.length,
179
- maxRows: maxRows ?? null,
180
- })
181
- }, [width, height, columnGapSize, columnCount, rowGap, contentShownRows, data.length, itemWidth, itemHeight, maxRows])
182
-
183
- return (
184
- <div
185
- ref={ele}
186
- className={clsx(
187
- css`
188
- position: relative;
189
- height: var(--height);
190
- overflow: hidden;
191
- `,
192
- className,
193
- )}
194
- style={transformCSSVariable({ height: px(height) }, style)}
195
- {...rest}
196
- >
197
- {data.map((item, index, arr) => (
198
- <div
199
- key={keyExactor ? keyExactor(item, index, arr) : index}
200
- className={clsx(
201
- css`
202
- position: absolute;
203
- width: var(--width);
204
- height: var(--height);
205
- transition: var(--transition);
206
- left: 0;
207
- top: 0;
208
- transform: translate(var(--left), var(--top));
209
- `,
210
- wrapperClassName,
211
- )}
212
- style={transformCSSVariable(
213
- {
214
- width: px(itemWidth),
215
- height: px(itemHeight),
216
- transition: transitionDuration === 0 ? "none" : `all ${transitionDuration || 400}ms`,
217
- left: px(getPosition(index).left),
218
- top: px(getPosition(index).top),
219
- },
220
- wrapperStyle,
221
- )}
222
- >
223
- <div
224
- className={clsx(
225
- css`
226
- width: 100%;
227
- height: 100%;
228
- display: var(--display);
229
- `,
230
- containerClassName,
231
- )}
232
- style={transformCSSVariable({ display: getHidden(index) ? "none" : "block" }, containerStyle)}
233
- >
234
- {render(item, index, arr)}
235
- </div>
236
- </div>
237
- ))}
238
- </div>
239
- )
240
- }
241
-
242
- /** 自适应浮动组件 */
243
- export function Flow<T>(props: FlowProps<T>): ReactNode {
244
- const {
245
- itemWidth,
246
- itemHeight,
247
- columnGap,
248
- rowGap,
249
- gap,
250
- maxRows,
251
- data,
252
- render,
253
- keyExactor,
254
- wrapperClassName,
255
- wrapperStyle,
256
- containerClassName,
257
- containerStyle,
258
- throttle,
259
- transitionDuration,
260
- onSizeChange,
261
- element,
262
- ...rest
263
- } = props
264
- const ele = useRef<HTMLDivElement>(null)
265
- const size = useSize(ele)
266
- const width = useRef(size?.width || 0)
267
- if (size && size.width !== 0) width.current = size.width
268
- useImperativeHandle(element, () => ele.current!, [ele.current])
269
- if (width.current === 0) return <div ref={ele} {...rest} />
270
- return <ManualFlow element={ele} {...props} width={width.current} />
271
- }
1
+ "use client"
2
+
3
+ import { css } from "@emotion/css"
4
+ import { clsx } from "deepsea-tools"
5
+ import { CSSProperties, HTMLAttributes, Key, ReactNode, Ref, useEffect, useImperativeHandle, useRef, useState } from "react"
6
+ import { useSize } from "soda-hooks"
7
+
8
+ import { px, transformCSSVariable } from "@/utils"
9
+
10
+ export interface FlowSizeData {
11
+ /** 容器宽度 */
12
+ width: number
13
+ /** 容器高度 */
14
+ height: number
15
+ /** 元素宽度 */
16
+ itemWidth: number
17
+ /** 元素高度 */
18
+ itemHeight: number
19
+ /** 列间距 */
20
+ columnGap: number
21
+ /** 列数 */
22
+ columnCount: number
23
+ /** 行间距 */
24
+ rowGap: number
25
+ /** 行数 */
26
+ rowCount: number
27
+ /** 元素格数 */
28
+ itemCount: number
29
+ /** 最大行数 */
30
+ maxRows: number | null
31
+ /** 是否有元素被隐藏 */
32
+ overflow: boolean
33
+ }
34
+
35
+ export interface FlowProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
36
+ /** 元素宽度 */
37
+ itemWidth: number
38
+ /** 元素高度 */
39
+ itemHeight: number
40
+ /**
41
+ * 列间距
42
+ * 1. 如果是数字,表示列间距是固定的
43
+ * 2. 如果是 auto,表示会在尽可能放进更多列的情况下,列间距是平均的
44
+ * 2. 如果是数组,表示列间距是区间的,第一个元素是最小值,第二个元素是最大值
45
+ */
46
+ columnGap?: number | "auto" | [number | "auto", number | "auto"]
47
+ /** 行间距 */
48
+ rowGap?: number
49
+ gap?: number
50
+ /** 最大行数 */
51
+ maxRows?: number | null
52
+ /** 源数据 */
53
+ data?: T[]
54
+ /** 渲染 */
55
+ render: (item: T, index: number, arr: T[]) => ReactNode
56
+ /** key释放器,默认为 index */
57
+ keyExactor?: (item: T, index: number, arr: T[]) => Key
58
+ /**
59
+ * 渲染的元素由两层容器包裹,外层容器类名
60
+ */
61
+ wrapperClassName?: string
62
+ /**
63
+ * 渲染的元素由两层容器包裹,外层容器样式
64
+ */
65
+ wrapperStyle?: CSSProperties
66
+ /**
67
+ * 渲染的元素由两层容器包裹,内层容器类名
68
+ */
69
+ containerClassName?: string
70
+ /**
71
+ * 渲染的元素由两层容器包裹,内层容器样式
72
+ */
73
+ containerStyle?: CSSProperties
74
+ /** 节流时间,单位毫秒,默认200ms,传入 0 不节流 */
75
+ throttle?: number
76
+ /** 动画时间,单位毫秒,默认400ms,传入 0 不展示动画 */
77
+ transitionDuration?: number
78
+ /** 变化的回调函数 */
79
+ onSizeChange?: (sizeData: FlowSizeData) => void
80
+ element?: Ref<HTMLDivElement>
81
+ }
82
+
83
+ export function getGapRange(gap?: undefined | number | "auto" | (number | "auto")[]): [number, number | "auto"] {
84
+ if (typeof gap === "number") return [gap, gap]
85
+ if (Array.isArray(gap)) return [typeof gap[0] === "number" ? gap[0] : 0, gap[1]]
86
+ return [0, "auto"]
87
+ }
88
+
89
+ export interface GapAndCount {
90
+ count: number
91
+ gap: number
92
+ }
93
+
94
+ export function getGapCountAndSize(width: number, itemWidth: number, minGap: number, maxGap: number | "auto"): GapAndCount {
95
+ const count = Math.floor((width + minGap) / (itemWidth + minGap)) || 1
96
+ if (count === 1) return { count, gap: 0 }
97
+ const averageGap = (width - itemWidth * count) / (count - 1)
98
+ if (averageGap < minGap) return { count, gap: minGap }
99
+ if (maxGap !== "auto" && averageGap > maxGap) return { count, gap: maxGap }
100
+ return { count, gap: averageGap }
101
+ }
102
+
103
+ export interface ManualFlowProps<T> extends FlowProps<T> {
104
+ /** 组件宽度,必须指定 */
105
+ width: number
106
+ }
107
+
108
+ /** 手动组件,由外界指定宽度,性能更好 */
109
+ export function ManualFlow<T>(props: ManualFlowProps<T>) {
110
+ let {
111
+ itemWidth,
112
+ itemHeight,
113
+ columnGap,
114
+ rowGap,
115
+ maxRows,
116
+ data = [],
117
+ render,
118
+ keyExactor,
119
+ className,
120
+ style,
121
+ wrapperClassName,
122
+ wrapperStyle,
123
+ throttle,
124
+ transitionDuration,
125
+ onSizeChange,
126
+ containerClassName,
127
+ containerStyle,
128
+ gap = 0,
129
+ width,
130
+ element,
131
+ ...rest
132
+ } = props
133
+ rowGap ??= gap
134
+ columnGap ??= gap
135
+ const [minColumnGap, maxColumnGap] = getGapRange(columnGap)
136
+ const [{ count: columnCount, gap: columnGapSize }, setGapAndCount] = useState(() => getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap))
137
+ const ele = useRef<HTMLDivElement>(null)
138
+ const contentRows = Math.ceil(data.length / columnCount)
139
+ const contentShownRows = typeof maxRows === "number" ? Math.min(contentRows, maxRows) : contentRows
140
+ const height = contentShownRows > 0 ? contentShownRows * (itemHeight + rowGap) - rowGap : 0
141
+
142
+ function getPosition(index: number) {
143
+ const y = Math.floor(index / columnCount)
144
+ const x = index - y * columnCount
145
+ return {
146
+ left: x * (itemWidth + columnGapSize),
147
+ top: y * (itemHeight + rowGap!),
148
+ }
149
+ }
150
+
151
+ function getHidden(index: number) {
152
+ if (typeof maxRows !== "number") return false
153
+ return index >= maxRows * columnCount
154
+ }
155
+
156
+ useImperativeHandle(element, () => ele.current!, [ele.current])
157
+
158
+ useEffect(() => {
159
+ function task() {
160
+ setGapAndCount(getGapCountAndSize(width, itemWidth, minColumnGap, maxColumnGap))
161
+ }
162
+ if (throttle === 0) return task()
163
+ const timeout = setTimeout(task, throttle || 200)
164
+ return () => clearTimeout(timeout)
165
+ }, [width, itemWidth, throttle, minColumnGap, maxColumnGap])
166
+
167
+ useEffect(() => {
168
+ onSizeChange?.({
169
+ width,
170
+ height,
171
+ itemWidth,
172
+ itemHeight,
173
+ columnGap: columnGapSize,
174
+ columnCount,
175
+ rowGap: rowGap!,
176
+ rowCount: contentShownRows,
177
+ overflow: data.length > contentShownRows * columnCount,
178
+ itemCount: data.length,
179
+ maxRows: maxRows ?? null,
180
+ })
181
+ }, [width, height, columnGapSize, columnCount, rowGap, contentShownRows, data.length, itemWidth, itemHeight, maxRows])
182
+
183
+ return (
184
+ <div
185
+ ref={ele}
186
+ className={clsx(
187
+ css`
188
+ position: relative;
189
+ height: var(--height);
190
+ overflow: hidden;
191
+ `,
192
+ className,
193
+ )}
194
+ style={transformCSSVariable({ height: px(height) }, style)}
195
+ {...rest}
196
+ >
197
+ {data.map((item, index, arr) => (
198
+ <div
199
+ key={keyExactor ? keyExactor(item, index, arr) : index}
200
+ className={clsx(
201
+ css`
202
+ position: absolute;
203
+ width: var(--width);
204
+ height: var(--height);
205
+ transition: var(--transition);
206
+ left: 0;
207
+ top: 0;
208
+ transform: translate(var(--left), var(--top));
209
+ `,
210
+ wrapperClassName,
211
+ )}
212
+ style={transformCSSVariable(
213
+ {
214
+ width: px(itemWidth),
215
+ height: px(itemHeight),
216
+ transition: transitionDuration === 0 ? "none" : `all ${transitionDuration || 400}ms`,
217
+ left: px(getPosition(index).left),
218
+ top: px(getPosition(index).top),
219
+ },
220
+ wrapperStyle,
221
+ )}
222
+ >
223
+ <div
224
+ className={clsx(
225
+ css`
226
+ width: 100%;
227
+ height: 100%;
228
+ display: var(--display);
229
+ `,
230
+ containerClassName,
231
+ )}
232
+ style={transformCSSVariable({ display: getHidden(index) ? "none" : "block" }, containerStyle)}
233
+ >
234
+ {render(item, index, arr)}
235
+ </div>
236
+ </div>
237
+ ))}
238
+ </div>
239
+ )
240
+ }
241
+
242
+ /** 自适应浮动组件 */
243
+ export function Flow<T>(props: FlowProps<T>): ReactNode {
244
+ const {
245
+ itemWidth,
246
+ itemHeight,
247
+ columnGap,
248
+ rowGap,
249
+ gap,
250
+ maxRows,
251
+ data,
252
+ render,
253
+ keyExactor,
254
+ wrapperClassName,
255
+ wrapperStyle,
256
+ containerClassName,
257
+ containerStyle,
258
+ throttle,
259
+ transitionDuration,
260
+ onSizeChange,
261
+ element,
262
+ ...rest
263
+ } = props
264
+ const ele = useRef<HTMLDivElement>(null)
265
+ const size = useSize(ele)
266
+ const width = useRef(size?.width || 0)
267
+ if (size && size.width !== 0) width.current = size.width
268
+ useImperativeHandle(element, () => ele.current!, [ele.current])
269
+ if (width.current === 0) return <div ref={ele} {...rest} />
270
+ return <ManualFlow element={ele} {...props} width={width.current} />
271
+ }
@@ -1,41 +1,41 @@
1
- "use client"
2
-
3
- import { ComponentPropsWithoutRef, FC, Fragment, ReactNode, createContext, useContext } from "react"
4
-
5
- export interface FormLabelConfig {
6
- /**
7
- * Label 的宽度.
8
- */
9
- width?: number
10
- /**
11
- * 是否在 Label 前面添加一个空白区域,只有当前 Label 为非必选,而存在其他 Label 为必选的时候开启
12
- */
13
- before?: boolean | number
14
- }
15
-
16
- export interface FormLabelProps extends ComponentPropsWithoutRef<"div">, FormLabelConfig {}
17
-
18
- export const FormLabelConfigContext = createContext<Partial<FormLabelConfig>>({})
19
-
20
- export interface FormLabelConfigProviderProps extends FormLabelConfig {
21
- children?: ReactNode
22
- }
23
-
24
- export const FormLabelConfigProvider: FC<FormLabelConfigProviderProps> = ({ width, before, children }) => (
25
- <FormLabelConfigContext.Provider value={{ width, before }}>{children}</FormLabelConfigContext.Provider>
26
- )
27
-
28
- /**
29
- * 为 Ant Design 的 FormItem 设计的 Label 组件
30
- */
31
- export const FormLabel: FC<FormLabelProps> = props => {
32
- const { width: _width, before: _before } = useContext(FormLabelConfigContext)
33
- const { style, width = _width, before = _before, ...rest } = props
34
-
35
- return (
36
- <Fragment>
37
- {!!before && <div style={{ width: 11, color: "transparent", userSelect: "none" }}>&ensp;</div>}
38
- <div style={{ width, textAlign: "justify", textAlignLast: "justify", ...style }} {...rest} />
39
- </Fragment>
40
- )
41
- }
1
+ "use client"
2
+
3
+ import { ComponentPropsWithoutRef, FC, Fragment, ReactNode, createContext, useContext } from "react"
4
+
5
+ export interface FormLabelConfig {
6
+ /**
7
+ * Label 的宽度.
8
+ */
9
+ width?: number
10
+ /**
11
+ * 是否在 Label 前面添加一个空白区域,只有当前 Label 为非必选,而存在其他 Label 为必选的时候开启
12
+ */
13
+ before?: boolean | number
14
+ }
15
+
16
+ export interface FormLabelProps extends ComponentPropsWithoutRef<"div">, FormLabelConfig {}
17
+
18
+ export const FormLabelConfigContext = createContext<Partial<FormLabelConfig>>({})
19
+
20
+ export interface FormLabelConfigProviderProps extends FormLabelConfig {
21
+ children?: ReactNode
22
+ }
23
+
24
+ export const FormLabelConfigProvider: FC<FormLabelConfigProviderProps> = ({ width, before, children }) => (
25
+ <FormLabelConfigContext.Provider value={{ width, before }}>{children}</FormLabelConfigContext.Provider>
26
+ )
27
+
28
+ /**
29
+ * 为 Ant Design 的 FormItem 设计的 Label 组件
30
+ */
31
+ export const FormLabel: FC<FormLabelProps> = props => {
32
+ const { width: _width, before: _before } = useContext(FormLabelConfigContext)
33
+ const { style, width = _width, before = _before, ...rest } = props
34
+
35
+ return (
36
+ <Fragment>
37
+ {!!before && <div style={{ width: 11, color: "transparent", userSelect: "none" }}>&ensp;</div>}
38
+ <div style={{ width, textAlign: "justify", textAlignLast: "justify", ...style }} {...rest} />
39
+ </Fragment>
40
+ )
41
+ }