@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,42 @@
1
+ import React, { useRef } from "react";
2
+ import classNames from "classnames";
3
+ import type { TdTabPanelProps } from "./type";
4
+ import { StyledProps } from "../common";
5
+ import { useTabClass } from "./useTabClass";
6
+ import { tabPanelDefaultProps } from "./defaultProps";
7
+ import useDefaultProps from "../hooks/useDefaultProps";
8
+
9
+ export interface TabPanelProps extends TdTabPanelProps, StyledProps {
10
+ children?: React.ReactNode;
11
+ isActive?: boolean;
12
+ }
13
+
14
+ const TabPanel: React.FC<TabPanelProps> = (props) => {
15
+ const { className, lazy, isActive, destroyOnHide, style } = useDefaultProps<TabPanelProps>(
16
+ props,
17
+ tabPanelDefaultProps
18
+ );
19
+ const { tdTabPanelClassPrefix } = useTabClass();
20
+ const lazyRenderRef = useRef(lazy);
21
+
22
+ if (lazy && isActive && lazyRenderRef.current) {
23
+ lazyRenderRef.current = false;
24
+ }
25
+
26
+ if ((!isActive && destroyOnHide) || lazyRenderRef.current) {
27
+ return null;
28
+ }
29
+
30
+ return (
31
+ <div
32
+ className={classNames(tdTabPanelClassPrefix, className)}
33
+ style={{ display: !isActive ? "none" : undefined, ...style }}
34
+ >
35
+ {props.children || props.panel}
36
+ </div>
37
+ );
38
+ };
39
+
40
+ TabPanel.displayName = "TabPanel";
41
+
42
+ export default TabPanel;
package/tab/Tabs.tsx ADDED
@@ -0,0 +1,71 @@
1
+ import { TabValue, TdTabsProps } from "./type";
2
+ import forwardRefWithStatics from "../utils/forwardRefWithStatics";
3
+ import TabNav from "./TabNav";
4
+ import TabPanel from "./TabPanel";
5
+ import classNames from "classnames";
6
+ import React from "react";
7
+ import { useTabClass } from "./useTabClass";
8
+ import { StyledProps } from "../common";
9
+ import { tabsDefaultProps } from "./defaultProps";
10
+ import useDefaultProps from "../hooks/useDefaultProps";
11
+ import useControlled from "../hooks/useControlled";
12
+
13
+ export interface TabsProps extends TdTabsProps, StyledProps {
14
+ children?: React.ReactNode;
15
+ }
16
+ const Tabs = forwardRefWithStatics(
17
+ (originalProps: TabsProps, ref: React.Ref<HTMLDivElement>) => {
18
+ const props = useDefaultProps<TabsProps>(originalProps, tabsDefaultProps);
19
+ const { children, list, placement, dragSort, className, style, onRemove } = props;
20
+ const [value, onChange] = useControlled(props, "value", props.onChange);
21
+ const { tdTabsClassPrefix, tdTabsClassGenerator, tdClassGenerator } = useTabClass();
22
+ const targetClassNameRegExpStr = `^${tdTabsClassPrefix}(__nav-item|__nav-item-wrapper|__nav-item-text-wrapper)`;
23
+ const memoChildren = React.useMemo<React.ReactNode | React.ReactNode[]>(() => {
24
+ if (!list || list.length === 0) {
25
+ return children;
26
+ }
27
+ return list.map<React.ReactNode>((panelProps) => <TabPanel key={panelProps.value} {...panelProps} />);
28
+ }, [children, list]);
29
+
30
+ const itemList = React.Children.map(memoChildren, (child: React.ReactElement<any>) => {
31
+ if (child && child.type === TabPanel) {
32
+ return child.props;
33
+ }
34
+ return null;
35
+ });
36
+
37
+ const handleChange = React.useCallback(
38
+ (v: TabValue) => {
39
+ onChange?.(v);
40
+ },
41
+ [onChange]
42
+ );
43
+
44
+ const headerNode = React.useMemo<React.ReactNode>(
45
+ () => (
46
+ <div className={classNames(tdTabsClassGenerator("header"), tdClassGenerator(`is-${placement}`))}>
47
+ <TabNav {...props} activeValue={value} onRemove={onRemove} itemList={itemList} onChange={handleChange} />
48
+ </div>
49
+ ),
50
+ [props, value, onRemove, itemList, handleChange, placement, tdTabsClassGenerator, tdClassGenerator]
51
+ );
52
+
53
+ return (
54
+ <div ref={ref} className={classNames(tdTabsClassPrefix, className)} style={style}>
55
+ {headerNode}
56
+ <div className={classNames(tdTabsClassGenerator("content"), tdClassGenerator(`is-${placement}`))}>
57
+ {React.Children.map(memoChildren, (child: any) => {
58
+ if (child && child.type === TabPanel) {
59
+ return <TabPanel {...child.props} isActive={child.props.value === value} />;
60
+ }
61
+ return null;
62
+ })}
63
+ </div>
64
+ </div>
65
+ );
66
+ },
67
+ { TabPanel }
68
+ );
69
+ Tabs.displayName = "Tabs";
70
+
71
+ export default Tabs;
@@ -0,0 +1,19 @@
1
+ import { TdTabsProps, TdTabPanelProps } from "./type";
2
+
3
+ export const tabsDefaultProps: TdTabsProps = {
4
+ addable: false,
5
+ disabled: false,
6
+ dragSort: false,
7
+ placement: "top",
8
+ scrollPosition: "auto",
9
+ size: "medium",
10
+ theme: "normal"
11
+ };
12
+
13
+ export const tabPanelDefaultProps: TdTabPanelProps = {
14
+ destroyOnHide: true,
15
+ disabled: false,
16
+ draggable: true,
17
+ lazy: false,
18
+ removable: false
19
+ };
package/tab/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ import _Tabs from "./Tabs";
2
+ import TabPanel from "./TabPanel";
3
+ import "./style/index";
4
+ export * from "./type";
5
+ export const Tabs = _Tabs;
6
+ export { TabPanel };
7
+ export default Tabs;
@@ -0,0 +1 @@
1
+ import "../../styles/components/tabs/_index.scss";
package/tab/type.ts ADDED
@@ -0,0 +1,125 @@
1
+ import { TNode } from "../common";
2
+ import { MouseEvent } from "react";
3
+
4
+ export interface TdTabsProps {
5
+ /**
6
+ * 选项卡右侧的操作区域
7
+ */
8
+ action?: TNode;
9
+ /**
10
+ * 选项卡是否可增加
11
+ * @default false
12
+ */
13
+ addable?: boolean;
14
+ /**
15
+ * 是否禁用选项卡
16
+ * @default false
17
+ */
18
+ disabled?: boolean;
19
+ /**
20
+ * 是否开启拖拽调整顺序
21
+ * @default false
22
+ */
23
+ dragSort?: boolean;
24
+ /**
25
+ * 选项卡列表
26
+ */
27
+ list?: Array<TdTabPanelProps>;
28
+ /**
29
+ * 选项卡位置
30
+ * @default top
31
+ */
32
+ placement?: "left" | "top" | "bottom" | "right";
33
+ /**
34
+ * Tab较多的时候,选中滑块滚动最终停留的位置
35
+ * @default auto
36
+ */
37
+ scrollPosition?: "auto" | "start" | "center" | "end";
38
+ /**
39
+ * 组件尺寸
40
+ * @default medium
41
+ */
42
+ size?: "medium" | "large";
43
+ /**
44
+ * 选项卡风格,包含 默认风格 和 卡片风格两种
45
+ * @default normal
46
+ */
47
+ theme?: "normal" | "card";
48
+ /**
49
+ * 激活的选项卡值
50
+ */
51
+ value?: TabValue;
52
+ /**
53
+ * 激活的选项卡值,非受控属性
54
+ */
55
+ defaultValue?: TabValue;
56
+ /**
57
+ * 添加选项卡时触发
58
+ */
59
+ onAdd?: (context: { e: MouseEvent<HTMLDivElement> }) => void;
60
+ /**
61
+ * 激活的选项卡发生变化时触发
62
+ */
63
+ onChange?: (value: TabValue) => void;
64
+ /**
65
+ * 拖拽排序时触发
66
+ */
67
+ onDragSort?: (context: TabsDragSortContext) => void;
68
+ /**
69
+ * 删除选项卡时触发
70
+ */
71
+ onRemove?: (options: { value: TabValue; index: number; e: MouseEvent<HTMLSpanElement> }) => void;
72
+ }
73
+
74
+ export interface TdTabPanelProps {
75
+ /**
76
+ * 选项卡内容隐藏时是否销毁
77
+ * @default true
78
+ */
79
+ destroyOnHide?: boolean;
80
+ /**
81
+ * 是否禁用当前选项卡
82
+ * @default false
83
+ */
84
+ disabled?: boolean;
85
+ /**
86
+ * 选项卡组件开启允许拖动排序时,当前选项卡是否允许拖动
87
+ * @default true
88
+ */
89
+ draggable?: boolean;
90
+ /**
91
+ * 选项卡名称,可自定义选项卡导航内容
92
+ */
93
+ label?: TNode;
94
+ /**
95
+ * 是否启用选项卡懒加载
96
+ * @default false
97
+ */
98
+ lazy?: boolean;
99
+ /**
100
+ * 用于自定义选项卡面板内容
101
+ */
102
+ panel?: TNode;
103
+ /**
104
+ * 当前选项卡是否允许移除
105
+ * @default false
106
+ */
107
+ removable?: boolean;
108
+ /**
109
+ * 选项卡的值,唯一标识
110
+ */
111
+ value?: TabValue;
112
+ /**
113
+ * 点击删除按钮时触发
114
+ */
115
+ onRemove?: (options: { value: TabValue; e: MouseEvent<HTMLSpanElement> }) => void;
116
+ }
117
+
118
+ export type TabValue = string | number;
119
+
120
+ export interface TabsDragSortContext {
121
+ currentIndex: number;
122
+ current: TabValue;
123
+ targetIndex: number;
124
+ target: TabValue;
125
+ }
@@ -0,0 +1,20 @@
1
+ import useConfig from "../hooks/useConfig";
2
+
3
+ export const useTabClass = () => {
4
+ const { classPrefix } = useConfig();
5
+ const tdTabsClassPrefix = `${classPrefix}-tabs`;
6
+ const tdTabPanelClassPrefix = `${classPrefix}-tab-panel`;
7
+ const tdClassGenerator = (append: string) => `${classPrefix}-${append}`;
8
+ const tdTabsClassGenerator = (append: string) => `${tdTabsClassPrefix}__${append}`;
9
+ const tdTabPanelClassGenerator = (append: string) => `${tdTabPanelClassPrefix}__${append}`;
10
+ const tdSizeClassGenerator = (size: "medium" | "large") => `${classPrefix}-size-${size === "large" ? "l" : "m"}`;
11
+
12
+ return {
13
+ tdTabsClassPrefix,
14
+ tdTabPanelClassPrefix,
15
+ tdClassGenerator,
16
+ tdTabsClassGenerator,
17
+ tdTabPanelClassGenerator,
18
+ tdSizeClassGenerator
19
+ };
20
+ };
package/table/Cell.tsx ADDED
@@ -0,0 +1,109 @@
1
+ import React, { MouseEvent } from "react";
2
+ import classNames from "classnames";
3
+ import { isFunction, get } from "lodash-es";
4
+ import useConfig from "../hooks/useConfig";
5
+ import { BaseTableCellParams, TableRowData } from "./type";
6
+
7
+ export interface CellProps<T extends TableRowData = TableRowData> {
8
+ cellParams: BaseTableCellParams<T>;
9
+ cellEmptyContent?: React.ReactNode | ((params: BaseTableCellParams<T>) => React.ReactNode);
10
+ onClick?: (e: React.MouseEvent<HTMLElement>) => void;
11
+ }
12
+
13
+ /**
14
+ * 渲染单元格内容
15
+ */
16
+ export function renderCell<T extends TableRowData = TableRowData>(
17
+ params: BaseTableCellParams<T>,
18
+ extra?: {
19
+ cellEmptyContent?: React.ReactNode | ((params: BaseTableCellParams<T>) => React.ReactNode);
20
+ }
21
+ ): React.ReactNode {
22
+ const { col, row } = params;
23
+
24
+ // 如果列配置了自定义渲染函数
25
+ if (isFunction(col.cell)) {
26
+ return col.cell(params);
27
+ }
28
+
29
+ if (isFunction(col.render)) {
30
+ return col.render(params);
31
+ }
32
+
33
+ // 如果列配置了字符串或 ReactNode
34
+ if (col.cell && !isFunction(col.cell)) {
35
+ return col.cell;
36
+ }
37
+
38
+ // 默认从 row 数据中获取值
39
+ const value = get(row, col.colKey) as React.ReactNode;
40
+
41
+ // 处理空值
42
+ if (value === undefined || value === null || value === "") {
43
+ if (extra?.cellEmptyContent) {
44
+ return isFunction(extra.cellEmptyContent) ? extra.cellEmptyContent(params) : extra.cellEmptyContent;
45
+ }
46
+ }
47
+
48
+ return value;
49
+ }
50
+
51
+ const Cell = <T extends TableRowData = TableRowData>(props: CellProps<T>) => {
52
+ const { cellParams, cellEmptyContent, onClick } = props;
53
+ const { col, colIndex } = cellParams;
54
+ const { classPrefix } = useConfig();
55
+
56
+ const cellNode = renderCell(cellParams, { cellEmptyContent });
57
+
58
+ // 处理省略文本
59
+ const isEllipsis = Boolean(col.ellipsis);
60
+ const cellContent = isEllipsis ? (
61
+ <div
62
+ className={`${classPrefix}-table__ellipsis`}
63
+ title={String(cellNode)}
64
+ style={{ width: "100%", overflow: "hidden" }}
65
+ >
66
+ {cellNode}
67
+ </div>
68
+ ) : (
69
+ cellNode
70
+ );
71
+
72
+ // 处理类名
73
+ const customClasses = isFunction(col.className) ? col.className(cellParams) : col.className;
74
+
75
+ const classes = classNames(customClasses, {
76
+ [`${classPrefix}-table__cell--ellipsis`]: isEllipsis,
77
+ [`${classPrefix}-align-left`]: col.align === "left" || !col.align,
78
+ [`${classPrefix}-align-center`]: col.align === "center",
79
+ [`${classPrefix}-align-right`]: col.align === "right"
80
+ });
81
+
82
+ // 处理属性
83
+ const attrs = isFunction(col.attrs) ? col.attrs(cellParams) : col.attrs || {};
84
+
85
+ // 处理单元格样式
86
+ const cellStyle: React.CSSProperties = {};
87
+ if (col.width) {
88
+ cellStyle.width = typeof col.width === "number" ? `${col.width}px` : col.width;
89
+ }
90
+ if (col.minWidth) {
91
+ cellStyle.minWidth = typeof col.minWidth === "number" ? `${col.minWidth}px` : col.minWidth;
92
+ }
93
+
94
+ return (
95
+ <td
96
+ key={col.colKey || colIndex}
97
+ className={classes || undefined}
98
+ style={Object.keys(cellStyle).length > 0 ? cellStyle : undefined}
99
+ {...attrs}
100
+ onClick={onClick}
101
+ >
102
+ {cellContent}
103
+ </td>
104
+ );
105
+ };
106
+
107
+ Cell.displayName = "Cell";
108
+
109
+ export default Cell;
@@ -0,0 +1,77 @@
1
+ import React from "react";
2
+ import { get } from "lodash-es";
3
+ import useConfig from "../hooks/useConfig";
4
+ import { useLocaleReceiver } from "../locale/LocalReceiver";
5
+ import { TableRowData, BaseTableCol, BaseTableCellParams } from "./type";
6
+ import TR from "./TR";
7
+
8
+ export interface TBodyProps<T extends TableRowData = TableRowData> {
9
+ data: T[];
10
+ columns: BaseTableCol<T>[];
11
+ rowKey: string;
12
+ rowClassName?: string | ((params: { row: T; rowIndex: number }) => string);
13
+ rowAttributes?: Record<string, unknown> | ((params: { row: T; rowIndex: number }) => Record<string, unknown>);
14
+ cellEmptyContent?: React.ReactNode | ((params: BaseTableCellParams<T>) => React.ReactNode);
15
+ empty?: React.ReactNode;
16
+ onRowClick?: (params: { row: T; rowIndex: number; e: React.MouseEvent<HTMLTableRowElement> }) => void;
17
+ onCellClick?: (params: BaseTableCellParams<T>) => void;
18
+ }
19
+
20
+ const TBody = <T extends TableRowData = TableRowData>(props: TBodyProps<T>) => {
21
+ const { data, columns, rowKey, rowClassName, rowAttributes, cellEmptyContent, empty, onRowClick, onCellClick } =
22
+ props;
23
+ const { classPrefix } = useConfig();
24
+ const [local, t] = useLocaleReceiver("table");
25
+ const emptyText = typeof local.empty === "string" ? t(local.empty) : local.empty;
26
+
27
+ // 空数据渲染
28
+ const renderEmpty = () => {
29
+ if (empty !== undefined) {
30
+ return (
31
+ <tr className={`${classPrefix}-table__empty-row`}>
32
+ <td colSpan={columns.length}>
33
+ <div className={`${classPrefix}-table__empty`}>{empty}</div>
34
+ </td>
35
+ </tr>
36
+ );
37
+ }
38
+ return (
39
+ <tr className={`${classPrefix}-table__empty-row`}>
40
+ <td colSpan={columns.length}>
41
+ <div className={`${classPrefix}-table__empty`}>{emptyText}</div>
42
+ </td>
43
+ </tr>
44
+ );
45
+ };
46
+
47
+ // 如果没有数据,显示空状态
48
+ if (!data || data.length === 0) {
49
+ return <tbody className={`${classPrefix}-table__body`}>{renderEmpty()}</tbody>;
50
+ }
51
+
52
+ // 渲染数据行
53
+ const rows = data.map((row, rowIndex) => {
54
+ const rowKeyValue = get(row, rowKey);
55
+ const key = typeof rowKeyValue === "string" || typeof rowKeyValue === "number" ? rowKeyValue : rowIndex;
56
+ return (
57
+ <TR
58
+ key={key}
59
+ row={row}
60
+ rowIndex={rowIndex}
61
+ columns={columns}
62
+ rowKey={rowKey}
63
+ rowClassName={rowClassName}
64
+ rowAttributes={rowAttributes}
65
+ cellEmptyContent={cellEmptyContent}
66
+ onRowClick={onRowClick}
67
+ onCellClick={onCellClick}
68
+ />
69
+ );
70
+ });
71
+
72
+ return <tbody className={`${classPrefix}-table__body`}>{rows}</tbody>;
73
+ };
74
+
75
+ TBody.displayName = "TBody";
76
+
77
+ export default TBody;
@@ -0,0 +1,63 @@
1
+ import React from "react";
2
+ import classNames from "classnames";
3
+ import { isFunction } from "lodash-es";
4
+ import useConfig from "../hooks/useConfig";
5
+ import { BaseTableCol, TableRowData, BaseTableHeadCellParams } from "./type";
6
+
7
+ export interface THeadProps<T extends TableRowData = TableRowData> {
8
+ columns: BaseTableCol<T>[];
9
+ }
10
+
11
+ /**
12
+ * 渲染表头标题
13
+ */
14
+ function renderTitle<T extends TableRowData = TableRowData>(col: BaseTableCol<T>, colIndex: number): React.ReactNode {
15
+ const params: BaseTableHeadCellParams<T> = { col, colIndex };
16
+
17
+ if (isFunction(col.title)) {
18
+ return col.title(params);
19
+ }
20
+
21
+ return col.title || "";
22
+ }
23
+
24
+ const THead = <T extends TableRowData = TableRowData>(props: THeadProps<T>) => {
25
+ const { columns } = props;
26
+ const { classPrefix } = useConfig();
27
+
28
+ const thList = columns.map((col, colIndex) => {
29
+ const title = renderTitle(col, colIndex);
30
+ const customClasses = isFunction(col.className)
31
+ ? col.className({ row: {} as T, rowIndex: -1, col, colIndex })
32
+ : col.className;
33
+
34
+ const classes = classNames(customClasses, {
35
+ [`${classPrefix}-align-left`]: col.align === "left" || !col.align,
36
+ [`${classPrefix}-align-center`]: col.align === "center",
37
+ [`${classPrefix}-align-right`]: col.align === "right"
38
+ });
39
+
40
+ const attrs = isFunction(col.attrs) ? col.attrs({ row: {} as T, rowIndex: -1, col, colIndex }) : col.attrs || {};
41
+
42
+ return (
43
+ <th
44
+ key={col.colKey || colIndex}
45
+ className={classes || undefined}
46
+ style={col.width ? { width: typeof col.width === "number" ? `${col.width}px` : col.width } : undefined}
47
+ {...attrs}
48
+ >
49
+ {title}
50
+ </th>
51
+ );
52
+ });
53
+
54
+ return (
55
+ <thead className={`${classPrefix}-table__header`}>
56
+ <tr>{thList}</tr>
57
+ </thead>
58
+ );
59
+ };
60
+
61
+ THead.displayName = "THead";
62
+
63
+ export default THead;
package/table/TR.tsx ADDED
@@ -0,0 +1,78 @@
1
+ import React, { MouseEvent } from "react";
2
+ import classNames from "classnames";
3
+ import { isFunction } from "lodash-es";
4
+ import { TableRowData, BaseTableCol, BaseTableCellParams } from "./type";
5
+ import Cell from "./Cell";
6
+
7
+ export interface TRProps<T extends TableRowData = TableRowData> {
8
+ row: T;
9
+ rowIndex: number;
10
+ columns: BaseTableCol<T>[];
11
+ rowKey: string;
12
+ rowClassName?: string | ((params: { row: T; rowIndex: number }) => string);
13
+ rowAttributes?: Record<string, unknown> | ((params: { row: T; rowIndex: number }) => Record<string, unknown>);
14
+ cellEmptyContent?: React.ReactNode | ((params: BaseTableCellParams<T>) => React.ReactNode);
15
+ onRowClick?: (params: { row: T; rowIndex: number; e: MouseEvent<HTMLTableRowElement> }) => void;
16
+ onCellClick?: (params: BaseTableCellParams<T>) => void;
17
+ }
18
+
19
+ const TR = <T extends TableRowData = TableRowData>(props: TRProps<T>) => {
20
+ const { row, rowIndex, columns, rowClassName, rowAttributes, cellEmptyContent, onRowClick, onCellClick } = props;
21
+
22
+ // 处理行类名
23
+ const customRowClassName = isFunction(rowClassName) ? rowClassName({ row, rowIndex }) : rowClassName;
24
+
25
+ const rowClasses = classNames(customRowClassName);
26
+
27
+ // 处理行属性
28
+ const customRowAttributes = isFunction(rowAttributes) ? rowAttributes({ row, rowIndex }) : rowAttributes || {};
29
+
30
+ // 处理单元格点击
31
+ const handleCellClick = (e: React.MouseEvent<HTMLElement>, col: BaseTableCol<T>, colIndex: number) => {
32
+ if (onCellClick) {
33
+ onCellClick({
34
+ row,
35
+ rowIndex,
36
+ col,
37
+ colIndex,
38
+ e
39
+ });
40
+ }
41
+ };
42
+
43
+ // 处理行点击
44
+ const handleRowClick = (e: MouseEvent<HTMLTableRowElement>) => {
45
+ if (onRowClick) {
46
+ onRowClick({ row, rowIndex, e });
47
+ }
48
+ };
49
+
50
+ // 渲染单元格
51
+ const cells = columns.map((col, colIndex) => {
52
+ const cellParams: BaseTableCellParams<T> = {
53
+ row,
54
+ rowIndex,
55
+ col,
56
+ colIndex
57
+ };
58
+
59
+ return (
60
+ <Cell
61
+ key={col.colKey || colIndex}
62
+ cellParams={cellParams}
63
+ cellEmptyContent={cellEmptyContent}
64
+ onClick={(e) => handleCellClick(e, col, colIndex)}
65
+ />
66
+ );
67
+ });
68
+
69
+ return (
70
+ <tr className={rowClasses || undefined} {...customRowAttributes} onClick={handleRowClick}>
71
+ {cells}
72
+ </tr>
73
+ );
74
+ };
75
+
76
+ TR.displayName = "TR";
77
+
78
+ export default TR;
@@ -0,0 +1,73 @@
1
+ import React, { forwardRef } from "react";
2
+ import useConfig from "../hooks/useConfig";
3
+ import useDefaultProps from "../hooks/useDefaultProps";
4
+ import { BaseTableProps, TableRowData } from "./type";
5
+ import { tableDefaultProps } from "./defaultProps";
6
+ import { useTableStyle, formatCSSUnit } from "./hooks";
7
+ import THead from "./THead";
8
+ import TBody from "./TBody";
9
+
10
+ export interface TableProps<T extends TableRowData = TableRowData>
11
+ extends Omit<React.HTMLAttributes<HTMLDivElement>, "onClick">,
12
+ BaseTableProps<T> {}
13
+
14
+ const TableComponent = forwardRef<HTMLDivElement, TableProps<TableRowData>>((originalProps, ref) => {
15
+ const props = useDefaultProps<TableProps<TableRowData>>(originalProps, tableDefaultProps);
16
+ const {
17
+ columns = [],
18
+ data = [],
19
+ rowKey = "id",
20
+ showHeader = true,
21
+ empty,
22
+ cellEmptyContent,
23
+ rowClassName,
24
+ rowAttributes,
25
+ onRowClick,
26
+ onCellClick,
27
+ ...restProps
28
+ } = props;
29
+
30
+ const { classPrefix } = useConfig();
31
+ const { tableClasses, tableContentStyles, tableElementStyles } = useTableStyle(props);
32
+
33
+ return (
34
+ <div ref={ref} className={tableClasses} style={tableElementStyles} {...restProps}>
35
+ <div className={`${classPrefix}-table__content`} style={tableContentStyles}>
36
+ <table className={`${classPrefix}-table__table`} style={{ tableLayout: props.tableLayout || "fixed" }}>
37
+ <colgroup>
38
+ {columns.map((col, index) => {
39
+ const colStyle: React.CSSProperties = {};
40
+ if (col.width) {
41
+ colStyle.width = formatCSSUnit(col.width);
42
+ }
43
+ if (col.minWidth) {
44
+ colStyle.minWidth = formatCSSUnit(col.minWidth);
45
+ }
46
+ return <col key={col.colKey || index} style={colStyle} />;
47
+ })}
48
+ </colgroup>
49
+ {showHeader && <THead columns={columns} />}
50
+ <TBody
51
+ data={data}
52
+ columns={columns}
53
+ rowKey={rowKey}
54
+ rowClassName={rowClassName}
55
+ rowAttributes={rowAttributes}
56
+ cellEmptyContent={cellEmptyContent}
57
+ empty={empty}
58
+ onRowClick={onRowClick}
59
+ onCellClick={onCellClick}
60
+ />
61
+ </table>
62
+ </div>
63
+ </div>
64
+ );
65
+ });
66
+
67
+ TableComponent.displayName = "Table";
68
+
69
+ const Table = TableComponent as <T extends TableRowData = TableRowData>(
70
+ props: TableProps<T> & React.RefAttributes<HTMLDivElement>
71
+ ) => React.ReactElement;
72
+
73
+ export default Table;