@tendaui/components 1.0.0 → 1.2.3

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 (270) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +176 -176
  3. package/alert/Alert.tsx +3 -2
  4. package/button/_example/base.tsx +10 -0
  5. package/button/_example/icon.tsx +20 -0
  6. package/color-picker/ColorPickPanel.tsx +9 -0
  7. package/color-picker/ColorPicker.tsx +67 -0
  8. package/color-picker/components/panel/alpha.tsx +32 -0
  9. package/color-picker/components/panel/format/index.tsx +47 -0
  10. package/color-picker/components/panel/format/inputs.tsx +119 -0
  11. package/color-picker/components/panel/header.tsx +37 -0
  12. package/color-picker/components/panel/hue.tsx +20 -0
  13. package/color-picker/components/panel/index.tsx +191 -0
  14. package/color-picker/components/panel/saturation.tsx +81 -0
  15. package/color-picker/components/panel/slider.tsx +76 -0
  16. package/color-picker/components/panel/swatches.tsx +84 -0
  17. package/color-picker/components/trigger.tsx +49 -0
  18. package/color-picker/defaultProps.ts +7 -0
  19. package/color-picker/helpers.ts +53 -0
  20. package/color-picker/hooks/useClassNames.ts +9 -0
  21. package/color-picker/hooks/useStyles.ts +39 -0
  22. package/color-picker/index.ts +12 -0
  23. package/color-picker/style/css.js +1 -0
  24. package/color-picker/style/index.js +1 -0
  25. package/color-picker/type.ts +143 -0
  26. package/color-picker/utils/color-picker/cmyk.ts +89 -0
  27. package/color-picker/utils/color-picker/color.ts +467 -0
  28. package/color-picker/utils/color-picker/constants.ts +187 -0
  29. package/color-picker/utils/color-picker/draggable.ts +100 -0
  30. package/color-picker/utils/color-picker/format.ts +95 -0
  31. package/color-picker/utils/color-picker/gradient.ts +243 -0
  32. package/color-picker/utils/color-picker/index.ts +7 -0
  33. package/color-picker/utils/color-picker/types.ts +33 -0
  34. package/common/observe.ts +33 -0
  35. package/common.ts +20 -0
  36. package/config-provider/ConfigContext.tsx +4 -1
  37. package/config-provider/index.ts +1 -1
  38. package/dialog/DialogCard.tsx +4 -6
  39. package/dialog/hooks/useDialogPosition.ts +1 -2
  40. package/dialog/plugin.tsx +3 -2
  41. package/drawer/Drawer.tsx +264 -0
  42. package/drawer/defaultProps.ts +19 -0
  43. package/drawer/hooks/useDrag.ts +98 -0
  44. package/drawer/hooks/useLockStyle.ts +36 -0
  45. package/drawer/index.ts +5 -0
  46. package/drawer/style/css.js +1 -0
  47. package/drawer/style/index.js +1 -0
  48. package/drawer/type.ts +193 -0
  49. package/drawer/utils/index.ts +76 -0
  50. package/fireworks/Fireworks.tsx +138 -0
  51. package/fireworks/index.ts +10 -0
  52. package/fireworks/style/css.js +0 -0
  53. package/fireworks/style/index.js +0 -0
  54. package/fireworks/type.ts +72 -0
  55. package/form/FormItem.tsx +5 -5
  56. package/form/easing.ts +10 -0
  57. package/form/scroll.ts +124 -0
  58. package/form/type.ts +519 -519
  59. package/global-config/default-config.ts +95 -0
  60. package/global-config/locale/ar_KW.ts +270 -0
  61. package/global-config/locale/en_US.ts +280 -0
  62. package/global-config/locale/it_IT.ts +287 -0
  63. package/global-config/locale/ja_JP.ts +279 -0
  64. package/global-config/locale/ko_KR.ts +279 -0
  65. package/global-config/locale/ru_RU.ts +288 -0
  66. package/global-config/locale/zh_CN.ts +279 -0
  67. package/global-config/locale/zh_TW.ts +279 -0
  68. package/global-config/mobile/default-config.ts +6 -0
  69. package/global-config/mobile/locale/ar_KW.ts +113 -0
  70. package/global-config/mobile/locale/en_US.ts +114 -0
  71. package/global-config/mobile/locale/it_IT.ts +114 -0
  72. package/global-config/mobile/locale/ja_JP.ts +101 -0
  73. package/global-config/mobile/locale/ko_KR.ts +101 -0
  74. package/global-config/mobile/locale/ru_RU.ts +113 -0
  75. package/global-config/mobile/locale/zh_CN.ts +101 -0
  76. package/global-config/mobile/locale/zh_TW.ts +101 -0
  77. package/global-config/t.ts +111 -0
  78. package/hooks/useControlled.ts +3 -3
  79. package/hooks/useDeepEffect.ts +32 -0
  80. package/hooks/useGlobalIcon.ts +10 -3
  81. package/hooks/useLastest.ts +2 -6
  82. package/hooks/useResizeObserve.ts +36 -0
  83. package/index.ts +10 -7
  84. package/input/Input.tsx +4 -1
  85. package/input/defaultProps.ts +0 -2
  86. package/input/type.ts +1 -6
  87. package/input-number/InputNumber.tsx +124 -0
  88. package/input-number/defaultProps.ts +17 -0
  89. package/input-number/index.ts +9 -0
  90. package/input-number/style/css.js +1 -0
  91. package/input-number/style/index.js +1 -0
  92. package/input-number/type.ts +147 -0
  93. package/input-number/useInputNumber.tsx +270 -0
  94. package/ip-input/IPInput.tsx +516 -0
  95. package/ip-input/defaultProps.ts +11 -0
  96. package/ip-input/index.ts +3 -0
  97. package/ip-input/style/css.js +1 -0
  98. package/ip-input/style/index.js +1 -0
  99. package/ip-input/type.ts +115 -0
  100. package/ip-input/utils.ts +112 -0
  101. package/layout/Aside.tsx +38 -0
  102. package/layout/Layout.tsx +104 -0
  103. package/layout/defaultProps.ts +9 -0
  104. package/layout/index.ts +9 -0
  105. package/layout/style/css.js +1 -0
  106. package/layout/style/index.js +1 -0
  107. package/layout/type.ts +43 -0
  108. package/list/List.tsx +144 -0
  109. package/list/ListItem.tsx +36 -0
  110. package/list/ListItemMeta.tsx +40 -0
  111. package/list/defaultProps.ts +11 -0
  112. package/list/hooks/useListVirtualScroll.ts +82 -0
  113. package/list/index.ts +11 -0
  114. package/list/style/css.js +1 -0
  115. package/list/style/index.js +1 -0
  116. package/list/type.ts +93 -0
  117. package/locale/LocalReceiver.ts +55 -0
  118. package/locale/ar_KW.ts +7 -0
  119. package/locale/en_US.ts +7 -0
  120. package/locale/it_IT.ts +6 -0
  121. package/locale/ja_JP.ts +6 -0
  122. package/locale/ko_KR.ts +6 -0
  123. package/locale/ru_RU.ts +6 -0
  124. package/locale/zh_CN.ts +5 -0
  125. package/locale/zh_TW.ts +7 -0
  126. package/notification/NotifyContainer.tsx +2 -2
  127. package/notification/NotifyContext.tsx +1 -0
  128. package/package.json +6 -3
  129. package/popup/Popup.tsx +34 -10
  130. package/radio/Radio.tsx +24 -0
  131. package/radio/RadioGroup.tsx +159 -0
  132. package/radio/defaultProps.ts +18 -0
  133. package/radio/index.ts +12 -0
  134. package/radio/style/css.js +0 -0
  135. package/radio/style/index.js +1 -0
  136. package/radio/type.ts +115 -0
  137. package/radio/useKeyboard.ts +36 -0
  138. package/select/hooks/useOptions.ts +10 -7
  139. package/select/hooks/usePanelVirtualScroll.ts +1 -1
  140. package/select/type.ts +382 -382
  141. package/select-input/type.ts +280 -280
  142. package/slider/Slider.tsx +270 -0
  143. package/slider/SliderHandleButton.tsx +50 -0
  144. package/slider/defaultProps.ts +15 -0
  145. package/slider/index.ts +9 -0
  146. package/slider/style/css.js +1 -0
  147. package/slider/style/index.js +1 -0
  148. package/slider/type.ts +77 -0
  149. package/style/all.js +26 -0
  150. package/styles/_global.scss +39 -39
  151. package/styles/_vars.scss +358 -386
  152. package/styles/components/alert/_index.scss +175 -175
  153. package/styles/components/alert/_vars.scss +39 -39
  154. package/styles/components/badge/_index.scss +70 -70
  155. package/styles/components/badge/_vars.scss +25 -25
  156. package/styles/components/button/_index.scss +499 -511
  157. package/styles/components/button/_mixins.scss +39 -39
  158. package/styles/components/button/_vars.scss +120 -122
  159. package/styles/components/checkbox/_index.scss +158 -158
  160. package/styles/components/checkbox/_var.scss +60 -60
  161. package/styles/components/color-picker/_index.scss +586 -0
  162. package/styles/components/color-picker/_mixins.scss +0 -0
  163. package/styles/components/color-picker/_vars.scss +84 -0
  164. package/styles/components/dialog/_animate.scss +135 -135
  165. package/styles/components/dialog/_index.scss +311 -311
  166. package/styles/components/dialog/_vars.scss +59 -59
  167. package/styles/components/drawer/_index.scss +205 -0
  168. package/styles/components/drawer/_mixins.scss +1 -0
  169. package/styles/components/drawer/_var.scss +53 -0
  170. package/styles/components/fireworks/_index.scss +86 -0
  171. package/styles/components/fireworks/_vars.scss +4 -0
  172. package/styles/components/form/_index.scss +174 -174
  173. package/styles/components/form/_mixins.scss +76 -76
  174. package/styles/components/form/_vars.scss +100 -100
  175. package/styles/components/input/_index.scss +349 -349
  176. package/styles/components/input/_mixins.scss +116 -116
  177. package/styles/components/input/_vars.scss +134 -134
  178. package/styles/components/input-number/_index.scss +353 -0
  179. package/styles/components/input-number/_mixins.scss +0 -0
  180. package/styles/components/input-number/_vars.scss +65 -0
  181. package/styles/components/ip-input/_index.scss +280 -0
  182. package/styles/components/layout/_index.scss +47 -0
  183. package/styles/components/layout/_mixin.scss +0 -0
  184. package/styles/components/layout/_vars.scss +18 -0
  185. package/styles/components/layout/doc.scss +74 -0
  186. package/styles/components/list/_index.scss +172 -0
  187. package/styles/components/list/_mixins.scss +0 -0
  188. package/styles/components/list/_vars.scss +41 -0
  189. package/styles/components/loading/_index.scss +112 -112
  190. package/styles/components/loading/_vars.scss +39 -39
  191. package/styles/components/notification/_index.scss +160 -160
  192. package/styles/components/notification/_mixins.scss +12 -12
  193. package/styles/components/notification/_vars.scss +59 -59
  194. package/styles/components/popup/_index.scss +82 -82
  195. package/styles/components/popup/_mixin.scss +149 -149
  196. package/styles/components/popup/_var.scss +31 -31
  197. package/styles/components/radio/_index.scss +376 -0
  198. package/styles/components/radio/_mixins.scss +0 -0
  199. package/styles/components/radio/_var.scss +92 -0
  200. package/styles/components/select/_index.scss +290 -290
  201. package/styles/components/select/_var.scss +65 -65
  202. package/styles/components/select-input/_index.scss +5 -5
  203. package/styles/components/select-input/_var.scss +3 -3
  204. package/styles/components/slider/_index.scss +241 -0
  205. package/styles/components/slider/_mixins.scss +0 -0
  206. package/styles/components/slider/_vars.scss +50 -0
  207. package/styles/components/switch/_index.scss +279 -279
  208. package/styles/components/switch/_vars.scss +61 -61
  209. package/styles/components/table/_index.scss +193 -0
  210. package/styles/components/table/_var.scss +52 -0
  211. package/styles/components/tabs/_index.scss +165 -0
  212. package/styles/components/tabs/_mixins.scss +11 -0
  213. package/styles/components/tabs/_vars.scss +71 -0
  214. package/styles/components/tag/_index.scss +316 -316
  215. package/styles/components/tag/_var.scss +85 -85
  216. package/styles/components/tag-input/_index.scss +163 -163
  217. package/styles/components/tag-input/_vars.scss +16 -16
  218. package/styles/globals.css +250 -250
  219. package/styles/mixins/_focus.scss +7 -7
  220. package/styles/mixins/_layout.scss +32 -32
  221. package/styles/mixins/_reset.scss +10 -10
  222. package/styles/mixins/_scrollbar.scss +31 -31
  223. package/styles/mixins/_text.scss +48 -48
  224. package/styles/rillple.css +16 -16
  225. package/styles/scrollbar.css +41 -41
  226. package/styles/themes/_dark.scss +191 -191
  227. package/styles/themes/_font.scss +69 -79
  228. package/styles/themes/_index.scss +5 -5
  229. package/styles/themes/_light.scss +190 -190
  230. package/styles/themes/_radius.scss +9 -9
  231. package/styles/themes/_size.scss +68 -68
  232. package/styles/themes.css +66 -66
  233. package/styles/utilities/_animation.scss +57 -57
  234. package/styles/utilities/_tips.scss +9 -9
  235. package/tab/TabBar.tsx +85 -0
  236. package/tab/TabNav.tsx +103 -0
  237. package/tab/TabNavItem.tsx +80 -0
  238. package/tab/TabPanel.tsx +42 -0
  239. package/tab/Tabs.tsx +71 -0
  240. package/tab/defaultProps.ts +19 -0
  241. package/tab/index.ts +7 -0
  242. package/tab/style/index.js +1 -0
  243. package/tab/type.ts +125 -0
  244. package/tab/useTabClass.ts +20 -0
  245. package/table/Cell.tsx +109 -0
  246. package/table/TBody.tsx +77 -0
  247. package/table/THead.tsx +63 -0
  248. package/table/TR.tsx +78 -0
  249. package/table/Table.tsx +73 -0
  250. package/table/defaultProps.ts +14 -0
  251. package/table/hooks/index.ts +4 -0
  252. package/table/hooks/useTableClassName.ts +63 -0
  253. package/table/hooks/useTableStyle.ts +93 -0
  254. package/table/index.ts +7 -0
  255. package/table/style/css.js +1 -0
  256. package/table/style/index.js +1 -0
  257. package/table/type.ts +192 -0
  258. package/tag/Tag.tsx +1 -1
  259. package/tag-input/hooks/useTagList.tsx +1 -1
  260. package/utils/dom.ts +4 -0
  261. package/utils/forwardRefWithStatics.ts +1 -4
  262. package/utils/input-number/large-number.ts +423 -0
  263. package/utils/input-number/number.ts +257 -0
  264. package/utils/isFragment.ts +6 -6
  265. package/utils/log/index.ts +3 -0
  266. package/utils/log/log.ts +30 -0
  267. package/utils/log/types.ts +12 -0
  268. package/utils/number.ts +21 -0
  269. package/utils/scroll.ts +26 -0
  270. package/utils/style.ts +2 -4
@@ -0,0 +1,138 @@
1
+ import React, {
2
+ CSSProperties,
3
+ forwardRef,
4
+ useCallback,
5
+ useEffect,
6
+ useMemo,
7
+ useRef,
8
+ useState
9
+ } from "react";
10
+ import classNames from "classnames";
11
+
12
+ import useConfig from "../hooks/useConfig";
13
+ import { StyledProps } from "../common";
14
+ import type { FireworkBurst, FireworksLaunchContext, TdFireworksProps } from "./type";
15
+
16
+ const DEFAULT_COLORS = ["#FF5F6D", "#FFC371", "#00C9FF", "#92FE9D", "#C77DFF", "#F2EA02"];
17
+
18
+ type CSSPropertiesWithVars = CSSProperties & {
19
+ [key: `--${string}`]: string | number;
20
+ };
21
+
22
+ const randomInRange = (min: number, max: number) => Math.random() * (max - min) + min;
23
+
24
+ const pickColor = (palette: string[]) => {
25
+ if (!palette || palette.length === 0) return DEFAULT_COLORS[0];
26
+ const index = Math.floor(Math.random() * palette.length);
27
+ return palette[index];
28
+ };
29
+
30
+ const createBurstList = (count: number, colors: string[]): FireworkBurst[] =>
31
+ Array.from({ length: Math.max(1, count) }).map((_, index) => ({
32
+ id: `${Date.now()}-${index}-${Math.random().toString(36).slice(2, 7)}`,
33
+ color: pickColor(colors),
34
+ left: randomInRange(8, 92),
35
+ top: randomInRange(15, 85),
36
+ delay: randomInRange(0, 500),
37
+ rotationOffset: randomInRange(0, 360)
38
+ }));
39
+
40
+ export interface FireworksProps extends TdFireworksProps, StyledProps {}
41
+
42
+ const Fireworks = forwardRef<HTMLDivElement, FireworksProps>((props, ref) => {
43
+ const {
44
+ className,
45
+ style,
46
+ count = 6,
47
+ colors = DEFAULT_COLORS,
48
+ duration = 2400,
49
+ size = 140,
50
+ interval = 2800,
51
+ particleCount = 12,
52
+ loop = true,
53
+ onLaunch,
54
+ ...rest
55
+ } = props;
56
+
57
+ const { classPrefix } = useConfig();
58
+ const componentCls = `${classPrefix}-fireworks`;
59
+ const safeParticleCount = Math.max(6, particleCount);
60
+ const [bursts, setBursts] = useState<FireworkBurst[]>(() => createBurstList(count, colors));
61
+ const timerRef = useRef<ReturnType<typeof setInterval>>();
62
+
63
+ const particleAngles = useMemo(() => {
64
+ return Array.from({ length: safeParticleCount }).map((_, index) => (360 / safeParticleCount) * index);
65
+ }, [safeParticleCount]);
66
+
67
+ const triggerLaunch = useCallback(() => {
68
+ const nextBursts = createBurstList(count, colors);
69
+ setBursts(nextBursts);
70
+ const context: FireworksLaunchContext = { bursts: nextBursts };
71
+ onLaunch?.(context);
72
+ }, [count, colors, onLaunch]);
73
+
74
+ useEffect(() => {
75
+ triggerLaunch();
76
+ }, [triggerLaunch]);
77
+
78
+ useEffect(() => {
79
+ if (!loop) return undefined;
80
+ timerRef.current && clearInterval(timerRef.current);
81
+ timerRef.current = setInterval(triggerLaunch, Math.max(interval, duration));
82
+ return () => {
83
+ if (timerRef.current) {
84
+ clearInterval(timerRef.current);
85
+ }
86
+ };
87
+ }, [duration, interval, loop, triggerLaunch]);
88
+
89
+ useEffect(
90
+ () => () => {
91
+ if (timerRef.current) {
92
+ clearInterval(timerRef.current);
93
+ }
94
+ },
95
+ []
96
+ );
97
+
98
+ return (
99
+ <div
100
+ ref={ref}
101
+ className={classNames(componentCls, className)}
102
+ style={style}
103
+ role="presentation"
104
+ aria-hidden="true"
105
+ {...rest}
106
+ >
107
+ {bursts.map((burst) => {
108
+ const burstStyle: CSSPropertiesWithVars = {
109
+ "--fireworks-left": `${burst.left}%`,
110
+ "--fireworks-top": `${burst.top}%`,
111
+ "--fireworks-delay": `${burst.delay}ms`,
112
+ "--fireworks-color": burst.color,
113
+ "--fireworks-size": `${size}px`,
114
+ "--fireworks-duration": `${duration}ms`
115
+ };
116
+
117
+ return (
118
+ <span key={burst.id} className={`${componentCls}__burst`} style={burstStyle}>
119
+ {particleAngles.map((angle, index) => {
120
+ const sparkStyle: CSSPropertiesWithVars = {
121
+ "--fireworks-delay": `${burst.delay}ms`,
122
+ "--fireworks-duration": `${duration}ms`,
123
+ "--fireworks-color": burst.color,
124
+ "--fireworks-rotate": `${angle + burst.rotationOffset}deg`
125
+ };
126
+ return <i key={`${burst.id}-${index}`} className={`${componentCls}__spark`} style={sparkStyle} />;
127
+ })}
128
+ </span>
129
+ );
130
+ })}
131
+ </div>
132
+ );
133
+ });
134
+
135
+ Fireworks.displayName = "Fireworks";
136
+
137
+ export default Fireworks;
138
+
@@ -0,0 +1,10 @@
1
+ import _Fireworks from "./Fireworks";
2
+
3
+ import "./style/index.js";
4
+
5
+ export type { FireworksProps } from "./Fireworks";
6
+ export * from "./type";
7
+
8
+ export const Fireworks = _Fireworks;
9
+ export default Fireworks;
10
+
File without changes
File without changes
@@ -0,0 +1,72 @@
1
+ export interface FireworkBurst {
2
+ /**
3
+ * 唯一标识,用于 React 渲染
4
+ */
5
+ id: string;
6
+ /**
7
+ * 烟花的主色
8
+ */
9
+ color: string;
10
+ /**
11
+ * 爆炸中心的横向位置(百分比)
12
+ */
13
+ left: number;
14
+ /**
15
+ * 爆炸中心的纵向位置(百分比)
16
+ */
17
+ top: number;
18
+ /**
19
+ * 动画延迟,毫秒
20
+ */
21
+ delay: number;
22
+ /**
23
+ * 每朵烟花的旋转偏移,度数
24
+ */
25
+ rotationOffset: number;
26
+ }
27
+
28
+ export interface FireworksLaunchContext {
29
+ bursts: FireworkBurst[];
30
+ }
31
+
32
+ export interface TdFireworksProps {
33
+ /**
34
+ * 同时展示的烟花数量
35
+ * @default 6
36
+ */
37
+ count?: number;
38
+ /**
39
+ * 烟花的随机颜色池
40
+ */
41
+ colors?: string[];
42
+ /**
43
+ * 单次烟花动画时长,毫秒
44
+ * @default 2400
45
+ */
46
+ duration?: number;
47
+ /**
48
+ * 单朵烟花的最大尺寸,像素
49
+ * @default 140
50
+ */
51
+ size?: number;
52
+ /**
53
+ * 每轮重新生成烟花的间隔,毫秒
54
+ * @default 2800
55
+ */
56
+ interval?: number;
57
+ /**
58
+ * 单朵烟花的光束数量
59
+ * @default 12
60
+ */
61
+ particleCount?: number;
62
+ /**
63
+ * 是否持续循环播放
64
+ * @default true
65
+ */
66
+ loop?: boolean;
67
+ /**
68
+ * 每次重新生成烟花时回调
69
+ */
70
+ onLaunch?: (context: FireworksLaunchContext) => void;
71
+ }
72
+
package/form/FormItem.tsx CHANGED
@@ -244,7 +244,7 @@ const FormItem = forwardRef<FormItemInstance, FormItemProps>((originalProps, ref
244
244
  .filter((item) => item.result !== true)
245
245
  .map((item) => {
246
246
  Object.keys(item).forEach((key) => {
247
- if (!item.message && errorMessages[key]) {
247
+ if (!item.message && errorMessages && errorMessages[key] && typeof errorMessages[key] === "string") {
248
248
  item.message = parseMessage(errorMessages[key], {
249
249
  validate: item[key],
250
250
  name: isString(label) ? label : String(name)
@@ -512,8 +512,8 @@ const FormItem = forwardRef<FormItemInstance, FormItemProps>((originalProps, ref
512
512
  let ctrlKey = "value";
513
513
  if (React.isValidElement(child)) {
514
514
  if (child.type === FormItem) {
515
- return React.cloneElement(child, {
516
- ref: (el) => {
515
+ return React.cloneElement(child as React.ReactElement<any>, {
516
+ ref: (el: any) => {
517
517
  if (!el) return;
518
518
  innerFormItemsRef.current[index] = el;
519
519
  }
@@ -523,11 +523,11 @@ const FormItem = forwardRef<FormItemInstance, FormItemProps>((originalProps, ref
523
523
  ctrlKey = ctrlKeyMap.get(child.type) || "value";
524
524
  }
525
525
  const childProps = child.props as TdFormItemProps & React.HTMLAttributes<HTMLDivElement>;
526
- return React.cloneElement(child, {
526
+ return React.cloneElement(child as React.ReactElement<any>, {
527
527
  disabled: disabledFromContext,
528
528
  ...childProps,
529
529
  [ctrlKey]: formValue,
530
- onChange: (value: ValueType, ...args: unknown[]) => {
530
+ onChange: (value: ValueType, ...args: any[]) => {
531
531
  const newValue = valueFormat ? valueFormat(value) : value;
532
532
  updateFormValue(newValue, true, true);
533
533
  childProps?.onChange?.call?.(null, value, ...args);
package/form/easing.ts ADDED
@@ -0,0 +1,10 @@
1
+ export type EasingFunction = (t: number, b: number, c: number, d: number) => number;
2
+
3
+ export const easeInOutCubic: EasingFunction = (t, b, c, d) => {
4
+ const cc = c - b;
5
+ t /= d / 2;
6
+ if (t < 1) {
7
+ return (cc / 2) * t * t * t + b;
8
+ }
9
+ return (cc / 2) * ((t -= 2) * t * t + 2) + b;
10
+ };
package/form/scroll.ts ADDED
@@ -0,0 +1,124 @@
1
+ import { isString } from "lodash-es";
2
+ import raf from "raf";
3
+ import { ScrollContainer, ScrollContainerElement } from "../common";
4
+ import { isWindow } from "../utils/dom";
5
+ import { easeInOutCubic, EasingFunction } from "./easing";
6
+
7
+ export function hasBodyScrollbar() {
8
+ return document.body.scrollHeight > document.documentElement.clientHeight;
9
+ }
10
+
11
+ // 用于判断节点内容是否溢出
12
+ export const isNodeOverflow = (ele: Element | Element[]): boolean => {
13
+ const { clientWidth = 0, scrollWidth = 0 } = ele as Element & { clientWidth: number; scrollWidth: number };
14
+
15
+ if (scrollWidth > clientWidth) {
16
+ return true;
17
+ }
18
+ return false;
19
+ };
20
+
21
+ /**
22
+ * 获取滚动容器
23
+ * 因为 document 不存在 scroll 等属性, 因此排除 document
24
+ * window | HTMLElement
25
+ * @param {ScrollContainerElement} [container='body']
26
+ * @returns {ScrollContainer}
27
+ */
28
+ export const getScrollContainer = (container: ScrollContainer = "body"): ScrollContainerElement => {
29
+ if (isString(container)) {
30
+ return container ? (document.querySelector(container) as HTMLElement) : window;
31
+ }
32
+ if (typeof container === "function") {
33
+ return container();
34
+ }
35
+ return container || window;
36
+ };
37
+
38
+ /**
39
+ * 获取滚动距离
40
+ *
41
+ * @export
42
+ * @param {ScrollTarget} target
43
+ * @param {boolean} isLeft true 为获取 scrollLeft, false 为获取 scrollTop
44
+ * @returns {number}
45
+ */
46
+ export function getScroll(target: ScrollTarget, isLeft?: boolean): number {
47
+ // node 环境或者 target 为空
48
+ if (typeof window === "undefined" || !target) {
49
+ return 0;
50
+ }
51
+ const method = isLeft ? "scrollLeft" : "scrollTop";
52
+ let result = 0;
53
+ if (isWindow(target)) {
54
+ result = (target as Window)[isLeft ? "pageXOffset" : "pageYOffset"];
55
+ } else if (target instanceof Document) {
56
+ result = target.documentElement[method];
57
+ } else if (target) {
58
+ result = (target as HTMLElement)[method];
59
+ }
60
+ return result;
61
+ }
62
+
63
+ export type ScrollTarget = HTMLElement | Window | Document;
64
+
65
+ interface ScrollTopOptions {
66
+ container?: ScrollTarget;
67
+ duration?: number;
68
+ easing?: EasingFunction;
69
+ }
70
+
71
+ export function scrollTo(target: number, opt: ScrollTopOptions) {
72
+ const { container = window, duration = 450, easing = easeInOutCubic } = opt;
73
+ const scrollTop = getScroll(container);
74
+ const startTime = Date.now();
75
+ return new Promise((res) => {
76
+ const fnc = () => {
77
+ const timestamp = Date.now();
78
+ const time = timestamp - startTime;
79
+ const nextScrollTop = easing(Math.min(time, duration), scrollTop, target, duration);
80
+ if (isWindow(container)) {
81
+ (container as Window).scrollTo(window.pageXOffset, nextScrollTop);
82
+ } else if (
83
+ typeof HTMLDocument !== "undefined" &&
84
+ (container instanceof HTMLDocument || container.constructor.name === "HTMLDocument")
85
+ ) {
86
+ (container as HTMLDocument).documentElement.scrollTop = nextScrollTop;
87
+ } else {
88
+ (container as HTMLElement).scrollTop = nextScrollTop;
89
+ }
90
+ if (time < duration) {
91
+ raf(fnc);
92
+ } else {
93
+ // 由于上面步骤设置了 scrollTop, 滚动事件可能未触发完毕
94
+ // 此时应该在下一帧再执行 res
95
+ raf(res);
96
+ }
97
+ };
98
+ raf(fnc);
99
+ });
100
+ }
101
+
102
+ /**
103
+ * 获取当前视图滑动的距离
104
+ * @returns { scrollTop: number, scrollLeft: number }
105
+ */
106
+ export function getWindowScroll(): { scrollTop: number; scrollLeft: number } {
107
+ const { body } = document;
108
+ const docElm = document.documentElement;
109
+ const scrollTop = window.pageYOffset || docElm.scrollTop || body.scrollTop;
110
+ const scrollLeft = window.pageXOffset || docElm.scrollLeft || body.scrollLeft;
111
+
112
+ return { scrollTop, scrollLeft };
113
+ }
114
+
115
+ export type AnchorContainer = HTMLElement | Window;
116
+
117
+ export function getOffsetTop(target: HTMLElement, container: AnchorContainer) {
118
+ const { top } = target.getBoundingClientRect();
119
+ if (container === window) {
120
+ // 减去 document 的边框
121
+ return top - document.documentElement.clientTop;
122
+ }
123
+ return top - (container as HTMLElement).getBoundingClientRect().top;
124
+ }