deepsea-components 5.15.23 → 5.15.25

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 (76) hide show
  1. package/README.md +23 -23
  2. package/dist/components/AutoFit.cjs +6 -6
  3. package/dist/components/AutoFit.js +29 -29
  4. package/dist/components/AutoScroll.cjs +7 -7
  5. package/dist/components/AutoScroll.js +30 -30
  6. package/dist/components/AutoSizeTextarea.cjs +4 -4
  7. package/dist/components/AutoSizeTextarea.js +17 -17
  8. package/dist/components/CircleText.js +4 -4
  9. package/dist/components/CopyButton.cjs +2 -2
  10. package/dist/components/CopyButton.js +13 -14
  11. package/dist/components/Echart.cjs +2 -2
  12. package/dist/components/Echart.js +12 -12
  13. package/dist/components/Flow.cjs +19 -19
  14. package/dist/components/Flow.js +44 -44
  15. package/dist/components/FormLabel.cjs +2 -2
  16. package/dist/components/FormLabel.js +8 -8
  17. package/dist/components/HlsPlayer.js +10 -10
  18. package/dist/components/IconFileType.cjs +4 -4
  19. package/dist/components/IconFileType.js +9 -9
  20. package/dist/components/InfiniteScroll.cjs +13 -13
  21. package/dist/components/InfiniteScroll.js +32 -32
  22. package/dist/components/InputFile.js +4 -4
  23. package/dist/components/InputFileButton.js +11 -11
  24. package/dist/components/LoopSwiper.cjs +33 -33
  25. package/dist/components/LoopSwiper.js +47 -47
  26. package/dist/components/ReadExcel.js +2 -2
  27. package/dist/components/ReadSheet.js +5 -5
  28. package/dist/components/Ring.js +4 -4
  29. package/dist/components/Scroll.cjs +15 -15
  30. package/dist/components/Scroll.js +32 -33
  31. package/dist/components/ScrollMask.js +13 -13
  32. package/dist/components/SectionRing.js +6 -6
  33. package/dist/components/Skeleton.cjs +17 -17
  34. package/dist/components/Skeleton.js +23 -23
  35. package/dist/components/Title.js +12 -12
  36. package/dist/components/TransitionBox.js +10 -10
  37. package/dist/components/TransitionNum.js +11 -11
  38. package/dist/components/Trapezium.cjs +4 -4
  39. package/dist/components/Trapezium.js +14 -14
  40. package/dist/components/Unify.js +10 -10
  41. package/dist/components/WriteExcel.js +2 -2
  42. package/dist/components/WriteSheet.js +4 -4
  43. package/dist/utils/getReactVersion.js +2 -2
  44. package/package.json +5 -5
  45. package/src/components/AutoFit.tsx +104 -104
  46. package/src/components/AutoScroll.tsx +150 -150
  47. package/src/components/AutoSizeTextarea.tsx +50 -50
  48. package/src/components/CircleText.tsx +81 -81
  49. package/src/components/CopyButton.tsx +31 -31
  50. package/src/components/Echart.tsx +69 -69
  51. package/src/components/Flow.tsx +271 -271
  52. package/src/components/FormLabel.tsx +41 -41
  53. package/src/components/HlsPlayer.tsx +34 -34
  54. package/src/components/IconFileType.tsx +162 -162
  55. package/src/components/InfiniteScroll.tsx +163 -163
  56. package/src/components/InputFile.tsx +93 -93
  57. package/src/components/InputFileButton.tsx +122 -122
  58. package/src/components/LoopSwiper.tsx +125 -125
  59. package/src/components/ReadExcel.tsx +13 -13
  60. package/src/components/ReadSheet.tsx +17 -17
  61. package/src/components/Ring.tsx +30 -30
  62. package/src/components/Scroll.tsx +97 -97
  63. package/src/components/ScrollMask.module.css +87 -87
  64. package/src/components/ScrollMask.tsx +68 -68
  65. package/src/components/SectionRing.tsx +40 -40
  66. package/src/components/Skeleton.tsx +45 -45
  67. package/src/components/Title.tsx +27 -27
  68. package/src/components/TransitionBox.tsx +44 -44
  69. package/src/components/TransitionNum.tsx +54 -54
  70. package/src/components/Trapezium.tsx +60 -60
  71. package/src/components/Unify.tsx +38 -38
  72. package/src/components/WriteExcel.tsx +13 -13
  73. package/src/components/WriteSheet.tsx +25 -25
  74. package/src/utils/getReactVersion.ts +7 -7
  75. package/src/utils/index.ts +33 -33
  76. package/tsconfig.json +16 -16
@@ -1,10 +1,10 @@
1
1
  "use client"
2
- import * as __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__ from "react/jsx-runtime";
3
- import * as __WEBPACK_EXTERNAL_MODULE__emotion_css_bfcd1b5d__ from "@emotion/css";
4
- import * as __WEBPACK_EXTERNAL_MODULE_deepsea_tools_8ecdf5a5__ from "deepsea-tools";
5
- import * as __WEBPACK_EXTERNAL_MODULE_react__ from "react";
6
- import * as __WEBPACK_EXTERNAL_MODULE__utils_index_js_6619c453__ from "../utils/index.js";
7
- const Trapezium = /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react__.forwardRef)((props, ref)=>{
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { css } from "@emotion/css";
4
+ import { clsx } from "deepsea-tools";
5
+ import { forwardRef } from "react";
6
+ import { px, transformCSSVariable } from "../utils/index.js";
7
+ const Trapezium = /*#__PURE__*/ forwardRef((props, ref)=>{
8
8
  const { top, bottom, height, borderRadius, className, style, ...rest } = props;
9
9
  const diff = (bottom - top) / 2;
10
10
  const a = Math.atan(height / diff) / 2;
@@ -15,16 +15,16 @@ const Trapezium = /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react__.forwardRef
15
15
  const f = borderRadius / Math.tan(e);
16
16
  const g = f * Math.cos(2 * a);
17
17
  const h = f * Math.sin(2 * a);
18
- return /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("div", {
18
+ return /*#__PURE__*/ jsx("div", {
19
19
  ref: ref,
20
- className: (0, __WEBPACK_EXTERNAL_MODULE_deepsea_tools_8ecdf5a5__.clsx)((0, __WEBPACK_EXTERNAL_MODULE__emotion_css_bfcd1b5d__.css)`
21
- width: var(--width);
22
- height: var(--height);
23
- clip-path: var(--clip-path);
20
+ className: clsx(css`
21
+ width: var(--width);
22
+ height: var(--height);
23
+ clip-path: var(--clip-path);
24
24
  `, className),
25
- style: (0, __WEBPACK_EXTERNAL_MODULE__utils_index_js_6619c453__.transformCSSVariable)({
26
- width: (0, __WEBPACK_EXTERNAL_MODULE__utils_index_js_6619c453__.px)(bottom),
27
- height: (0, __WEBPACK_EXTERNAL_MODULE__utils_index_js_6619c453__.px)(height),
25
+ style: transformCSSVariable({
26
+ width: px(bottom),
27
+ height: px(height),
28
28
  clipath: `path("M ${diff + f} 0 A ${borderRadius} ${borderRadius} 0 0 0 ${diff - g} ${h} L ${c} ${height - d} A ${borderRadius} ${borderRadius} 0 0 0 ${b} ${height} L ${bottom - b} ${height} A ${borderRadius} ${borderRadius} 0 0 0 ${bottom - c} ${height - d} L ${top + diff + g} ${h} A ${borderRadius} ${borderRadius} 0 0 0 ${top + diff - f} 0 Z")`
29
29
  }, style),
30
30
  ...rest
@@ -1,13 +1,13 @@
1
1
  "use client"
2
- import * as __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__ from "react/jsx-runtime";
3
- import * as __WEBPACK_EXTERNAL_MODULE_deepsea_tools_8ecdf5a5__ from "deepsea-tools";
4
- import * as __WEBPACK_EXTERNAL_MODULE_react__ from "react";
5
- const UnifyConfigContext = /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react__.createContext)({});
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { clsx } from "deepsea-tools";
4
+ import { createContext, createElement, useContext } from "react";
5
+ const UnifyConfigContext = /*#__PURE__*/ createContext({});
6
6
  const UnifyConfigProvider = ({ className, style, children })=>{
7
- const { className: _className, style: _style } = (0, __WEBPACK_EXTERNAL_MODULE_react__.useContext)(UnifyConfigContext);
8
- return /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(UnifyConfigContext.Provider, {
7
+ const { className: _className, style: _style } = useContext(UnifyConfigContext);
8
+ return /*#__PURE__*/ jsx(UnifyConfigContext.Provider, {
9
9
  value: {
10
- className: (0, __WEBPACK_EXTERNAL_MODULE_deepsea_tools_8ecdf5a5__.clsx)(_className, className),
10
+ className: clsx(_className, className),
11
11
  style: {
12
12
  ..._style,
13
13
  ...style
@@ -18,9 +18,9 @@ const UnifyConfigProvider = ({ className, style, children })=>{
18
18
  };
19
19
  function Unify(props) {
20
20
  const { as = "div", className, style, ...rest } = props;
21
- const { className: _className, style: _style } = (0, __WEBPACK_EXTERNAL_MODULE_react__.useContext)(UnifyConfigContext);
22
- return /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react__.createElement)(as, {
23
- className: (0, __WEBPACK_EXTERNAL_MODULE_deepsea_tools_8ecdf5a5__.clsx)(_className, className),
21
+ const { className: _className, style: _style } = useContext(UnifyConfigContext);
22
+ return /*#__PURE__*/ createElement(as, {
23
+ className: clsx(_className, className),
24
24
  style: {
25
25
  ..._style,
26
26
  ...style
@@ -1,4 +1,4 @@
1
1
  "use client"
2
- import * as __WEBPACK_EXTERNAL_MODULE__WriteSheet_js_e86d0e28__ from "./WriteSheet.js";
3
- const WriteExcel = __WEBPACK_EXTERNAL_MODULE__WriteSheet_js_e86d0e28__.WriteSheet;
2
+ import { WriteSheet } from "./WriteSheet.js";
3
+ const WriteExcel = WriteSheet;
4
4
  export { WriteExcel };
@@ -1,14 +1,14 @@
1
1
  "use client"
2
- import * as __WEBPACK_EXTERNAL_MODULE_deepsea_tools_8ecdf5a5__ from "deepsea-tools";
3
- import * as __WEBPACK_EXTERNAL_MODULE_react__ from "react";
2
+ import { writeSheet } from "deepsea-tools";
3
+ import { createElement } from "react";
4
4
  function WriteSheet(props) {
5
5
  const { as, excel, onClick: _onClick, ...rest } = props;
6
6
  function onClick(e) {
7
7
  _onClick?.(e);
8
8
  if (!excel) return;
9
- (0, __WEBPACK_EXTERNAL_MODULE_deepsea_tools_8ecdf5a5__.writeSheet)(excel);
9
+ writeSheet(excel);
10
10
  }
11
- return /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react__.createElement)(as ?? "button", {
11
+ return /*#__PURE__*/ createElement(as ?? "button", {
12
12
  onClick,
13
13
  ...rest
14
14
  });
@@ -1,6 +1,6 @@
1
- import * as __WEBPACK_EXTERNAL_MODULE_react__ from "react";
1
+ import { version } from "react";
2
2
  const reg = /(\d+)\.(\d+)\.(\d+)/;
3
3
  function getReactVersion() {
4
- return __WEBPACK_EXTERNAL_MODULE_react__.version.match(reg).slice(1).map(Number);
4
+ return version.match(reg).slice(1).map(Number);
5
5
  }
6
6
  export { getReactVersion };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepsea-components",
3
- "version": "5.15.23",
3
+ "version": "5.15.25",
4
4
  "description": "格数科技自用组件库",
5
5
  "type": "module",
6
6
  "exports": {
@@ -38,13 +38,13 @@
38
38
  "@emotion/css": "^11.13.5",
39
39
  "clipboard": "^2.0.11",
40
40
  "echarts": "^5.6.0",
41
- "hls.js": "^1.6.7",
41
+ "hls.js": "^1.6.9",
42
42
  "smooth-scrollbar": "^8.8.4",
43
- "deepsea-tools": "5.40.3",
44
- "soda-hooks": "6.12.6"
43
+ "deepsea-tools": "5.40.4",
44
+ "soda-hooks": "6.13.0"
45
45
  },
46
46
  "devDependencies": {
47
- "typescript": "^5.8.3"
47
+ "typescript": "^5.9.2"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "@types/node": ">=20",
@@ -1,104 +1,104 @@
1
- "use client"
2
-
3
- import { css } from "@emotion/css"
4
- import { clsx } from "deepsea-tools"
5
- import { HTMLAttributes, forwardRef, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from "react"
6
-
7
- import { px, transformCSSVariable } from "@/utils"
8
-
9
- export interface AutoFitProps extends HTMLAttributes<HTMLDivElement> {
10
- /** 设计稿宽度,默认 1920 */
11
- width?: number
12
- /** 设计稿高度,默认 1080 */
13
- height?: number
14
- /**
15
- * 在哪些方向进行缩放,默认缩放所有方向
16
- * 1. 水平方向是指,宽度按照设计稿进行占满,高度反向缩放
17
- * 2. 垂直方向是指,高度按照设计稿进行占满,宽度反向缩放
18
- * 3. 默认是水平和垂直方向都进行缩放,类似于 background-size: contain 的效果
19
- */
20
- direction?: "horizontal" | "vertical" | "both"
21
- }
22
-
23
- /**
24
- * 自适应缩放组件
25
- *
26
- * 注意:
27
- * 1. 父元素必须设置非 static 定位方式
28
- * 2. 父元素只能有且仅有一个子元素,那就是 AutoFit
29
- * 3. 不要设置 AutoFit 的 position、left、top、transform、width、height 属性
30
- * 4. 在第一次完成缩放前,无论 props 是什么,返回的都是 <div style={{ display: "none" }} />
31
- * 5. 元素的属性、事件、资源并不是立即加载的,会有一帧的延迟,在第一次完成缩放后才会显示
32
- */
33
- export const AutoFit = forwardRef<HTMLDivElement, AutoFitProps>((props, ref) => {
34
- const { width: designWidth = 1920, height: designHeight = 1080, direction, className, style, ...rest } = props
35
- const ele = useRef<HTMLDivElement>(null)
36
- const [show, setShow] = useState(false)
37
- const [transform, setTransform] = useState<string | undefined>(undefined)
38
- const [width, setWidth] = useState<string | undefined>(undefined)
39
- const [height, setHeight] = useState<string | undefined>(undefined)
40
-
41
- useImperativeHandle(ref, () => ele.current!, [ele.current])
42
- useLayoutEffect(() => {
43
- const element = ele.current
44
- const parent = element?.parentElement
45
- if (!element || !parent) return
46
- function listener(entries: ResizeObserverEntry[]) {
47
- const entry = entries[0]
48
- const { contentRect } = entry
49
- if (direction === "horizontal") {
50
- const scale = contentRect.width / designWidth
51
- setTransform(`scale(${scale})`)
52
- setWidth(px(designWidth))
53
- setHeight(px(contentRect.height / scale))
54
- } else if (direction === "vertical") {
55
- const scale = contentRect.height / designHeight
56
- setTransform(`scale(${scale})`)
57
- setWidth(px(contentRect.width / scale))
58
- setHeight(px(designHeight))
59
- } else {
60
- const scale = Math.min(contentRect.width / designWidth, contentRect.height / designHeight)
61
- setTransform(
62
- `translateX(${(contentRect.width - designWidth * scale) / 2}px) translateY(${(contentRect.height - designHeight * scale) / 2}px) scale(${scale})`,
63
- )
64
- setWidth(px(designWidth))
65
- setHeight(px(designHeight))
66
- }
67
- setShow(true)
68
- }
69
- const observer = new ResizeObserver(listener)
70
- observer.observe(parent)
71
- return () => observer.disconnect()
72
- }, [ele.current?.parentElement, designWidth, designHeight, direction])
73
-
74
- if (process.env.NODE_ENV === "development") {
75
- useEffect(() => {
76
- const parent = ele.current?.parentElement
77
- if (!parent) return
78
- const style = getComputedStyle(parent)
79
- if (style.position === "static") {
80
- console.warn("AutoFit 组件的父元素的 position 属性不应该是 static")
81
- }
82
- }, [ele.current?.parentElement])
83
- }
84
-
85
- if (!show) return <div ref={ele} style={{ display: "none" }} />
86
-
87
- return (
88
- <div
89
- ref={ele}
90
- className={clsx(
91
- css`
92
- position: absolute;
93
- transform: var(--transform);
94
- transform-origin: top left;
95
- width: var(--width);
96
- height: var(--height);
97
- `,
98
- className,
99
- )}
100
- style={transformCSSVariable({ transform, width, height }, style)}
101
- {...rest}
102
- />
103
- )
104
- })
1
+ "use client"
2
+
3
+ import { css } from "@emotion/css"
4
+ import { clsx } from "deepsea-tools"
5
+ import { HTMLAttributes, forwardRef, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from "react"
6
+
7
+ import { px, transformCSSVariable } from "@/utils"
8
+
9
+ export interface AutoFitProps extends HTMLAttributes<HTMLDivElement> {
10
+ /** 设计稿宽度,默认 1920 */
11
+ width?: number
12
+ /** 设计稿高度,默认 1080 */
13
+ height?: number
14
+ /**
15
+ * 在哪些方向进行缩放,默认缩放所有方向
16
+ * 1. 水平方向是指,宽度按照设计稿进行占满,高度反向缩放
17
+ * 2. 垂直方向是指,高度按照设计稿进行占满,宽度反向缩放
18
+ * 3. 默认是水平和垂直方向都进行缩放,类似于 background-size: contain 的效果
19
+ */
20
+ direction?: "horizontal" | "vertical" | "both"
21
+ }
22
+
23
+ /**
24
+ * 自适应缩放组件
25
+ *
26
+ * 注意:
27
+ * 1. 父元素必须设置非 static 定位方式
28
+ * 2. 父元素只能有且仅有一个子元素,那就是 AutoFit
29
+ * 3. 不要设置 AutoFit 的 position、left、top、transform、width、height 属性
30
+ * 4. 在第一次完成缩放前,无论 props 是什么,返回的都是 <div style={{ display: "none" }} />
31
+ * 5. 元素的属性、事件、资源并不是立即加载的,会有一帧的延迟,在第一次完成缩放后才会显示
32
+ */
33
+ export const AutoFit = forwardRef<HTMLDivElement, AutoFitProps>((props, ref) => {
34
+ const { width: designWidth = 1920, height: designHeight = 1080, direction, className, style, ...rest } = props
35
+ const ele = useRef<HTMLDivElement>(null)
36
+ const [show, setShow] = useState(false)
37
+ const [transform, setTransform] = useState<string | undefined>(undefined)
38
+ const [width, setWidth] = useState<string | undefined>(undefined)
39
+ const [height, setHeight] = useState<string | undefined>(undefined)
40
+
41
+ useImperativeHandle(ref, () => ele.current!, [ele.current])
42
+ useLayoutEffect(() => {
43
+ const element = ele.current
44
+ const parent = element?.parentElement
45
+ if (!element || !parent) return
46
+ function listener(entries: ResizeObserverEntry[]) {
47
+ const entry = entries[0]
48
+ const { contentRect } = entry
49
+ if (direction === "horizontal") {
50
+ const scale = contentRect.width / designWidth
51
+ setTransform(`scale(${scale})`)
52
+ setWidth(px(designWidth))
53
+ setHeight(px(contentRect.height / scale))
54
+ } else if (direction === "vertical") {
55
+ const scale = contentRect.height / designHeight
56
+ setTransform(`scale(${scale})`)
57
+ setWidth(px(contentRect.width / scale))
58
+ setHeight(px(designHeight))
59
+ } else {
60
+ const scale = Math.min(contentRect.width / designWidth, contentRect.height / designHeight)
61
+ setTransform(
62
+ `translateX(${(contentRect.width - designWidth * scale) / 2}px) translateY(${(contentRect.height - designHeight * scale) / 2}px) scale(${scale})`,
63
+ )
64
+ setWidth(px(designWidth))
65
+ setHeight(px(designHeight))
66
+ }
67
+ setShow(true)
68
+ }
69
+ const observer = new ResizeObserver(listener)
70
+ observer.observe(parent)
71
+ return () => observer.disconnect()
72
+ }, [ele.current?.parentElement, designWidth, designHeight, direction])
73
+
74
+ if (process.env.NODE_ENV === "development") {
75
+ useEffect(() => {
76
+ const parent = ele.current?.parentElement
77
+ if (!parent) return
78
+ const style = getComputedStyle(parent)
79
+ if (style.position === "static") {
80
+ console.warn("AutoFit 组件的父元素的 position 属性不应该是 static")
81
+ }
82
+ }, [ele.current?.parentElement])
83
+ }
84
+
85
+ if (!show) return <div ref={ele} style={{ display: "none" }} />
86
+
87
+ return (
88
+ <div
89
+ ref={ele}
90
+ className={clsx(
91
+ css`
92
+ position: absolute;
93
+ transform: var(--transform);
94
+ transform-origin: top left;
95
+ width: var(--width);
96
+ height: var(--height);
97
+ `,
98
+ className,
99
+ )}
100
+ style={transformCSSVariable({ transform, width, height }, style)}
101
+ {...rest}
102
+ />
103
+ )
104
+ })
@@ -1,150 +1,150 @@
1
- "use client"
2
-
3
- import { css } from "@emotion/css"
4
- import { clsx, getArray } from "deepsea-tools"
5
- import { CSSProperties, MouseEvent as ReactMouseEvent, forwardRef, useEffect, useImperativeHandle, useRef } from "react"
6
- import Scrollbar from "smooth-scrollbar"
7
- import { ScrollStatus } from "smooth-scrollbar/interfaces/scrollbar"
8
- import { useSize } from "soda-hooks"
9
-
10
- import { px, transformCSSVariable } from "@/utils"
11
-
12
- import { Scroll, ScrollProps } from "./Scroll"
13
-
14
- export interface AutoScrollProps extends ScrollProps {
15
- /** 轮播元素的个数 */
16
- count: number
17
-
18
- /** 轮播元素的高度 */
19
- itemHeight: number
20
-
21
- /**
22
- * 轮播动画的时间,单位毫秒
23
- * @default 1000
24
- */
25
- animation?: number
26
-
27
- /**
28
- * 每个元素的停留时间,单位毫秒
29
- * @default 3000
30
- */
31
- duration?: number
32
-
33
- /**
34
- * 元素之间的间距
35
- * @default 0
36
- */
37
- gap?: number
38
-
39
- /** 容器类名 */
40
- containerClassName?: string
41
-
42
- /** 容器样式 */
43
- containerStyle?: CSSProperties
44
-
45
- /**
46
- * 在鼠标移入时是否继续播放
47
- * @default false
48
- */
49
- playOnMouseEnter?: boolean
50
-
51
- /**
52
- * 是否暂停
53
- * @default false
54
- */
55
- paused?: boolean
56
- }
57
-
58
- export const AutoScroll = forwardRef<HTMLDivElement, AutoScrollProps>((props, ref) => {
59
- const {
60
- count,
61
- itemHeight,
62
- animation = 1000,
63
- duration = 3000,
64
- onMouseEnter,
65
- onMouseLeave,
66
- gap = 0,
67
- containerClassName,
68
- containerStyle,
69
- children,
70
- playOnMouseEnter,
71
- scrollbar,
72
- paused,
73
- ...rest
74
- } = props
75
- const bar = useRef<Scrollbar | null>(null)
76
- const timeout = useRef<NodeJS.Timeout | undefined>(undefined)
77
- const ele = useRef<HTMLDivElement>(null)
78
- const size = useSize(ele)
79
- const pausedRef = useRef(false)
80
- const pausedProps = useRef(paused)
81
- pausedProps.current = paused
82
-
83
- useImperativeHandle(ref, () => ele.current!, [])
84
- useImperativeHandle(scrollbar, () => bar.current!, [])
85
-
86
- useEffect(() => {
87
- if (playOnMouseEnter) pausedRef.current = false
88
- }, [playOnMouseEnter])
89
-
90
- useEffect(() => {
91
- if (!size || count === 0) return
92
- const { height } = size
93
- const range = getArray(count, index => (itemHeight + gap) * (index + 1) - (index === count - 1 ? gap : 0))
94
- const scrollHeight = range[range.length - 1]
95
- if (height >= scrollHeight) return
96
- function scroll(target: number) {
97
- clearTimeout(timeout.current)
98
- timeout.current = setTimeout(() => {
99
- if (pausedRef.current || pausedProps.current) return scroll(target)
100
- bar.current?.scrollTo(0, target, animation)
101
- }, duration)
102
- }
103
- scroll(range[0])
104
- function listener(status: ScrollStatus) {
105
- const { y } = status.offset
106
- const scrollToBottom = Math.abs(y + height - scrollHeight) / itemHeight <= 0.05
107
- const target = scrollToBottom ? 0 : range.find(item => item > y)!
108
- scroll(target)
109
- }
110
- bar.current?.addListener(listener)
111
- return () => {
112
- clearTimeout(timeout.current)
113
- bar.current?.removeListener(listener)
114
- bar.current?.scrollTo(0, 0)
115
- }
116
- }, [size, count, itemHeight, gap, duration, animation])
117
-
118
- function onContainerMouseEnter(e: ReactMouseEvent<HTMLDivElement, MouseEvent>) {
119
- if (playOnMouseEnter) return
120
- pausedRef.current = true
121
- onMouseEnter?.(e)
122
- }
123
-
124
- function onContainerMouseLeave(e: ReactMouseEvent<HTMLDivElement, MouseEvent>) {
125
- if (playOnMouseEnter) return
126
- pausedRef.current = false
127
- onMouseLeave?.(e)
128
- }
129
-
130
- return (
131
- <Scroll ref={ele} scrollbar={bar} onMouseEnter={onContainerMouseEnter} onMouseLeave={onContainerMouseLeave} {...rest}>
132
- <div
133
- className={clsx(
134
- css`
135
- display: flex;
136
- flex-direction: column;
137
- gap: var(--gap, 0);
138
- & > * {
139
- flex: none;
140
- }
141
- `,
142
- containerClassName,
143
- )}
144
- style={transformCSSVariable({ gap: px(gap) }, containerStyle)}
145
- >
146
- {children}
147
- </div>
148
- </Scroll>
149
- )
150
- })
1
+ "use client"
2
+
3
+ import { css } from "@emotion/css"
4
+ import { clsx, getArray } from "deepsea-tools"
5
+ import { CSSProperties, MouseEvent as ReactMouseEvent, forwardRef, useEffect, useImperativeHandle, useRef } from "react"
6
+ import Scrollbar from "smooth-scrollbar"
7
+ import { ScrollStatus } from "smooth-scrollbar/interfaces/scrollbar"
8
+ import { useSize } from "soda-hooks"
9
+
10
+ import { px, transformCSSVariable } from "@/utils"
11
+
12
+ import { Scroll, ScrollProps } from "./Scroll"
13
+
14
+ export interface AutoScrollProps extends ScrollProps {
15
+ /** 轮播元素的个数 */
16
+ count: number
17
+
18
+ /** 轮播元素的高度 */
19
+ itemHeight: number
20
+
21
+ /**
22
+ * 轮播动画的时间,单位毫秒
23
+ * @default 1000
24
+ */
25
+ animation?: number
26
+
27
+ /**
28
+ * 每个元素的停留时间,单位毫秒
29
+ * @default 3000
30
+ */
31
+ duration?: number
32
+
33
+ /**
34
+ * 元素之间的间距
35
+ * @default 0
36
+ */
37
+ gap?: number
38
+
39
+ /** 容器类名 */
40
+ containerClassName?: string
41
+
42
+ /** 容器样式 */
43
+ containerStyle?: CSSProperties
44
+
45
+ /**
46
+ * 在鼠标移入时是否继续播放
47
+ * @default false
48
+ */
49
+ playOnMouseEnter?: boolean
50
+
51
+ /**
52
+ * 是否暂停
53
+ * @default false
54
+ */
55
+ paused?: boolean
56
+ }
57
+
58
+ export const AutoScroll = forwardRef<HTMLDivElement, AutoScrollProps>((props, ref) => {
59
+ const {
60
+ count,
61
+ itemHeight,
62
+ animation = 1000,
63
+ duration = 3000,
64
+ onMouseEnter,
65
+ onMouseLeave,
66
+ gap = 0,
67
+ containerClassName,
68
+ containerStyle,
69
+ children,
70
+ playOnMouseEnter,
71
+ scrollbar,
72
+ paused,
73
+ ...rest
74
+ } = props
75
+ const bar = useRef<Scrollbar | null>(null)
76
+ const timeout = useRef<NodeJS.Timeout | undefined>(undefined)
77
+ const ele = useRef<HTMLDivElement>(null)
78
+ const size = useSize(ele)
79
+ const pausedRef = useRef(false)
80
+ const pausedProps = useRef(paused)
81
+ pausedProps.current = paused
82
+
83
+ useImperativeHandle(ref, () => ele.current!, [])
84
+ useImperativeHandle(scrollbar, () => bar.current!, [])
85
+
86
+ useEffect(() => {
87
+ if (playOnMouseEnter) pausedRef.current = false
88
+ }, [playOnMouseEnter])
89
+
90
+ useEffect(() => {
91
+ if (!size || count === 0) return
92
+ const { height } = size
93
+ const range = getArray(count, index => (itemHeight + gap) * (index + 1) - (index === count - 1 ? gap : 0))
94
+ const scrollHeight = range[range.length - 1]
95
+ if (height >= scrollHeight) return
96
+ function scroll(target: number) {
97
+ clearTimeout(timeout.current)
98
+ timeout.current = setTimeout(() => {
99
+ if (pausedRef.current || pausedProps.current) return scroll(target)
100
+ bar.current?.scrollTo(0, target, animation)
101
+ }, duration)
102
+ }
103
+ scroll(range[0])
104
+ function listener(status: ScrollStatus) {
105
+ const { y } = status.offset
106
+ const scrollToBottom = Math.abs(y + height - scrollHeight) / itemHeight <= 0.05
107
+ const target = scrollToBottom ? 0 : range.find(item => item > y)!
108
+ scroll(target)
109
+ }
110
+ bar.current?.addListener(listener)
111
+ return () => {
112
+ clearTimeout(timeout.current)
113
+ bar.current?.removeListener(listener)
114
+ bar.current?.scrollTo(0, 0)
115
+ }
116
+ }, [size, count, itemHeight, gap, duration, animation])
117
+
118
+ function onContainerMouseEnter(e: ReactMouseEvent<HTMLDivElement, MouseEvent>) {
119
+ if (playOnMouseEnter) return
120
+ pausedRef.current = true
121
+ onMouseEnter?.(e)
122
+ }
123
+
124
+ function onContainerMouseLeave(e: ReactMouseEvent<HTMLDivElement, MouseEvent>) {
125
+ if (playOnMouseEnter) return
126
+ pausedRef.current = false
127
+ onMouseLeave?.(e)
128
+ }
129
+
130
+ return (
131
+ <Scroll ref={ele} scrollbar={bar} onMouseEnter={onContainerMouseEnter} onMouseLeave={onContainerMouseLeave} {...rest}>
132
+ <div
133
+ className={clsx(
134
+ css`
135
+ display: flex;
136
+ flex-direction: column;
137
+ gap: var(--gap, 0);
138
+ & > * {
139
+ flex: none;
140
+ }
141
+ `,
142
+ containerClassName,
143
+ )}
144
+ style={transformCSSVariable({ gap: px(gap) }, containerStyle)}
145
+ >
146
+ {children}
147
+ </div>
148
+ </Scroll>
149
+ )
150
+ })