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,163 +1,163 @@
1
- "use client"
2
-
3
- import { css } from "@emotion/css"
4
- import { clsx } from "deepsea-tools"
5
- import { CSSProperties, ComponentPropsWithoutRef, MouseEvent as ReactMouseEvent, forwardRef, useEffect, useImperativeHandle, useRef } from "react"
6
- import { useSize } from "soda-hooks"
7
-
8
- export type InfiniteScrollProps = ComponentPropsWithoutRef<"div"> & {
9
- /**
10
- * 滚动的方向
11
- * @default "vertical"
12
- */
13
- direction?: "vertical" | "horizontal"
14
- /** 渲染 children 的容器的类名 */
15
- containerClassName?: string
16
- /** 渲染 children 的容器的样式 */
17
- containerStyle?: CSSProperties
18
- /**
19
- * 两个 children 容器之间的间距
20
- * @default 0
21
- */
22
- gap?: number
23
- /** 一个周期的时间,单位:毫秒 */
24
- duration: number
25
- /** 是否将 gap 的距离也加入 overflow 的计算 */
26
- withGap?: boolean
27
- /** 尺寸刚好相同时,是否视为溢出 */
28
- withEqual?: boolean
29
- /** 鼠标移入时,是否停止动画 */
30
- pauseOnHover?: boolean
31
- }
32
-
33
- /**
34
- * 无限滚动的组件
35
- * 子元素会内置的容器中被渲染两次,首尾相连,形成无限滚动的效果
36
- * 但是,如果内部检测到并没有溢出,那么不会渲染两次,并且没有动画
37
- */
38
- export const InfiniteScroll = forwardRef<HTMLDivElement, InfiniteScrollProps>((props, ref) => {
39
- const {
40
- className,
41
- direction = "vertical",
42
- children,
43
- containerClassName,
44
- containerStyle,
45
- gap = 0,
46
- duration,
47
- withGap,
48
- withEqual,
49
- pauseOnHover,
50
- onMouseEnter,
51
- onMouseLeave,
52
- ...rest
53
- } = props
54
-
55
- const wrapper = useRef<HTMLDivElement>(null)
56
- const wrapperSize = useSize(wrapper)
57
-
58
- const ele = useRef<HTMLDivElement>(null)
59
-
60
- useImperativeHandle(ref, () => wrapper.current as HTMLDivElement, [wrapper.current])
61
-
62
- const container = useRef<HTMLDivElement>(null)
63
- const containerSize = useSize(container)
64
-
65
- function bigger(containerSize: number, wrapperSize: number) {
66
- return withEqual ? containerSize + (withGap ? gap : 0) >= wrapperSize : containerSize + (withGap ? gap : 0) > wrapperSize
67
- }
68
-
69
- const overflow =
70
- wrapperSize && containerSize
71
- ? direction === "vertical"
72
- ? bigger(containerSize.height, wrapperSize.height)
73
- : bigger(containerSize.width, wrapperSize.width)
74
- : false
75
-
76
- const animation = useRef<Animation | undefined>(undefined)
77
-
78
- useEffect(() => {
79
- if (!wrapperSize || !containerSize || !overflow) return
80
- animation.current = ele.current?.animate(
81
- {
82
- transform:
83
- direction === "vertical"
84
- ? [`translateY(0)`, `translateY(-${containerSize.height + gap}px)`]
85
- : [`translateX(0)`, `translateX(-${containerSize.width + gap}px)`],
86
- },
87
- { duration, iterations: Infinity },
88
- )
89
- return () => animation.current?.cancel()
90
- }, [wrapperSize, containerSize, overflow, direction, duration])
91
-
92
- function enter(e: ReactMouseEvent<HTMLDivElement, MouseEvent>) {
93
- if (pauseOnHover) animation.current?.pause()
94
- onMouseEnter?.(e)
95
- }
96
-
97
- function leave(e: ReactMouseEvent<HTMLDivElement, MouseEvent>) {
98
- if (pauseOnHover) animation.current?.play()
99
- onMouseLeave?.(e)
100
- }
101
-
102
- useEffect(() => {
103
- if (!pauseOnHover && animation.current?.playState === "paused") animation.current?.play()
104
- }, [animation.current, pauseOnHover])
105
-
106
- return (
107
- <div
108
- ref={wrapper}
109
- className={clsx(
110
- css`
111
- position: relative;
112
- ${direction === "vertical" ? "overflow-y: hidden;" : "overflow-x: hidden;"}
113
- `,
114
- className,
115
- )}
116
- onMouseEnter={enter}
117
- onMouseLeave={leave}
118
- {...rest}
119
- >
120
- <div
121
- ref={ele}
122
- style={{
123
- position: "absolute",
124
- width: direction === "vertical" ? "100%" : containerSize && (overflow ? containerSize.width * 2 + gap : containerSize.width),
125
- height: direction === "horizontal" ? "100%" : containerSize && (overflow ? containerSize.height * 2 + gap : containerSize.width),
126
- }}
127
- >
128
- <div
129
- ref={container}
130
- className={clsx(
131
- css`
132
- position: absolute;
133
- left: 0;
134
- top: 0;
135
- ${direction === "vertical" ? "width: 100%;" : "height: 100%;"}
136
- `,
137
- containerClassName,
138
- )}
139
- style={containerStyle}
140
- >
141
- {children}
142
- </div>
143
- {overflow && (
144
- <div
145
- ref={container}
146
- className={clsx(
147
- css`
148
- position: absolute;
149
- right: 0;
150
- bottom: 0;
151
- ${direction === "vertical" ? "width: 100%;" : "height: 100%;"}
152
- `,
153
- containerClassName,
154
- )}
155
- style={containerStyle}
156
- >
157
- {children}
158
- </div>
159
- )}
160
- </div>
161
- </div>
162
- )
163
- })
1
+ "use client"
2
+
3
+ import { css } from "@emotion/css"
4
+ import { clsx } from "deepsea-tools"
5
+ import { CSSProperties, ComponentPropsWithoutRef, MouseEvent as ReactMouseEvent, forwardRef, useEffect, useImperativeHandle, useRef } from "react"
6
+ import { useSize } from "soda-hooks"
7
+
8
+ export type InfiniteScrollProps = ComponentPropsWithoutRef<"div"> & {
9
+ /**
10
+ * 滚动的方向
11
+ * @default "vertical"
12
+ */
13
+ direction?: "vertical" | "horizontal"
14
+ /** 渲染 children 的容器的类名 */
15
+ containerClassName?: string
16
+ /** 渲染 children 的容器的样式 */
17
+ containerStyle?: CSSProperties
18
+ /**
19
+ * 两个 children 容器之间的间距
20
+ * @default 0
21
+ */
22
+ gap?: number
23
+ /** 一个周期的时间,单位:毫秒 */
24
+ duration: number
25
+ /** 是否将 gap 的距离也加入 overflow 的计算 */
26
+ withGap?: boolean
27
+ /** 尺寸刚好相同时,是否视为溢出 */
28
+ withEqual?: boolean
29
+ /** 鼠标移入时,是否停止动画 */
30
+ pauseOnHover?: boolean
31
+ }
32
+
33
+ /**
34
+ * 无限滚动的组件
35
+ * 子元素会内置的容器中被渲染两次,首尾相连,形成无限滚动的效果
36
+ * 但是,如果内部检测到并没有溢出,那么不会渲染两次,并且没有动画
37
+ */
38
+ export const InfiniteScroll = forwardRef<HTMLDivElement, InfiniteScrollProps>((props, ref) => {
39
+ const {
40
+ className,
41
+ direction = "vertical",
42
+ children,
43
+ containerClassName,
44
+ containerStyle,
45
+ gap = 0,
46
+ duration,
47
+ withGap,
48
+ withEqual,
49
+ pauseOnHover,
50
+ onMouseEnter,
51
+ onMouseLeave,
52
+ ...rest
53
+ } = props
54
+
55
+ const wrapper = useRef<HTMLDivElement>(null)
56
+ const wrapperSize = useSize(wrapper)
57
+
58
+ const ele = useRef<HTMLDivElement>(null)
59
+
60
+ useImperativeHandle(ref, () => wrapper.current as HTMLDivElement, [wrapper.current])
61
+
62
+ const container = useRef<HTMLDivElement>(null)
63
+ const containerSize = useSize(container)
64
+
65
+ function bigger(containerSize: number, wrapperSize: number) {
66
+ return withEqual ? containerSize + (withGap ? gap : 0) >= wrapperSize : containerSize + (withGap ? gap : 0) > wrapperSize
67
+ }
68
+
69
+ const overflow =
70
+ wrapperSize && containerSize
71
+ ? direction === "vertical"
72
+ ? bigger(containerSize.height, wrapperSize.height)
73
+ : bigger(containerSize.width, wrapperSize.width)
74
+ : false
75
+
76
+ const animation = useRef<Animation | undefined>(undefined)
77
+
78
+ useEffect(() => {
79
+ if (!wrapperSize || !containerSize || !overflow) return
80
+ animation.current = ele.current?.animate(
81
+ {
82
+ transform:
83
+ direction === "vertical"
84
+ ? [`translateY(0)`, `translateY(-${containerSize.height + gap}px)`]
85
+ : [`translateX(0)`, `translateX(-${containerSize.width + gap}px)`],
86
+ },
87
+ { duration, iterations: Infinity },
88
+ )
89
+ return () => animation.current?.cancel()
90
+ }, [wrapperSize, containerSize, overflow, direction, duration])
91
+
92
+ function enter(e: ReactMouseEvent<HTMLDivElement, MouseEvent>) {
93
+ if (pauseOnHover) animation.current?.pause()
94
+ onMouseEnter?.(e)
95
+ }
96
+
97
+ function leave(e: ReactMouseEvent<HTMLDivElement, MouseEvent>) {
98
+ if (pauseOnHover) animation.current?.play()
99
+ onMouseLeave?.(e)
100
+ }
101
+
102
+ useEffect(() => {
103
+ if (!pauseOnHover && animation.current?.playState === "paused") animation.current?.play()
104
+ }, [animation.current, pauseOnHover])
105
+
106
+ return (
107
+ <div
108
+ ref={wrapper}
109
+ className={clsx(
110
+ css`
111
+ position: relative;
112
+ ${direction === "vertical" ? "overflow-y: hidden;" : "overflow-x: hidden;"}
113
+ `,
114
+ className,
115
+ )}
116
+ onMouseEnter={enter}
117
+ onMouseLeave={leave}
118
+ {...rest}
119
+ >
120
+ <div
121
+ ref={ele}
122
+ style={{
123
+ position: "absolute",
124
+ width: direction === "vertical" ? "100%" : containerSize && (overflow ? containerSize.width * 2 + gap : containerSize.width),
125
+ height: direction === "horizontal" ? "100%" : containerSize && (overflow ? containerSize.height * 2 + gap : containerSize.width),
126
+ }}
127
+ >
128
+ <div
129
+ ref={container}
130
+ className={clsx(
131
+ css`
132
+ position: absolute;
133
+ left: 0;
134
+ top: 0;
135
+ ${direction === "vertical" ? "width: 100%;" : "height: 100%;"}
136
+ `,
137
+ containerClassName,
138
+ )}
139
+ style={containerStyle}
140
+ >
141
+ {children}
142
+ </div>
143
+ {overflow && (
144
+ <div
145
+ ref={container}
146
+ className={clsx(
147
+ css`
148
+ position: absolute;
149
+ right: 0;
150
+ bottom: 0;
151
+ ${direction === "vertical" ? "width: 100%;" : "height: 100%;"}
152
+ `,
153
+ containerClassName,
154
+ )}
155
+ style={containerStyle}
156
+ >
157
+ {children}
158
+ </div>
159
+ )}
160
+ </div>
161
+ </div>
162
+ )
163
+ })
@@ -1,93 +1,93 @@
1
- "use client"
2
-
3
- import { ChangeEvent, ComponentProps, ReactNode, useState } from "react"
4
-
5
- export interface InputFileDataTypeMap {
6
- base64: string
7
- text: string
8
- arrayBuffer: ArrayBuffer
9
- binary: string
10
- file: File
11
- }
12
-
13
- export type InputFileDataType = keyof InputFileDataTypeMap
14
-
15
- export async function getFileData<T extends InputFileDataType>(file: File, type: T): Promise<InputFileDataTypeMap[T]> {
16
- const fileReader = new FileReader()
17
- switch (type) {
18
- case "arrayBuffer":
19
- fileReader.readAsArrayBuffer(file)
20
- break
21
- case "binary":
22
- fileReader.readAsBinaryString(file)
23
- break
24
- case "base64":
25
- fileReader.readAsDataURL(file)
26
- break
27
- case "text":
28
- fileReader.readAsText(file)
29
- break
30
- default:
31
- return file as any
32
- }
33
- return new Promise(resolve => {
34
- fileReader.addEventListener("load", () => {
35
- resolve(fileReader.result as any)
36
- })
37
- })
38
- }
39
-
40
- export interface InputFileBaseProps extends Omit<ComponentProps<"input">, "multiple" | "type"> {}
41
-
42
- export type FileType<Multiple extends boolean> = Multiple extends true ? File[] : File
43
- export type ValueType<Multiple extends boolean, Type extends InputFileDataType> = Multiple extends true
44
- ? InputFileDataTypeMap[Type][]
45
- : InputFileDataTypeMap[Type]
46
-
47
- export interface InputFileExtraProps<Multiple extends boolean = false, Type extends InputFileDataType = "file"> {
48
- multiple?: Multiple
49
- type?: Type
50
- onValueChange?: (data: ValueType<Multiple, Type>) => void
51
- onFileChange?: (data: FileType<Multiple>) => void
52
- /** 是否在捕获文件后清除 input 上的文件,默认为 false,主要区别在于如果不清除,连续两次选择同样的文件不会触发 onChange 事件,如果用于 form 表单,请设置为 flase */
53
- clearAfterChange?: boolean
54
- }
55
-
56
- export interface InputFileProps<Multiple extends boolean = false, Type extends InputFileDataType = "file">
57
- extends InputFileBaseProps,
58
- InputFileExtraProps<Multiple, Type> {}
59
-
60
- /** 专用于读取文件的组件 */
61
- export function InputFile<Multiple extends boolean = false, Type extends InputFileDataType = "file">(props: InputFileProps<Multiple, Type>): ReactNode {
62
- const { multiple = false, type = "file", onChange: _onChange, disabled: _disabled, clearAfterChange, onValueChange, onFileChange, ...rest } = props
63
- const [disabled, setDisabled] = useState(false)
64
-
65
- async function onChange(e: ChangeEvent<HTMLInputElement>) {
66
- _onChange?.(e)
67
- const input = e.target
68
- const { files } = input
69
- if (!files || files.length === 0) return
70
- setDisabled(true)
71
- try {
72
- if (multiple) {
73
- const files2: File[] = Array.from(files)
74
- const values: InputFileDataTypeMap[Type][] = []
75
- for (const file of files2) {
76
- const value = (await getFileData(file, type)) as InputFileDataTypeMap[Type]
77
- values.push(value)
78
- }
79
- onFileChange?.(files2 as FileType<Multiple>)
80
- onValueChange?.(values as ValueType<Multiple, Type>)
81
- } else {
82
- const file = files[0]
83
- onFileChange?.(file as FileType<Multiple>)
84
- onValueChange?.((await getFileData(file, type)) as ValueType<Multiple, Type>)
85
- }
86
- } finally {
87
- if (clearAfterChange) input.value = ""
88
- setDisabled(false)
89
- }
90
- }
91
-
92
- return <input disabled={disabled || _disabled} type="file" multiple={multiple} onChange={onChange} {...rest} />
93
- }
1
+ "use client"
2
+
3
+ import { ChangeEvent, ComponentProps, ReactNode, useState } from "react"
4
+
5
+ export interface InputFileDataTypeMap {
6
+ base64: string
7
+ text: string
8
+ arrayBuffer: ArrayBuffer
9
+ binary: string
10
+ file: File
11
+ }
12
+
13
+ export type InputFileDataType = keyof InputFileDataTypeMap
14
+
15
+ export async function getFileData<T extends InputFileDataType>(file: File, type: T): Promise<InputFileDataTypeMap[T]> {
16
+ const fileReader = new FileReader()
17
+ switch (type) {
18
+ case "arrayBuffer":
19
+ fileReader.readAsArrayBuffer(file)
20
+ break
21
+ case "binary":
22
+ fileReader.readAsBinaryString(file)
23
+ break
24
+ case "base64":
25
+ fileReader.readAsDataURL(file)
26
+ break
27
+ case "text":
28
+ fileReader.readAsText(file)
29
+ break
30
+ default:
31
+ return file as any
32
+ }
33
+ return new Promise(resolve => {
34
+ fileReader.addEventListener("load", () => {
35
+ resolve(fileReader.result as any)
36
+ })
37
+ })
38
+ }
39
+
40
+ export interface InputFileBaseProps extends Omit<ComponentProps<"input">, "multiple" | "type"> {}
41
+
42
+ export type FileType<Multiple extends boolean> = Multiple extends true ? File[] : File
43
+ export type ValueType<Multiple extends boolean, Type extends InputFileDataType> = Multiple extends true
44
+ ? InputFileDataTypeMap[Type][]
45
+ : InputFileDataTypeMap[Type]
46
+
47
+ export interface InputFileExtraProps<Multiple extends boolean = false, Type extends InputFileDataType = "file"> {
48
+ multiple?: Multiple
49
+ type?: Type
50
+ onValueChange?: (data: ValueType<Multiple, Type>) => void
51
+ onFileChange?: (data: FileType<Multiple>) => void
52
+ /** 是否在捕获文件后清除 input 上的文件,默认为 false,主要区别在于如果不清除,连续两次选择同样的文件不会触发 onChange 事件,如果用于 form 表单,请设置为 flase */
53
+ clearAfterChange?: boolean
54
+ }
55
+
56
+ export interface InputFileProps<Multiple extends boolean = false, Type extends InputFileDataType = "file">
57
+ extends InputFileBaseProps,
58
+ InputFileExtraProps<Multiple, Type> {}
59
+
60
+ /** 专用于读取文件的组件 */
61
+ export function InputFile<Multiple extends boolean = false, Type extends InputFileDataType = "file">(props: InputFileProps<Multiple, Type>): ReactNode {
62
+ const { multiple = false, type = "file", onChange: _onChange, disabled: _disabled, clearAfterChange, onValueChange, onFileChange, ...rest } = props
63
+ const [disabled, setDisabled] = useState(false)
64
+
65
+ async function onChange(e: ChangeEvent<HTMLInputElement>) {
66
+ _onChange?.(e)
67
+ const input = e.target
68
+ const { files } = input
69
+ if (!files || files.length === 0) return
70
+ setDisabled(true)
71
+ try {
72
+ if (multiple) {
73
+ const files2: File[] = Array.from(files)
74
+ const values: InputFileDataTypeMap[Type][] = []
75
+ for (const file of files2) {
76
+ const value = (await getFileData(file, type)) as InputFileDataTypeMap[Type]
77
+ values.push(value)
78
+ }
79
+ onFileChange?.(files2 as FileType<Multiple>)
80
+ onValueChange?.(values as ValueType<Multiple, Type>)
81
+ } else {
82
+ const file = files[0]
83
+ onFileChange?.(file as FileType<Multiple>)
84
+ onValueChange?.((await getFileData(file, type)) as ValueType<Multiple, Type>)
85
+ }
86
+ } finally {
87
+ if (clearAfterChange) input.value = ""
88
+ setDisabled(false)
89
+ }
90
+ }
91
+
92
+ return <input disabled={disabled || _disabled} type="file" multiple={multiple} onChange={onChange} {...rest} />
93
+ }