@tendaui/components 1.2.4 → 1.3.1

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 (309) hide show
  1. package/_util/scroll.ts +9 -0
  2. package/alert/_example/base.tsx +13 -0
  3. package/alert/_example/collapse.tsx +15 -0
  4. package/badge/_example/base.tsx +10 -0
  5. package/badge/_example/count.tsx +29 -0
  6. package/badge/_example/custom-color.tsx +32 -0
  7. package/badge/_example/dot.tsx +26 -0
  8. package/badge/_example/max-count.tsx +26 -0
  9. package/badge/_example/offset.tsx +29 -0
  10. package/badge/_example/shape.tsx +32 -0
  11. package/badge/_example/show-zero.tsx +23 -0
  12. package/badge/_example/size.tsx +35 -0
  13. package/badge/_example/standalone.tsx +14 -0
  14. package/badge/_example/text-count.tsx +26 -0
  15. package/badge/_example/with-button.tsx +23 -0
  16. package/button/_example/block.tsx +18 -0
  17. package/button/_example/disabled.tsx +22 -0
  18. package/button/_example/ghost.tsx +21 -0
  19. package/button/_example/link.tsx +15 -0
  20. package/button/_example/loading.tsx +19 -0
  21. package/button/_example/shape.tsx +18 -0
  22. package/button/_example/size.tsx +18 -0
  23. package/button/_example/suffix.tsx +16 -0
  24. package/button/_example/theme.tsx +14 -0
  25. package/button/_example/variant-base.tsx +24 -0
  26. package/button/_example/variant-dashed.tsx +24 -0
  27. package/button/_example/variant-outline.tsx +24 -0
  28. package/button/_example/variant-text.tsx +24 -0
  29. package/checkbox/_example/base.tsx +8 -0
  30. package/checkbox/_example/controlled.tsx +11 -0
  31. package/checkbox/_example/group-disabled.tsx +13 -0
  32. package/checkbox/_example/group-with-check-all.tsx +22 -0
  33. package/checkbox/_example/group-with-max.tsx +17 -0
  34. package/checkbox/_example/group-with-options.tsx +18 -0
  35. package/checkbox/_example/group.tsx +17 -0
  36. package/checkbox/_example/states.tsx +19 -0
  37. package/color-picker/ColorPicker.tsx +16 -2
  38. package/color-picker/_example/base.tsx +12 -0
  39. package/color-picker/_example/borderless.tsx +17 -0
  40. package/color-picker/_example/clearable.tsx +12 -0
  41. package/color-picker/_example/disabled.tsx +17 -0
  42. package/color-picker/_example/formats.tsx +30 -0
  43. package/color-picker/_example/manual-input.tsx +39 -0
  44. package/color-picker/_example/recent-colors.tsx +19 -0
  45. package/color-picker/_example/swatch-colors.tsx +28 -0
  46. package/color-picker/_example/with-alpha.tsx +21 -0
  47. package/color-picker/components/panel/format/inputs.tsx +1 -1
  48. package/color-picker/components/panel/index.tsx +13 -0
  49. package/color-picker/components/trigger.tsx +64 -13
  50. package/color-picker/defaultProps.ts +4 -1
  51. package/color-picker/utils/color-picker/cmyk.ts +5 -5
  52. package/color-picker/utils/color-picker/draggable.ts +14 -15
  53. package/color-picker/utils/color-picker/format.ts +21 -26
  54. package/color-picker/utils/color-picker/gradient.ts +35 -41
  55. package/color-picker/utils/color-picker/types.ts +4 -4
  56. package/config-provider/ConfigContext.tsx +1 -0
  57. package/config-provider/ConfigProvider.tsx +18 -1
  58. package/config-provider/type.ts +5 -0
  59. package/dialog/_example/base.tsx +27 -0
  60. package/dialog/_example/confirm-loading.tsx +32 -0
  61. package/dialog/_example/custom-buttons.tsx +24 -0
  62. package/dialog/_example/full-screen.tsx +26 -0
  63. package/dialog/_example/hide-buttons.tsx +39 -0
  64. package/dialog/_example/modeless.tsx +25 -0
  65. package/dialog/_example/placement.tsx +40 -0
  66. package/dialog/_example/plugin-example.tsx +69 -0
  67. package/dialog/_example/themes.tsx +41 -0
  68. package/drawer/Drawer.tsx +17 -9
  69. package/drawer/_example/custom-header-footer.tsx +29 -0
  70. package/drawer/_example/default.tsx +20 -0
  71. package/drawer/_example/events.tsx +53 -0
  72. package/drawer/_example/no-footer.tsx +20 -0
  73. package/drawer/_example/no-overlay.tsx +20 -0
  74. package/drawer/_example/placement.tsx +43 -0
  75. package/drawer/_example/size-draggable.tsx +26 -0
  76. package/drawer/_example/size.tsx +40 -0
  77. package/drawer/defaultProps.ts +1 -1
  78. package/fireworks/Fireworks.tsx +1 -10
  79. package/fireworks/index.ts +0 -1
  80. package/fireworks/type.ts +0 -1
  81. package/form/_example/complex.tsx +76 -0
  82. package/form/_example/default.tsx +58 -0
  83. package/form/_example/disabled.tsx +26 -0
  84. package/form/_example/form-list.tsx +74 -0
  85. package/form/_example/inline-layout.tsx +20 -0
  86. package/form/_example/label-align.tsx +46 -0
  87. package/form/_example/methods.tsx +66 -0
  88. package/form/_example/validation.tsx +71 -0
  89. package/form/hooks/useFormItemStyle.tsx +19 -7
  90. package/form/index.ts +20 -2
  91. package/global-config/default-config.ts +28 -28
  92. package/global-config/locale/ar_KW.ts +176 -187
  93. package/global-config/locale/en_US.ts +180 -195
  94. package/global-config/locale/it_IT.ts +174 -197
  95. package/global-config/locale/ja_JP.ts +178 -193
  96. package/global-config/locale/ko_KR.ts +178 -193
  97. package/global-config/locale/ru_RU.ts +189 -200
  98. package/global-config/locale/zh_CN.ts +179 -193
  99. package/global-config/locale/zh_TW.ts +178 -192
  100. package/global-config/mobile/default-config.ts +3 -3
  101. package/global-config/mobile/locale/ar_KW.ts +76 -77
  102. package/global-config/mobile/locale/en_US.ts +76 -77
  103. package/global-config/mobile/locale/it_IT.ts +76 -77
  104. package/global-config/mobile/locale/ja_JP.ts +64 -65
  105. package/global-config/mobile/locale/ko_KR.ts +64 -65
  106. package/global-config/mobile/locale/ru_RU.ts +76 -77
  107. package/global-config/mobile/locale/zh_CN.ts +64 -65
  108. package/global-config/mobile/locale/zh_TW.ts +64 -65
  109. package/global-config/t.ts +12 -12
  110. package/hooks/useDebounce.ts +27 -0
  111. package/hooks/useLastest.ts +6 -2
  112. package/hooks/useResizeObserve.ts +0 -1
  113. package/index.ts +1 -1
  114. package/input/Input.tsx +53 -10
  115. package/input/_example/auto-width.tsx +14 -0
  116. package/input/_example/borderless.tsx +17 -0
  117. package/input/_example/clearable.tsx +14 -0
  118. package/input/_example/default.tsx +10 -0
  119. package/input/_example/disabled-readonly.tsx +12 -0
  120. package/input/_example/events.tsx +42 -0
  121. package/input/_example/group.tsx +14 -0
  122. package/input/_example/label-suffix.tsx +12 -0
  123. package/input/_example/max-length.tsx +11 -0
  124. package/input/_example/password.tsx +14 -0
  125. package/input/_example/sizes.tsx +12 -0
  126. package/input/_example/status.tsx +13 -0
  127. package/input/_example/text-align.tsx +12 -0
  128. package/input/_example/with-icon.tsx +13 -0
  129. package/input/type.ts +3 -0
  130. package/input/useLengthLimit.ts +122 -0
  131. package/input-number/_example/align.tsx +23 -0
  132. package/input-number/_example/auto-width.tsx +8 -0
  133. package/input-number/_example/default.tsx +8 -0
  134. package/input-number/_example/events.tsx +45 -0
  135. package/input-number/_example/format.tsx +27 -0
  136. package/input-number/_example/large-number.tsx +17 -0
  137. package/input-number/_example/min-max.tsx +14 -0
  138. package/input-number/_example/sizes.tsx +35 -0
  139. package/input-number/_example/status.tsx +65 -0
  140. package/input-number/_example/step-and-decimal.tsx +14 -0
  141. package/input-number/_example/themes.tsx +21 -0
  142. package/input-number/_example/with-suffix.tsx +12 -0
  143. package/ip-input/_example/controlled.tsx +26 -0
  144. package/ip-input/_example/default.tsx +12 -0
  145. package/ip-input/_example/full-featured.tsx +32 -0
  146. package/ip-input/_example/ipv6.tsx +23 -0
  147. package/ip-input/_example/keyboard-navigation.tsx +19 -0
  148. package/ip-input/_example/paste-demo.tsx +23 -0
  149. package/ip-input/_example/states.tsx +21 -0
  150. package/ip-input/_example/with-cidr.tsx +23 -0
  151. package/layout/_example/combine-left.tsx +54 -0
  152. package/layout/_example/combine-right.tsx +54 -0
  153. package/layout/_example/custom-aside-width.tsx +56 -0
  154. package/layout/_example/custom-height.tsx +45 -0
  155. package/layout/_example/double-sidebar.tsx +57 -0
  156. package/layout/_example/side-navigation-right.tsx +51 -0
  157. package/layout/_example/side-navigation.tsx +51 -0
  158. package/layout/_example/top-navigation.tsx +41 -0
  159. package/list/_example/async-loading.tsx +46 -0
  160. package/list/_example/default.tsx +23 -0
  161. package/list/_example/header-footer.tsx +40 -0
  162. package/list/_example/multiline.tsx +24 -0
  163. package/list/_example/scroll-loading.tsx +69 -0
  164. package/list/_example/sizes.tsx +45 -0
  165. package/list/_example/split.tsx +36 -0
  166. package/list/_example/stripe.tsx +24 -0
  167. package/list/_example/virtual-scroll.tsx +51 -0
  168. package/list/_example/with-image.tsx +26 -0
  169. package/loading/_example/default.tsx +6 -0
  170. package/loading/_example/delay.tsx +53 -0
  171. package/loading/_example/fullscreen.tsx +29 -0
  172. package/loading/_example/inherit-color.tsx +24 -0
  173. package/loading/_example/no-overlay.tsx +15 -0
  174. package/loading/_example/sizes.tsx +25 -0
  175. package/loading/_example/with-text.tsx +12 -0
  176. package/loading/_example/wrapper.tsx +30 -0
  177. package/notification/_example/default.tsx +31 -0
  178. package/notification/_example/long-content.tsx +37 -0
  179. package/notification/_example/stacking.tsx +40 -0
  180. package/notification/_example/types.tsx +78 -0
  181. package/notification/_example/usage-example.tsx +62 -0
  182. package/package.json +4 -3
  183. package/popup/Popup.tsx +17 -5
  184. package/popup/_example/controlled.tsx +32 -0
  185. package/popup/_example/custom-content.tsx +64 -0
  186. package/popup/_example/default.tsx +19 -0
  187. package/popup/_example/delay.tsx +35 -0
  188. package/popup/_example/disabled.tsx +17 -0
  189. package/popup/_example/no-arrow.tsx +17 -0
  190. package/popup/_example/placements.tsx +61 -0
  191. package/popup/_example/triggers.tsx +26 -0
  192. package/radio/_example/allow-uncheck.tsx +19 -0
  193. package/radio/_example/button-style.tsx +40 -0
  194. package/radio/_example/controlled.tsx +13 -0
  195. package/radio/_example/default.tsx +13 -0
  196. package/radio/_example/group-disabled.tsx +22 -0
  197. package/radio/_example/group-with-options.tsx +20 -0
  198. package/radio/_example/group.tsx +19 -0
  199. package/radio/_example/sizes.tsx +37 -0
  200. package/radio/_example/states.tsx +20 -0
  201. package/select/_example/collapsed.tsx +30 -0
  202. package/select/_example/creatable.tsx +36 -0
  203. package/select/_example/custom-content.tsx +26 -0
  204. package/select/_example/default.tsx +29 -0
  205. package/select/_example/disabled.tsx +20 -0
  206. package/select/_example/filterable.tsx +27 -0
  207. package/select/_example/group-options.tsx +44 -0
  208. package/select/_example/label-suffix.tsx +24 -0
  209. package/select/_example/loading.tsx +19 -0
  210. package/select/_example/multiple.tsx +31 -0
  211. package/select/_example/sizes.tsx +20 -0
  212. package/select/_example/status.tsx +27 -0
  213. package/slider/Slider.tsx +13 -5
  214. package/slider/_example/custom-label.tsx +19 -0
  215. package/slider/_example/default.tsx +14 -0
  216. package/slider/_example/disabled.tsx +17 -0
  217. package/slider/_example/marks.tsx +31 -0
  218. package/slider/_example/range.tsx +16 -0
  219. package/slider/_example/step.tsx +14 -0
  220. package/slider/_example/vertical.tsx +26 -0
  221. package/slider/_example/with-input-number.tsx +21 -0
  222. package/slider/type.ts +1 -1
  223. package/styles/_vars.scss +16 -0
  224. package/styles/components/button/_index.scss +3 -3
  225. package/styles/components/dialog/_index.scss +18 -20
  226. package/styles/components/drawer/_index.scss +4 -3
  227. package/styles/components/drawer/_var.scss +1 -1
  228. package/styles/components/form/_index.scss +7 -6
  229. package/styles/components/input/_mixins.scss +7 -5
  230. package/styles/components/input-number/_index.scss +13 -12
  231. package/styles/components/list/_index.scss +5 -5
  232. package/styles/components/notification/_index.scss +4 -4
  233. package/styles/components/slider/_index.scss +8 -8
  234. package/styles/components/switch/_index.scss +98 -15
  235. package/styles/components/table/_index.scss +37 -29
  236. package/styles/components/tabs/_index.scss +8 -9
  237. package/styles/components/tooltip/_index.scss +104 -0
  238. package/styles/components/tooltip/_vars.scss +23 -0
  239. package/switch/_example/async-change.tsx +25 -0
  240. package/switch/_example/before-change.tsx +22 -0
  241. package/switch/_example/controlled.tsx +14 -0
  242. package/switch/_example/custom-value.tsx +21 -0
  243. package/switch/_example/default.tsx +6 -0
  244. package/switch/_example/disabled.tsx +25 -0
  245. package/switch/_example/loading.tsx +17 -0
  246. package/switch/_example/sizes.tsx +21 -0
  247. package/switch/_example/with-label.tsx +21 -0
  248. package/tab/TabPanel.tsx +9 -6
  249. package/tab/_example/addable.tsx +45 -0
  250. package/tab/_example/card-theme.tsx +22 -0
  251. package/tab/_example/default.tsx +22 -0
  252. package/tab/_example/disabled.tsx +38 -0
  253. package/tab/_example/lazy.tsx +25 -0
  254. package/tab/_example/placement.tsx +36 -0
  255. package/tab/_example/removable.tsx +31 -0
  256. package/tab/_example/sizes.tsx +31 -0
  257. package/tab/_example/with-action.tsx +26 -0
  258. package/table/Cell.tsx +3 -6
  259. package/table/Ellipsis.tsx +73 -0
  260. package/table/_example/alignment.tsx +46 -0
  261. package/table/_example/auto-width.tsx +47 -0
  262. package/table/_example/bordered-stripe-hover.tsx +42 -0
  263. package/table/_example/bordered.tsx +42 -0
  264. package/table/_example/cell-click.tsx +52 -0
  265. package/table/_example/complex.tsx +82 -0
  266. package/table/_example/custom-cell.tsx +68 -0
  267. package/table/_example/custom-empty.tsx +37 -0
  268. package/table/_example/custom-row-class-name.tsx +57 -0
  269. package/table/_example/default.tsx +42 -0
  270. package/table/_example/ellipsis.tsx +56 -0
  271. package/table/_example/empty.tsx +28 -0
  272. package/table/_example/fixed-width.tsx +48 -0
  273. package/table/_example/hover.tsx +42 -0
  274. package/table/_example/row-click.tsx +52 -0
  275. package/table/_example/sizes.tsx +57 -0
  276. package/table/_example/stripe.tsx +42 -0
  277. package/table/_example/vertical-align.tsx +110 -0
  278. package/table/hooks/useTableClassName.ts +3 -3
  279. package/table/index.ts +2 -0
  280. package/table/type.ts +1 -0
  281. package/tag/Tag.tsx +1 -1
  282. package/tag/_example/closable.tsx +44 -0
  283. package/tag/_example/default.tsx +17 -0
  284. package/tag/_example/disabled.tsx +19 -0
  285. package/tag/_example/sizes.tsx +18 -0
  286. package/tag/_example/variants.tsx +37 -0
  287. package/tag-input/_example/collapsed.tsx +27 -0
  288. package/tag-input/_example/controlled-uncontrolled.tsx +26 -0
  289. package/tag-input/_example/default.tsx +15 -0
  290. package/tag-input/_example/disabled-readonly.tsx +21 -0
  291. package/tag-input/_example/events.tsx +64 -0
  292. package/tag-input/_example/excess-display.tsx +27 -0
  293. package/tag-input/_example/max-tags.tsx +22 -0
  294. package/tag-input/_example/sizes.tsx +21 -0
  295. package/tag-input/_example/status.tsx +37 -0
  296. package/tag-input/_example/with-label.tsx +23 -0
  297. package/tag-input/hooks/useTagList.tsx +1 -1
  298. package/tooltip/Tooltip.tsx +76 -0
  299. package/tooltip/_example/base.tsx +26 -0
  300. package/tooltip/_example/custom-content.tsx +47 -0
  301. package/tooltip/_example/placement.tsx +33 -0
  302. package/tooltip/_example/theme.tsx +34 -0
  303. package/tooltip/defaultProps.ts +14 -0
  304. package/tooltip/index.ts +7 -0
  305. package/tooltip/style/index.js +1 -0
  306. package/tooltip/type.ts +99 -0
  307. package/utils/log/index.ts +1 -1
  308. package/utils/log/log.ts +2 -3
  309. package/utils/log/types.ts +1 -4
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ import { Checkbox } from "@tendaui/react";
3
+
4
+ export default function GroupDisabled() {
5
+ return (
6
+ <Checkbox.Group defaultValue={["北京", "深圳"]} disabled>
7
+ <Checkbox value="北京">北京</Checkbox>
8
+ <Checkbox value="上海">上海</Checkbox>
9
+ <Checkbox value="广州">广州</Checkbox>
10
+ <Checkbox value="深圳">深圳</Checkbox>
11
+ </Checkbox.Group>
12
+ );
13
+ }
@@ -0,0 +1,22 @@
1
+ import React, { useState } from "react";
2
+ import { Checkbox } from "@tendaui/react";
3
+
4
+ export default function GroupWithCheckAll() {
5
+ const [value, setValue] = useState<string[]>(["上海"]);
6
+ const handleValueChange = (val) => {
7
+ console.log(val);
8
+ setValue(val);
9
+ };
10
+ return (
11
+ <div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
12
+ <div>当前选中:{value.filter((item) => item).join(", ")}</div>
13
+ <Checkbox.Group value={value} onChange={(val) => handleValueChange(val)}>
14
+ <Checkbox checkAll>全选</Checkbox>
15
+ <Checkbox value="北京">北京</Checkbox>
16
+ <Checkbox value="上海">上海</Checkbox>
17
+ <Checkbox value="广州">广州</Checkbox>
18
+ <Checkbox value="深圳">深圳</Checkbox>
19
+ </Checkbox.Group>
20
+ </div>
21
+ );
22
+ }
@@ -0,0 +1,17 @@
1
+ import React, { useState } from "react";
2
+ import { Checkbox } from "@tendaui/react";
3
+
4
+ export default function GroupWithMax() {
5
+ const [value, setValue] = useState<string[]>(["北京"]);
6
+ return (
7
+ <div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
8
+ <div>最多选择 2 项,当前选中:{value.join(", ") || "无"}</div>
9
+ <Checkbox.Group value={value} onChange={(val) => setValue(val as string[])} max={2}>
10
+ <Checkbox value="北京">北京</Checkbox>
11
+ <Checkbox value="上海">上海</Checkbox>
12
+ <Checkbox value="广州">广州</Checkbox>
13
+ <Checkbox value="深圳">深圳</Checkbox>
14
+ </Checkbox.Group>
15
+ </div>
16
+ );
17
+ }
@@ -0,0 +1,18 @@
1
+ import React, { useState } from "react";
2
+ import { Checkbox } from "@tendaui/react";
3
+
4
+ export default function GroupWithOptions() {
5
+ const [value, setValue] = useState<(string | number)[]>([2]);
6
+ const options = [
7
+ { label: "选项一", value: 1 },
8
+ { label: "选项二", value: 2 },
9
+ { label: "选项三", value: 3, disabled: true },
10
+ { label: "选项四", value: 4 }
11
+ ];
12
+ return (
13
+ <div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
14
+ <div>当前选中值:{JSON.stringify(value)}</div>
15
+ <Checkbox.Group options={options} value={value} onChange={(val) => setValue(val as (string | number)[])} />
16
+ </div>
17
+ );
18
+ }
@@ -0,0 +1,17 @@
1
+ import React, { useState } from "react";
2
+ import { Checkbox } from "@tendaui/react";
3
+
4
+ export default function Group() {
5
+ const [value, setValue] = useState<string[]>(["北京"]);
6
+ return (
7
+ <div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
8
+ <div>当前选中:{value.join(", ") || "无"}</div>
9
+ <Checkbox.Group value={value} onChange={(val) => setValue(val as string[])}>
10
+ <Checkbox value="北京">北京</Checkbox>
11
+ <Checkbox value="上海">上海</Checkbox>
12
+ <Checkbox value="广州">广州</Checkbox>
13
+ <Checkbox value="深圳">深圳</Checkbox>
14
+ </Checkbox.Group>
15
+ </div>
16
+ );
17
+ }
@@ -0,0 +1,19 @@
1
+ import React from "react";
2
+ import { Checkbox } from "@tendaui/react";
3
+
4
+ export default function States() {
5
+ return (
6
+ <div style={{ display: "flex", gap: "16px", flexWrap: "wrap" }}>
7
+ <Checkbox>未选中项</Checkbox>
8
+ <Checkbox defaultChecked>选中项</Checkbox>
9
+ <Checkbox indeterminate>半选状态</Checkbox>
10
+ <Checkbox disabled>未选禁用项</Checkbox>
11
+ <Checkbox disabled defaultChecked>
12
+ 选中禁用项
13
+ </Checkbox>
14
+ <Checkbox readonly defaultChecked>
15
+ 只读选中项
16
+ </Checkbox>
17
+ </div>
18
+ );
19
+ }
@@ -11,8 +11,18 @@ import useDefaultProps from "../hooks/useDefaultProps";
11
11
 
12
12
  const ColorPicker: React.FC<ColorPickerProps> = (props) => {
13
13
  const baseClassName = useClassName();
14
- const { popupProps, clearable, disabled, borderless, inputProps, onChange, onClear, ...panelProps } =
15
- useDefaultProps<ColorPickerProps>(props, colorPickerDefaultProps);
14
+ const {
15
+ popupProps,
16
+ clearable,
17
+ disabled,
18
+ borderless,
19
+ inputProps,
20
+ format,
21
+ enableAlpha,
22
+ onChange,
23
+ onClear,
24
+ ...panelProps
25
+ } = useDefaultProps<ColorPickerProps>(props, colorPickerDefaultProps);
16
26
  const { overlayClassName, overlayInnerStyle = {}, ...restPopupProps } = popupProps || {};
17
27
 
18
28
  const [innerValue, setInnerValue] = useControlled(props, "value", onChange);
@@ -40,6 +50,8 @@ const ColorPicker: React.FC<ColorPickerProps> = (props) => {
40
50
  {...panelProps}
41
51
  clearable={clearable}
42
52
  disabled={disabled}
53
+ format={format}
54
+ enableAlpha={enableAlpha}
43
55
  value={innerValue}
44
56
  onChange={(value: string, context: TdColorContext) => setInnerValue(value, context)}
45
57
  ref={colorPanelRef}
@@ -53,6 +65,8 @@ const ColorPicker: React.FC<ColorPickerProps> = (props) => {
53
65
  disabled={disabled}
54
66
  borderless={borderless}
55
67
  inputProps={inputProps}
68
+ format={format}
69
+ enableAlpha={enableAlpha}
56
70
  value={innerValue}
57
71
  onChange={setInnerValue}
58
72
  onClear={onClear}
@@ -0,0 +1,12 @@
1
+ import React, { useState } from "react";
2
+ import { ColorPicker } from "@tendaui/react";
3
+
4
+ export default function Base() {
5
+ const [color, setColor] = useState("#0052d9");
6
+ return (
7
+ <div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
8
+ <ColorPicker format="HEX" value={color} onChange={(v) => setColor(v)} />
9
+ <div>当前颜色值:{color}</div>
10
+ </div>
11
+ );
12
+ }
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import { ColorPicker } from "@tendaui/react";
3
+
4
+ export default function Borderless() {
5
+ return (
6
+ <div style={{ display: "flex", gap: "24px" }}>
7
+ <div>
8
+ <div style={{ marginBottom: "8px", color: "#666" }}>有边框</div>
9
+ <ColorPicker defaultValue="#0052d9" />
10
+ </div>
11
+ <div>
12
+ <div style={{ marginBottom: "8px", color: "#666" }}>无边框</div>
13
+ <ColorPicker borderless defaultValue="#0052d9" />
14
+ </div>
15
+ </div>
16
+ );
17
+ }
@@ -0,0 +1,12 @@
1
+ import React, { useState } from "react";
2
+ import { ColorPicker } from "@tendaui/react";
3
+
4
+ export default function Clearable() {
5
+ const [color, setColor] = useState("#0052d9");
6
+ return (
7
+ <div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
8
+ <ColorPicker clearable value={color} onChange={(v) => setColor(v)} onClear={() => setColor("")} />
9
+ <div>当前颜色值:{color || "(空)"}</div>
10
+ </div>
11
+ );
12
+ }
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import { ColorPicker } from "@tendaui/react";
3
+
4
+ export default function Disabled() {
5
+ return (
6
+ <div style={{ display: "flex", gap: "24px" }}>
7
+ <div>
8
+ <div style={{ marginBottom: "8px", color: "#666" }}>正常状态</div>
9
+ <ColorPicker defaultValue="#0052d9" />
10
+ </div>
11
+ <div>
12
+ <div style={{ marginBottom: "8px", color: "#666" }}>禁用状态</div>
13
+ <ColorPicker disabled defaultValue="#0052d9" />
14
+ </div>
15
+ </div>
16
+ );
17
+ }
@@ -0,0 +1,30 @@
1
+ import React, { useState } from "react";
2
+ import { ColorPicker } from "@tendaui/react";
3
+
4
+ export default function Formats() {
5
+ const [hexColor, setHexColor] = useState("#0052d9");
6
+ const [rgbColor, setRgbColor] = useState("rgb(0, 82, 217)");
7
+ const [hslColor, setHslColor] = useState("hsl(217, 100%, 43%)");
8
+
9
+ return (
10
+ <div style={{ display: "flex", flexDirection: "column", gap: "24px" }}>
11
+ <div>
12
+ <div style={{ marginBottom: "8px", color: "#666" }}>HEX 格式</div>
13
+ <ColorPicker format="HEX" value={hexColor} onChange={(v) => setHexColor(v)} />
14
+ <div style={{ marginTop: "8px", fontSize: "12px", color: "#999" }}>值:{hexColor}</div>
15
+ </div>
16
+
17
+ <div>
18
+ <div style={{ marginBottom: "8px", color: "#666" }}>RGB 格式</div>
19
+ <ColorPicker format="RGB" value={rgbColor} onChange={(v) => setRgbColor(v)} />
20
+ <div style={{ marginTop: "8px", fontSize: "12px", color: "#999" }}>值:{rgbColor}</div>
21
+ </div>
22
+
23
+ <div>
24
+ <div style={{ marginBottom: "8px", color: "#666" }}>HSL 格式</div>
25
+ <ColorPicker format="HSL" value={hslColor} onChange={(v) => setHslColor(v)} />
26
+ <div style={{ marginTop: "8px", fontSize: "12px", color: "#999" }}>值:{hslColor}</div>
27
+ </div>
28
+ </div>
29
+ );
30
+ }
@@ -0,0 +1,39 @@
1
+ import React, { useState } from "react";
2
+ import { ColorPicker } from "@tendaui/react";
3
+
4
+ export default function ManualInput() {
5
+ const [color, setColor] = useState("#0052d9");
6
+ return (
7
+ <div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
8
+ <div style={{ color: "#666", fontSize: "14px" }}>
9
+ <p style={{ margin: "0 0 8px 0" }}>
10
+ <strong>触发器输入框:</strong>在触发器中直接输入任意格式的颜色值,按回车或失焦后会自动转换为指定格式。
11
+ </p>
12
+ <p style={{ margin: "0" }}>
13
+ <strong>面板格式输入:</strong>
14
+ 打开颜色选择面板,可以通过格式选择器切换不同的输入格式(HEX/RGB/HSL/HSV/CMYK),并通过数值输入框精确调整颜色各分量的值。
15
+ </p>
16
+ </div>
17
+ <div style={{ display: "flex", gap: "24px", flexWrap: "wrap" }}>
18
+ <div>
19
+ <div style={{ marginBottom: "8px", color: "#666" }}>HEX 格式</div>
20
+ <ColorPicker format="HEX" value={color} onChange={(v) => setColor(v)} />
21
+ <div style={{ marginTop: "8px", fontSize: "12px", color: "#999" }}>
22
+ 触发器支持输入: rgb(255, 0, 0) 或 red
23
+ </div>
24
+ </div>
25
+ <div>
26
+ <div style={{ marginBottom: "8px", color: "#666" }}>RGB 格式(面板内可切换格式)</div>
27
+ <ColorPicker format="RGB" value={color} onChange={(v) => setColor(v)} />
28
+ <div style={{ marginTop: "8px", fontSize: "12px", color: "#999" }}>面板内支持 R/G/B 分量精确输入</div>
29
+ </div>
30
+ <div>
31
+ <div style={{ marginBottom: "8px", color: "#666" }}>带透明度(RGBA)</div>
32
+ <ColorPicker format="RGBA" enableAlpha value={color} onChange={(v) => setColor(v)} />
33
+ <div style={{ marginTop: "8px", fontSize: "12px", color: "#999" }}>面板内可调整透明度百分比</div>
34
+ </div>
35
+ </div>
36
+ <div>当前颜色值:{color}</div>
37
+ </div>
38
+ );
39
+ }
@@ -0,0 +1,19 @@
1
+ import React, { useState } from "react";
2
+ import { ColorPicker } from "@tendaui/react";
3
+
4
+ export default function RecentColors() {
5
+ const [color, setColor] = useState("#0052d9");
6
+ const [recentColors, setRecentColors] = useState<string[]>(["#ff0000", "#00ff00", "#0000ff"]);
7
+ return (
8
+ <div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
9
+ <ColorPicker
10
+ recentColors={recentColors}
11
+ onRecentColorsChange={setRecentColors}
12
+ value={color}
13
+ onChange={(v) => setColor(v)}
14
+ />
15
+ <div>当前颜色值:{color}</div>
16
+ <div>最近使用:{recentColors.join(", ")}</div>
17
+ </div>
18
+ );
19
+ }
@@ -0,0 +1,28 @@
1
+ import React, { useState } from "react";
2
+ import { ColorPicker } from "@tendaui/react";
3
+
4
+ export default function SwatchColors() {
5
+ const [color, setColor] = useState("#0052d9");
6
+ const customSwatchColors = [
7
+ "#ff0000",
8
+ "#ff7800",
9
+ "#ffff00",
10
+ "#00ff00",
11
+ "#00ffff",
12
+ "#0000ff",
13
+ "#8b00ff",
14
+ "#ff00ff",
15
+ "#000000",
16
+ "#333333",
17
+ "#666666",
18
+ "#999999",
19
+ "#cccccc",
20
+ "#ffffff"
21
+ ];
22
+ return (
23
+ <div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
24
+ <ColorPicker swatchColors={customSwatchColors} value={color} onChange={(v) => setColor(v)} />
25
+ <div>当前颜色值:{color}</div>
26
+ </div>
27
+ );
28
+ }
@@ -0,0 +1,21 @@
1
+ import React, { useState } from "react";
2
+ import { ColorPicker } from "@tendaui/react";
3
+
4
+ export default function WithAlpha() {
5
+ const [color, setColor] = useState("rgba(0, 82, 217, 0.8)");
6
+ return (
7
+ <div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
8
+ <ColorPicker format="RGBA" enableAlpha value={color} onChange={(v) => setColor(v)} />
9
+ <div>当前颜色值:{color}</div>
10
+ <div
11
+ style={{
12
+ width: "100px",
13
+ height: "40px",
14
+ backgroundColor: color,
15
+ borderRadius: "4px",
16
+ border: "1px solid #ddd"
17
+ }}
18
+ />
19
+ </div>
20
+ );
21
+ }
@@ -95,7 +95,7 @@ const FormatInputs = (props: TdColorFormatProps) => {
95
95
  {...commonProps}
96
96
  defaultValue={currentValue as string}
97
97
  key={`${inputKey.current}-${currentValue}`}
98
- maxlength={format === "HEX" ? 9 : undefined}
98
+ maxLength={format === "HEX" ? 9 : undefined}
99
99
  />
100
100
  ) : (
101
101
  <InputNumber
@@ -20,6 +20,7 @@ import AlphaSlider from "./alpha";
20
20
  import HueSlider from "./hue";
21
21
  import SaturationPanel from "./saturation";
22
22
  import SwatchesPanel from "./swatches";
23
+ import FormatPanel from "./format";
23
24
 
24
25
  const Panel = forwardRef<HTMLDivElement, ColorPickerProps>((props, ref) => {
25
26
  const baseClassName = useClassName();
@@ -33,6 +34,8 @@ const Panel = forwardRef<HTMLDivElement, ColorPickerProps>((props, ref) => {
33
34
  style,
34
35
  swatchColors,
35
36
  showPrimaryColorPreview,
37
+ inputProps,
38
+ selectInputProps,
36
39
  onChange,
37
40
  onPaletteBarChange
38
41
  } = useDefaultProps(props, colorPickerDefaultProps);
@@ -170,6 +173,16 @@ const Panel = forwardRef<HTMLDivElement, ColorPickerProps>((props, ref) => {
170
173
  ) : null}
171
174
  </div>
172
175
 
176
+ {/* 颜色格式输入区域 */}
177
+ <FormatPanel
178
+ {...baseProps}
179
+ format={format}
180
+ enableAlpha={enableAlpha}
181
+ inputProps={inputProps}
182
+ selectInputProps={selectInputProps}
183
+ onInputChange={() => emitColorChange("input")}
184
+ />
185
+
173
186
  {showSystemColors && (
174
187
  <div className={`${baseClassName}__swatches-wrap`}>
175
188
  {showSystemColors && (
@@ -1,30 +1,79 @@
1
- import React from "react";
1
+ import React, { useState, useCallback, useEffect } from "react";
2
2
  import classNames from "classnames";
3
3
  import { Color, getColorObject } from "../utils/color-picker/color";
4
+ import { initColorFormat } from "../utils/color-picker/format";
4
5
  import { Input } from "../../input";
5
6
  import { TdColorPickerProps } from "../type";
6
7
  import useClassName from "../hooks/useClassNames";
7
8
  import { TdColorContext } from "../type";
8
9
  import noop from "../../utils/noop";
10
+ import type { ColorFormat } from "../utils/color-picker/types";
9
11
 
10
12
  export interface ColorTriggerProps
11
- extends Pick<TdColorPickerProps, "disabled" | "inputProps" | "borderless" | "clearable" | "onClear"> {
13
+ extends Pick<
14
+ TdColorPickerProps,
15
+ "disabled" | "inputProps" | "borderless" | "clearable" | "onClear" | "format" | "enableAlpha"
16
+ > {
12
17
  value?: string;
13
18
  onChange?: (v?: string, context?: TdColorContext) => void;
14
19
  }
15
20
 
16
21
  const ColorPickerTrigger = (props: ColorTriggerProps) => {
17
22
  const baseClassName = useClassName();
18
- const { disabled = false, borderless = false, inputProps = { autoWidth: true }, clearable, onClear } = props;
19
-
20
- const handleChange = (input: string) => {
21
- if (input !== props.value) {
22
- props.onChange?.(input, {
23
- color: getColorObject(new Color(input)),
24
- trigger: "input"
25
- });
23
+ const {
24
+ disabled = false,
25
+ borderless = false,
26
+ inputProps = { autoWidth: true },
27
+ clearable,
28
+ onClear,
29
+ format = "RGB",
30
+ enableAlpha = false
31
+ } = props;
32
+
33
+ // 内部输入状态,用于处理用户输入
34
+ const [inputValue, setInputValue] = useState<string>(props.value || "");
35
+
36
+ // 同步外部 value 变化
37
+ useEffect(() => {
38
+ setInputValue(props.value || "");
39
+ }, [props.value]);
40
+
41
+ // 处理输入变化(实时更新内部状态)
42
+ const handleInputChange = useCallback((input: string) => {
43
+ setInputValue(input);
44
+ }, []);
45
+
46
+ // 处理失焦事件 - 验证并格式化颜色值
47
+ const handleBlur = useCallback(() => {
48
+ if (!inputValue) {
49
+ return;
26
50
  }
27
- };
51
+
52
+ // 验证颜色是否有效
53
+ if (Color.isValid(inputValue)) {
54
+ const colorInstance = new Color(inputValue);
55
+ const finalFormat = initColorFormat(format as ColorFormat, enableAlpha);
56
+ const formattedValue = colorInstance.getFormattedColor(finalFormat, enableAlpha);
57
+
58
+ // 如果格式化后的值与当前值不同,触发 onChange
59
+ if (formattedValue !== props.value) {
60
+ props.onChange?.(formattedValue, {
61
+ color: getColorObject(colorInstance),
62
+ trigger: "input"
63
+ });
64
+ }
65
+ // 更新显示值为格式化后的值
66
+ setInputValue(formattedValue);
67
+ } else {
68
+ // 如果颜色无效,恢复为之前的有效值
69
+ setInputValue(props.value || "");
70
+ }
71
+ }, [inputValue, props.value, props.onChange, format, enableAlpha]);
72
+
73
+ // 处理回车确认
74
+ const handleEnter = useCallback(() => {
75
+ handleBlur();
76
+ }, [handleBlur]);
28
77
 
29
78
  return (
30
79
  <div className={`${baseClassName}__trigger--default`}>
@@ -32,14 +81,16 @@ const ColorPickerTrigger = (props: ColorTriggerProps) => {
32
81
  borderless={borderless}
33
82
  clearable={clearable}
34
83
  {...inputProps}
35
- value={props.value}
84
+ value={inputValue}
36
85
  disabled={disabled}
37
86
  label={
38
87
  <div className={classNames(`${baseClassName}__trigger--default__color`, `${baseClassName}--bg-alpha`)}>
39
88
  <span className={"color-inner"} style={{ background: props.value }}></span>
40
89
  </div>
41
90
  }
42
- onChange={handleChange}
91
+ onChange={handleInputChange}
92
+ onBlur={handleBlur}
93
+ onEnter={handleEnter}
43
94
  onClear={onClear || noop}
44
95
  />
45
96
  </div>
@@ -3,5 +3,8 @@ import { TdColorPickerProps } from "./type";
3
3
  export const colorPickerDefaultProps: TdColorPickerProps = {
4
4
  borderless: false,
5
5
  clearable: false,
6
- disabled: false
6
+ disabled: false,
7
+ enableAlpha: false,
8
+ format: "RGB",
9
+ showPrimaryColorPreview: true
7
10
  };
@@ -11,9 +11,9 @@ export const rgb2cmyk = (red: number, green: number, blue: number) => {
11
11
  let computedY = 0;
12
12
  let computedK = 0;
13
13
 
14
- const r = parseInt(`${red}`.replace(/\s/g, ''), 10);
15
- const g = parseInt(`${green}`.replace(/\s/g, ''), 10);
16
- const b = parseInt(`${blue}`.replace(/\s/g, ''), 10);
14
+ const r = parseInt(`${red}`.replace(/\s/g, ""), 10);
15
+ const g = parseInt(`${green}`.replace(/\s/g, ""), 10);
16
+ const b = parseInt(`${blue}`.replace(/\s/g, ""), 10);
17
17
 
18
18
  if (r === 0 && g === 0 && b === 0) {
19
19
  computedK = 1;
@@ -61,7 +61,7 @@ export const cmyk2rgb = (cyan: number, magenta: number, yellow: number, black: n
61
61
  return {
62
62
  r,
63
63
  g,
64
- b,
64
+ b
65
65
  };
66
66
  };
67
67
 
@@ -76,7 +76,7 @@ const toNumber = (str: string) => Math.max(0, Math.min(255, parseInt(str, 10)));
76
76
  */
77
77
  export const cmykInputToColor = (input: string) => {
78
78
  if (/cmyk/i.test(input)) {
79
- const str = input.replace(/\s/g, '');
79
+ const str = input.replace(/\s/g, "");
80
80
  const match = str.match(REG_CMYK_STRING);
81
81
  const c = toNumber(match[1]);
82
82
  const m = toNumber(match[2]);
@@ -1,4 +1,3 @@
1
- /* eslint-disable no-use-before-define */
2
1
  export interface Coordinate {
3
2
  x: number;
4
3
  y: number;
@@ -26,7 +25,7 @@ interface DraggableHandles {
26
25
  const defaultsOptions: DraggableProps = {
27
26
  start: (coordinate: Coordinate, event: DraggableEvent) => {},
28
27
  drag: (coordinate: Coordinate, event: DraggableEvent) => {},
29
- end: (coordinate: Coordinate, event: DraggableEvent) => {},
28
+ end: (coordinate: Coordinate, event: DraggableEvent) => {}
30
29
  };
31
30
 
32
31
  export class Draggable {
@@ -44,9 +43,9 @@ export class Draggable {
44
43
  this.handles = {
45
44
  start: this.#dragStart.bind(this),
46
45
  drag: this.#drag.bind(this),
47
- end: this.#dragEnd.bind(this),
46
+ end: this.#dragEnd.bind(this)
48
47
  };
49
- this.$el.addEventListener('mousedown', this.handles.start, false);
48
+ this.$el.addEventListener("mousedown", this.handles.start, false);
50
49
  }
51
50
 
52
51
  #dragStart(event: DraggableEvent) {
@@ -54,9 +53,9 @@ export class Draggable {
54
53
  return;
55
54
  }
56
55
  // event.preventDefault();
57
- window.addEventListener('mousemove', this.handles.drag, false);
58
- window.addEventListener('mouseup', this.handles.end, false);
59
- window.addEventListener('contextmenu', this.handles.end, false);
56
+ window.addEventListener("mousemove", this.handles.drag, false);
57
+ window.addEventListener("mouseup", this.handles.end, false);
58
+ window.addEventListener("contextmenu", this.handles.end, false);
60
59
  this.dragging = true;
61
60
  this.props.start(this.#getCoordinate(event), event);
62
61
  }
@@ -73,9 +72,9 @@ export class Draggable {
73
72
  this.dragging = false;
74
73
  this.props.end(this.#getCoordinate(event), event);
75
74
  }, 0);
76
- window.removeEventListener('mousemove', this.handles.drag, false);
77
- window.removeEventListener('mouseup', this.handles.end, false);
78
- window.removeEventListener('contextmenu', this.handles.end, false);
75
+ window.removeEventListener("mousemove", this.handles.drag, false);
76
+ window.removeEventListener("mouseup", this.handles.end, false);
77
+ window.removeEventListener("contextmenu", this.handles.end, false);
79
78
  }
80
79
 
81
80
  #getCoordinate(event: DraggableEvent) {
@@ -85,15 +84,15 @@ export class Draggable {
85
84
  const top = mouseEvent.clientY - rect.top;
86
85
  return {
87
86
  y: Math.min(Math.max(0, top), rect.height),
88
- x: Math.min(Math.max(0, left), rect.width),
87
+ x: Math.min(Math.max(0, left), rect.width)
89
88
  };
90
89
  }
91
90
 
92
91
  destroy() {
93
- this.$el.removeEventListener('mousedown', this.handles.start, false);
94
- window.removeEventListener('mousemove', this.handles.drag, false);
95
- window.removeEventListener('mouseup', this.handles.end, false);
96
- window.removeEventListener('contextmenu', this.handles.end, false);
92
+ this.$el.removeEventListener("mousedown", this.handles.start, false);
93
+ window.removeEventListener("mousemove", this.handles.drag, false);
94
+ window.removeEventListener("mouseup", this.handles.end, false);
95
+ window.removeEventListener("contextmenu", this.handles.end, false);
97
96
  }
98
97
  }
99
98