@tendaui/components 1.0.0 → 1.0.2

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
package/list/type.ts ADDED
@@ -0,0 +1,93 @@
1
+ /* eslint-disable */
2
+
3
+ /**
4
+ * 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
5
+ * */
6
+
7
+ import { TNode, TScroll, ScrollToElementParams } from "../common";
8
+ import { MouseEvent, WheelEvent } from "react";
9
+
10
+ export interface TdListProps {
11
+ /**
12
+ * 自定义加载中。值为空不显示加载中,值为 'loading' 显示加载中状态,值为 'load-more' 显示加载更多状态。值类型为函数,则表示自定义加载状态呈现内容
13
+ */
14
+ asyncLoading?: TNode;
15
+ /**
16
+ * 底部
17
+ */
18
+ footer?: TNode;
19
+ /**
20
+ * 头部
21
+ */
22
+ header?: TNode;
23
+ /**
24
+ * 排列方式(待设计稿输出)
25
+ * @default horizontal
26
+ */
27
+ layout?: "horizontal" | "vertical";
28
+ /**
29
+ * 懒加载和虚拟滚动。为保证组件收益最大化,当数据量小于阈值 `scroll.threshold` 时,无论虚拟滚动的配置是否存在,组件内部都不会开启虚拟滚动,`scroll.threshold` 默认为 `100`
30
+ */
31
+ scroll?: TScroll;
32
+ /**
33
+ * 尺寸
34
+ * @default medium
35
+ */
36
+ size?: "small" | "medium" | "large";
37
+ /**
38
+ * 是否展示分割线
39
+ * @default false
40
+ */
41
+ split?: boolean;
42
+ /**
43
+ * 是否展示斑马纹
44
+ * @default false
45
+ */
46
+ stripe?: boolean;
47
+ /**
48
+ * 点击加载更多时触发
49
+ */
50
+ onLoadMore?: (options: { e: MouseEvent<HTMLDivElement> }) => void;
51
+ /**
52
+ * 列表滚动时触发,scrollTop 表示顶部滚动距离,scrollBottom 表示底部滚动距离
53
+ */
54
+ onScroll?: (options: { e: Event | WheelEvent<HTMLDivElement>; scrollTop: number; scrollBottom: number }) => void;
55
+ }
56
+
57
+ /** 组件实例方法 */
58
+ export interface ListInstanceFunctions {
59
+ /**
60
+ * 虚拟滚动场景下,支持指定滚动到具体的节点
61
+ */
62
+ scrollTo?: (scrollToParams: ScrollToElementParams) => void;
63
+ }
64
+
65
+ export interface TdListItemProps {
66
+ /**
67
+ * 操作栏
68
+ */
69
+ action?: TNode;
70
+ /**
71
+ * 内容,同 content
72
+ */
73
+ children?: TNode;
74
+ /**
75
+ * 内容
76
+ */
77
+ content?: TNode;
78
+ }
79
+
80
+ export interface TdListItemMetaProps {
81
+ /**
82
+ * 列表项内容
83
+ */
84
+ description?: TNode;
85
+ /**
86
+ * 列表项图片
87
+ */
88
+ image?: TNode;
89
+ /**
90
+ * 列表项标题
91
+ */
92
+ title?: TNode;
93
+ }
@@ -0,0 +1,55 @@
1
+ import React from "react";
2
+ import { t as commonT } from "../global-config/t";
3
+ import { ConfigContext, Locale } from "../config-provider";
4
+
5
+ export interface Placement {
6
+ [propName: string]: string | number;
7
+ }
8
+
9
+ export type TransformPattern = string | Function | Array<string>;
10
+
11
+ export function useLocaleReceiver<T extends keyof Locale>(componentName: T, defaultLocale?: Locale[T] | Function) {
12
+ const { globalConfig } = React.useContext(ConfigContext);
13
+
14
+ function transformLocale(pattern: TransformPattern, placement?: Placement): string;
15
+ function transformLocale(pattern: TransformPattern, placement?: number, data?: Placement): string;
16
+ function transformLocale(pattern: TransformPattern, ...args: any[]): string | Array<string> {
17
+ const REGEXP = /\{\s*([\w-]+)\s*\}/g;
18
+ const placement = args[0];
19
+
20
+ if (Array.isArray(pattern)) {
21
+ return pattern.map((p, index) => {
22
+ const translated = p.replace(REGEXP, (_: string, key: string) => {
23
+ if (placement) return String(placement[index][key]);
24
+ return "";
25
+ });
26
+ return translated;
27
+ });
28
+ }
29
+ if (typeof pattern === "function") {
30
+ return pattern(placement);
31
+ }
32
+
33
+ // use commonT for plural
34
+ const data = args[1];
35
+ if (data) {
36
+ return commonT(pattern, placement, data);
37
+ }
38
+ return commonT(pattern, placement);
39
+ }
40
+
41
+ /** @TypeA => 确保此参数是属于 globalConfig[componentName] 下的子属性 */
42
+ const componentLocale = React.useMemo<Locale[T] | Function>(() => {
43
+ const locale = defaultLocale || {};
44
+ const connectLocaleByName = globalConfig[componentName];
45
+
46
+ const localeFromContext = componentName && globalConfig ? connectLocaleByName : {};
47
+
48
+ return {
49
+ ...(typeof locale === "function" ? (locale as Function)() : locale),
50
+ ...(localeFromContext || {})
51
+ };
52
+ }, [componentName, defaultLocale, globalConfig]);
53
+
54
+ return [componentLocale, transformLocale] as [Locale[T], Function];
55
+ }
@@ -0,0 +1,7 @@
1
+ import { GlobalConfigProvider } from "../config-provider/type";
2
+
3
+ // TODO: Import from @tdesign/common-js when available
4
+ const arKW = {} as GlobalConfigProvider;
5
+
6
+ // 需要 GlobalConfigProvider 保证数据类型正确
7
+ export default arKW;
@@ -0,0 +1,7 @@
1
+ import { GlobalConfigProvider } from "../config-provider/type";
2
+
3
+ // TODO: Import from @tdesign/common-js when available
4
+ const enUS = {} as GlobalConfigProvider;
5
+
6
+ // 需要 GlobalConfigProvider 保证数据类型正确,本次提交就检查出了英文字段缺少
7
+ export default enUS;
@@ -0,0 +1,6 @@
1
+ import { GlobalConfigProvider } from "../config-provider/type";
2
+ // TODO: Import from @tdesign/common-js when available
3
+ const itIT = {} as GlobalConfigProvider;
4
+
5
+ // 需要 GlobalConfigProvider 保证数据类型正确
6
+ export default itIT as unknown as GlobalConfigProvider;
@@ -0,0 +1,6 @@
1
+ import { GlobalConfigProvider } from "../config-provider/type";
2
+ // TODO: Import from @tdesign/common-js when available
3
+ const jaJP = {} as GlobalConfigProvider;
4
+
5
+ // 需要 GlobalConfigProvider 保证数据类型正确
6
+ export default jaJP as unknown as GlobalConfigProvider;
@@ -0,0 +1,6 @@
1
+ import { GlobalConfigProvider } from "../config-provider/type";
2
+ // TODO: Import from @tdesign/common-js when available
3
+ const koKR = {} as GlobalConfigProvider;
4
+
5
+ // 需要 GlobalConfigProvider 保证数据类型正确
6
+ export default koKR as unknown as GlobalConfigProvider;
@@ -0,0 +1,6 @@
1
+ import { GlobalConfigProvider } from "../config-provider/type";
2
+ // TODO: Import from @tdesign/common-js when available
3
+ const ruRU = {} as GlobalConfigProvider;
4
+
5
+ // 需要 GlobalConfigProvider 保证数据类型正确
6
+ export default ruRU as unknown as GlobalConfigProvider;
@@ -0,0 +1,5 @@
1
+ import zhCN from "../global-config/locale/zh_CN";
2
+ import { GlobalConfigProvider } from "../config-provider/type";
3
+
4
+ // 需要 GlobalConfigProvider 保证数据类型正确
5
+ export default zhCN as unknown as GlobalConfigProvider;
@@ -0,0 +1,7 @@
1
+ import { GlobalConfigProvider } from "../config-provider/type";
2
+
3
+ // TODO: Import from @tdesign/common-js when available
4
+ const zhTW = {} as GlobalConfigProvider;
5
+
6
+ // 需要 GlobalConfigProvider 保证数据类型正确
7
+ export default zhTW;
@@ -1,5 +1,5 @@
1
1
  import React, { useCallback, useState } from "react";
2
- import { TdNotificationProps } from "./type";
2
+ import { TdNotificationProps, HeightItem } from "./type";
3
3
  import NotificationItem from "./NotifyItem";
4
4
  import useConfig from "../hooks/useConfig";
5
5
  export const GAP = 14;
@@ -32,7 +32,7 @@ const NotificationContainer = ({
32
32
  onHoverEnd();
33
33
  }, [onHoverEnd]);
34
34
 
35
- const [heights, setHeights] = useState<{ toastId: string; height: number }[]>([]);
35
+ const [heights, setHeights] = useState<HeightItem[]>([]);
36
36
 
37
37
  const { classPrefix: prefix } = useConfig();
38
38
 
@@ -1,6 +1,7 @@
1
1
  import React, { createContext, useState, useRef, useCallback, useContext } from "react";
2
2
  import { createPortal } from "react-dom";
3
3
  import NotifyContainer from "./NotifyContainer";
4
+ import { TdNotificationProps } from "./type";
4
5
 
5
6
  // 1. 定义类型
6
7
  type NotificationType = "success" | "error" | "warning" | "info";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tendaui/components",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "TendaUI React Components - Source code",
5
5
  "main": "index.ts",
6
6
  "module": "index.ts",
@@ -46,7 +46,10 @@
46
46
  ],
47
47
  "sideEffects": [
48
48
  "**/*.scss",
49
- "**/*.css"
49
+ "**/*.css",
50
+ "**/style/index.js",
51
+ "**/style/css.js",
52
+ "**/style/all.js"
50
53
  ],
51
- "gitHead": "31b15457f07146ef1604c713b32addd944fbb6dd"
54
+ "gitHead": "77c5b16410848a6dfee573581b602633306540cb"
52
55
  }
package/popup/Popup.tsx CHANGED
@@ -8,7 +8,7 @@ import useDefaultProps from "../hooks/useDefaultProps";
8
8
  import useMutationObserver from "../hooks/useMutationObserver";
9
9
  import useWindowSize from "../hooks/useWindowSize";
10
10
  import useTrigger from "./hooks/useTrigger";
11
- import type { TdPopupProps } from "./type";
11
+ import type { TdPopupProps, PopupVisibleChangeContext } from "./type";
12
12
  import usePopper from "../hooks/usePopper";
13
13
  import { popupDefaultProps } from "./defaultProps";
14
14
  import classNames from "classnames";
@@ -62,7 +62,28 @@ const Popup = forwardRef<PopupRef, PopupProps>((originalProps, ref) => {
62
62
 
63
63
  // 全局配置
64
64
  const { height: windowHeight, width: windowWidth } = useWindowSize();
65
- const [visible, onVisibleChange] = useControlled(props, "visible", props.onVisibleChange);
65
+ const handleVisibleChange = (visible: boolean, context: PopupVisibleChangeContext) => {
66
+ props.onVisibleChange?.(visible, context);
67
+ };
68
+ const [visible, onVisibleChangeInternal] = useControlled(props, "visible", handleVisibleChange);
69
+ // 适配 useTrigger 的类型
70
+ const onVisibleChangeForTrigger = (
71
+ visible: boolean,
72
+ context: {
73
+ e?:
74
+ | React.MouseEvent<HTMLElement>
75
+ | React.TouchEvent<HTMLElement>
76
+ | React.FocusEvent<HTMLElement>
77
+ | React.KeyboardEvent<HTMLElement>;
78
+ trigger: string;
79
+ }
80
+ ) => {
81
+ const popupContext: PopupVisibleChangeContext = {
82
+ e: context.e as any,
83
+ trigger: context.trigger as any
84
+ };
85
+ onVisibleChangeInternal(visible, popupContext);
86
+ };
66
87
  // 记录 popup 元素
67
88
  // 如果内容为 null 或 undefined,且 hideEmptyPopup 为 true,则不展示 popup
68
89
  const [popupElement, setPopupElement] = useState(null);
@@ -101,7 +122,7 @@ const Popup = forwardRef<PopupRef, PopupProps>((originalProps, ref) => {
101
122
  trigger,
102
123
  visible,
103
124
  delay,
104
- onVisibleChange
125
+ onVisibleChange: onVisibleChangeForTrigger
105
126
  });
106
127
  // 传入popperjs 配置选项
107
128
  const popperOptions = props.popperOptions as Options;
@@ -110,7 +131,7 @@ const Popup = forwardRef<PopupRef, PopupProps>((originalProps, ref) => {
110
131
  void _ignored;
111
132
 
112
133
  // popperRef 表示 popper 实例
113
- popperRef.current = usePopper(getRefDom(triggerRef), popupElement, {
134
+ popperRef.current = usePopper(getRefDom(triggerRef) as HTMLElement | null, popupElement, {
114
135
  placement: popperPlacement as Placement,
115
136
  ...restPopperOptions
116
137
  });
@@ -125,8 +146,9 @@ const Popup = forwardRef<PopupRef, PopupProps>((originalProps, ref) => {
125
146
 
126
147
  const updateTimeRef = useRef(null);
127
148
  // 监听 trigger 节点或内容变化动态更新 popup 定位
128
- useMutationObserver(getRefDom(triggerRef), () => {
129
- const isDisplayNone = getCssVarsValue("display", getRefDom(triggerRef)) === "none";
149
+ useMutationObserver(getRefDom(triggerRef) as HTMLElement | null, () => {
150
+ const triggerDom = getRefDom(triggerRef) as HTMLElement | null;
151
+ const isDisplayNone = triggerDom ? getCssVarsValue("display", triggerDom) === "none" : true;
130
152
  if (visible && !isDisplayNone) {
131
153
  clearTimeout(updateTimeRef.current);
132
154
  updateTimeRef.current = setTimeout(() => popperRef.current?.update?.(), 0);
@@ -177,8 +199,9 @@ const Popup = forwardRef<PopupRef, PopupProps>((originalProps, ref) => {
177
199
 
178
200
  // 整理浮层样式
179
201
  function getOverlayStyle(overlayStyle: TdPopupProps["overlayStyle"]) {
180
- if (getRefDom(triggerRef) && popupRef.current && typeof overlayStyle === "function") {
181
- return { ...overlayStyle(getRefDom(triggerRef), popupRef.current) };
202
+ const triggerDom = getRefDom(triggerRef) as HTMLElement | null;
203
+ if (triggerDom && popupRef.current && typeof overlayStyle === "function") {
204
+ return { ...overlayStyle(triggerDom, popupRef.current) };
182
205
  }
183
206
  return { ...overlayStyle };
184
207
  }
@@ -194,7 +217,7 @@ const Popup = forwardRef<PopupRef, PopupProps>((originalProps, ref) => {
194
217
  onExited={handleExited}
195
218
  classNames={`${classPrefix}-portal`}
196
219
  >
197
- <Portal triggerNode={getRefDom(triggerRef)} attach="body" ref={portalRef}>
220
+ <Portal triggerNode={getRefDom(triggerRef) as HTMLElement | null} attach="body" ref={portalRef}>
198
221
  <CSSTransition appear timeout={0} in={visible} nodeRef={popupRef} classNames={`${classPrefix}-popup`}>
199
222
  <div
200
223
  ref={(node) => {
@@ -247,7 +270,8 @@ const Popup = forwardRef<PopupRef, PopupProps>((originalProps, ref) => {
247
270
  getPopupElement: () => popupRef.current,
248
271
  getPortalElement: () => portalRef.current,
249
272
  getPopupContentElement: () => contentRef.current,
250
- setVisible: (visible: boolean) => onVisibleChange(visible, { trigger: "document" })
273
+ setVisible: (visible: boolean) =>
274
+ onVisibleChangeInternal(visible, { trigger: "document" } as PopupVisibleChangeContext)
251
275
  }));
252
276
  // 这里使用 React.Fragment 包裹 triggerNode 和 overlay,确保返回一个单一的父节点
253
277
  // 这样可以避免在渲染时出现多个根节点的错误
@@ -0,0 +1,24 @@
1
+ import React, { Ref, forwardRef } from "react";
2
+ import forwardRefWithStatics from "../utils/forwardRefWithStatics";
3
+ import Check, { CheckProps } from "../common/Check";
4
+ import RadioGroup from "./RadioGroup";
5
+ import { radioDefaultProps } from "./defaultProps";
6
+ import useDefaultProps from "../hooks/useDefaultProps";
7
+
8
+ export type RadioProps = Omit<CheckProps, "type">;
9
+ const RadioButton = forwardRef<HTMLLabelElement, RadioProps>((props, ref) => (
10
+ <Check ref={ref} type="radio-button" {...useDefaultProps<RadioProps>(props, radioDefaultProps)} />
11
+ ));
12
+ RadioButton.displayName = "RadioButton";
13
+ const Radio = forwardRefWithStatics(
14
+ (props: RadioProps, ref: Ref<HTMLLabelElement>) => (
15
+ <Check ref={ref} type="radio" {...useDefaultProps<RadioProps>(props, radioDefaultProps)} />
16
+ ),
17
+ {
18
+ Group: RadioGroup,
19
+ Button: RadioButton
20
+ }
21
+ );
22
+ Radio.displayName = "Radio";
23
+
24
+ export default Radio;
@@ -0,0 +1,159 @@
1
+ import React, { CSSProperties, ReactNode, useEffect, useRef, useState } from "react";
2
+ import classNames from "classnames";
3
+ import observe from "../common/observe";
4
+ import { CheckContext, type CheckContextValue } from "../common/Check";
5
+ import useCommonClassName from "../hooks/useCommonClassName";
6
+
7
+ import useConfig from "../hooks/useConfig";
8
+ import useControlled from "../hooks/useControlled";
9
+ import useDefaultProps from "../hooks/useDefaultProps";
10
+ import useMutationObserver from "../hooks/useMutationObserver";
11
+
12
+ import Radio from "./Radio";
13
+ import { radioGroupDefaultProps } from "./defaultProps";
14
+ import useKeyboard from "./useKeyboard";
15
+
16
+ import type { StyledProps } from "../common";
17
+ import type { TdRadioGroupProps } from "./type";
18
+
19
+ /**
20
+ * RadioGroup 组件所接收的属性
21
+ */
22
+ export interface RadioGroupProps extends TdRadioGroupProps, StyledProps {
23
+ children?: ReactNode;
24
+ }
25
+
26
+ /**
27
+ * 单选选项组,里面可以嵌套 <Radio />
28
+ */
29
+
30
+ const RadioGroup: React.FC<RadioGroupProps> = (originalProps) => {
31
+ const { classPrefix } = useConfig();
32
+ const props = useDefaultProps<RadioGroupProps>(originalProps, radioGroupDefaultProps);
33
+ const { disabled, readonly, children, onChange, size, variant, options = [], className, style, theme } = props;
34
+ const [internalValue, setInternalValue] = useControlled(props, "value", onChange);
35
+ const [barStyle, setBarStyle] = useState<Partial<CSSProperties> | null>(null);
36
+
37
+ const radioGroupRef = useRef<HTMLDivElement>(null);
38
+ const observerRef = useRef<IntersectionObserver>(null);
39
+ const handleKeyboardChange = (value: any, context: { e: KeyboardEvent }) => {
40
+ setInternalValue(value, { e: context.e as any, name: props.name });
41
+ };
42
+ useKeyboard(radioGroupRef, handleKeyboardChange);
43
+
44
+ const checkedRadioCls = `.${classPrefix}-radio-button.${classPrefix}-is-checked`;
45
+ const { SIZE: sizeMap } = useCommonClassName();
46
+
47
+ const context: CheckContextValue = {
48
+ inject: (checkProps) => {
49
+ if (typeof checkProps.checked !== "undefined") {
50
+ return checkProps;
51
+ }
52
+ const { value: checkValue } = checkProps;
53
+ return {
54
+ ...checkProps,
55
+ name: props.name,
56
+ // 有一个允许取消,就可以取消选中
57
+ allowUncheck: checkProps.allowUncheck || props.allowUncheck,
58
+ checked: internalValue === checkProps.value,
59
+ disabled: checkProps.disabled || disabled,
60
+ readonly: checkProps.readonly || readonly,
61
+ onChange(checked, { e }) {
62
+ if (typeof checkProps.onChange === "function") {
63
+ checkProps.onChange(checked, { e });
64
+ }
65
+ setInternalValue(checked ? checkValue : undefined, { e, name: props.name });
66
+ }
67
+ };
68
+ }
69
+ };
70
+
71
+ const calcBarStyle = () => {
72
+ if (!variant.includes("filled")) return;
73
+ const checkedRadio = radioGroupRef.current.querySelector?.(checkedRadioCls) as HTMLElement;
74
+ if (!checkedRadio) {
75
+ setBarStyle(null);
76
+ return;
77
+ }
78
+ const { offsetWidth, offsetHeight, offsetLeft, offsetTop } = checkedRadio;
79
+ setBarStyle({
80
+ width: `${offsetWidth}px`,
81
+ height: `${offsetHeight}px`,
82
+ left: `${offsetLeft}px`,
83
+ top: `${offsetTop}px`
84
+ });
85
+ };
86
+
87
+ // 针对子元素更新的场景,包括 value 变化等
88
+ useMutationObserver(radioGroupRef.current, (mutations) => {
89
+ // 排除高亮元素自身的变化,避免重复触发
90
+ const filteredMutations = mutations.filter((mutation) => {
91
+ const target = mutation.target as HTMLElement;
92
+ return !target.classList?.contains(`${classPrefix}-radio-group__bg-block`);
93
+ });
94
+ if (filteredMutations.length > 0) {
95
+ calcBarStyle();
96
+ }
97
+ });
98
+
99
+ useEffect(() => {
100
+ calcBarStyle();
101
+ if (!radioGroupRef.current) return;
102
+ // 针对父元素初始化时隐藏导致无法正确计算尺寸的问题
103
+ const observer = observe(radioGroupRef.current, null, calcBarStyle, 0);
104
+ observerRef.current = observer;
105
+ return () => {
106
+ observerRef.current?.disconnect();
107
+ observerRef.current = null;
108
+ };
109
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
110
+
111
+ const renderBlock = () => {
112
+ if (!variant.includes("filled") || !barStyle) {
113
+ return null;
114
+ }
115
+ return <div style={barStyle} className={`${classPrefix}-radio-group__bg-block`}></div>;
116
+ };
117
+
118
+ const renderOptions = () => {
119
+ const Comp = theme === "button" ? Radio.Button : Radio;
120
+ return options.map((item, index) => {
121
+ let label: ReactNode;
122
+ let value: string | number | boolean;
123
+ let disabled: boolean | undefined;
124
+ if (typeof item === "string" || typeof item === "number") {
125
+ label = item;
126
+ value = item;
127
+ } else {
128
+ label = item.label;
129
+ value = item.value;
130
+ disabled = item.disabled;
131
+ }
132
+ return (
133
+ <Comp value={value} key={index} disabled={disabled}>
134
+ {label}
135
+ </Comp>
136
+ );
137
+ });
138
+ };
139
+ return (
140
+ <CheckContext.Provider value={context}>
141
+ <div
142
+ ref={radioGroupRef}
143
+ style={style}
144
+ className={classNames(`${classPrefix}-radio-group`, sizeMap[size], className, {
145
+ [`${classPrefix}-radio-group__outline`]: variant === "outline",
146
+ [`${classPrefix}-radio-group--filled`]: variant.includes("filled"),
147
+ [`${classPrefix}-radio-group--primary-filled`]: variant === "primary-filled"
148
+ })}
149
+ >
150
+ {children || renderOptions()}
151
+ {renderBlock()}
152
+ </div>
153
+ </CheckContext.Provider>
154
+ );
155
+ };
156
+
157
+ RadioGroup.displayName = "RadioGroup";
158
+
159
+ export default RadioGroup;
@@ -0,0 +1,18 @@
1
+ import { TdRadioProps, TdRadioGroupProps } from "./type";
2
+
3
+ export const radioDefaultProps: TdRadioProps = {
4
+ allowUncheck: false,
5
+ defaultChecked: false,
6
+ disabled: undefined,
7
+ readonly: undefined,
8
+ value: undefined
9
+ };
10
+
11
+ export const radioGroupDefaultProps: TdRadioGroupProps = {
12
+ allowUncheck: false,
13
+ disabled: undefined,
14
+ readonly: undefined,
15
+ size: "medium",
16
+ variant: "outline",
17
+ theme: "radio"
18
+ };
package/radio/index.ts ADDED
@@ -0,0 +1,12 @@
1
+ import _Radio from "./Radio";
2
+
3
+ import "./style/index.js";
4
+
5
+ export type { RadioProps } from "./Radio";
6
+ export type { RadioGroupProps } from "./RadioGroup";
7
+ export * from "./type";
8
+
9
+ export const Radio = _Radio;
10
+ export const RadioGroup = _Radio.Group;
11
+
12
+ export default Radio;
File without changes
@@ -0,0 +1 @@
1
+ import "../../styles/components/radio/_index.scss";