@teamix-evo/ui 0.1.1 → 0.3.0

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 (295) hide show
  1. package/README.md +184 -184
  2. package/manifest.json +680 -492
  3. package/package.json +20 -10
  4. package/src/components/accordion/accordion.meta.md +5 -4
  5. package/src/components/accordion/accordion.stories.tsx +14 -9
  6. package/src/components/accordion/accordion.tsx +104 -8
  7. package/src/components/affix/affix.meta.md +20 -2
  8. package/src/components/affix/affix.stories.tsx +102 -25
  9. package/src/components/affix/affix.tsx +79 -9
  10. package/src/components/alert/alert.meta.md +44 -13
  11. package/src/components/alert/alert.stories.tsx +66 -21
  12. package/src/components/alert/alert.tsx +81 -34
  13. package/src/components/alert-dialog/alert-dialog.meta.md +61 -16
  14. package/src/components/alert-dialog/alert-dialog.stories.tsx +145 -3
  15. package/src/components/alert-dialog/alert-dialog.tsx +60 -13
  16. package/src/components/anchor/anchor.meta.md +8 -3
  17. package/src/components/anchor/anchor.stories.tsx +3 -3
  18. package/src/components/anchor/anchor.tsx +2 -2
  19. package/src/components/app/app.meta.md +9 -4
  20. package/src/components/app/app.stories.tsx +9 -7
  21. package/src/components/aspect-ratio/aspect-ratio.meta.md +4 -3
  22. package/src/components/aspect-ratio/aspect-ratio.stories.tsx +3 -3
  23. package/src/components/auto-complete/auto-complete.meta.md +14 -6
  24. package/src/components/auto-complete/auto-complete.stories.tsx +47 -4
  25. package/src/components/auto-complete/auto-complete.tsx +119 -71
  26. package/src/components/avatar/avatar.meta.md +6 -7
  27. package/src/components/avatar/avatar.stories.tsx +21 -3
  28. package/src/components/avatar/avatar.tsx +24 -23
  29. package/src/components/badge/badge.meta.md +10 -9
  30. package/src/components/badge/badge.stories.tsx +2 -2
  31. package/src/components/badge/badge.tsx +9 -15
  32. package/src/components/breadcrumb/breadcrumb.meta.md +27 -7
  33. package/src/components/breadcrumb/breadcrumb.stories.tsx +127 -4
  34. package/src/components/breadcrumb/breadcrumb.tsx +22 -8
  35. package/src/components/button/button.meta.md +258 -21
  36. package/src/components/button/button.stories.tsx +549 -41
  37. package/src/components/button/button.tsx +335 -33
  38. package/src/components/button/demo/as-child.tsx +24 -0
  39. package/src/components/button/demo/basic.tsx +8 -0
  40. package/src/components/button/demo/block.tsx +16 -0
  41. package/src/components/button/demo/loading.tsx +19 -0
  42. package/src/components/button/demo/shapes.tsx +18 -0
  43. package/src/components/button/demo/sizes.tsx +19 -0
  44. package/src/components/button/demo/variants.tsx +19 -0
  45. package/src/components/button/demo/with-icon.tsx +20 -0
  46. package/src/components/calendar/calendar.meta.md +13 -3
  47. package/src/components/calendar/calendar.stories.tsx +6 -6
  48. package/src/components/calendar/calendar.tsx +73 -8
  49. package/src/components/card/card.meta.md +27 -5
  50. package/src/components/card/card.stories.tsx +42 -3
  51. package/src/components/card/card.tsx +146 -63
  52. package/src/components/carousel/carousel.meta.md +4 -3
  53. package/src/components/carousel/carousel.stories.tsx +11 -6
  54. package/src/components/cascader/cascader.meta.md +47 -17
  55. package/src/components/cascader/cascader.stories.tsx +22 -10
  56. package/src/components/cascader/cascader.tsx +428 -85
  57. package/src/components/checkbox/checkbox.meta.md +75 -7
  58. package/src/components/checkbox/checkbox.stories.tsx +161 -3
  59. package/src/components/checkbox/checkbox.tsx +77 -9
  60. package/src/components/collapsible/collapsible.meta.md +14 -6
  61. package/src/components/collapsible/collapsible.stories.tsx +10 -2
  62. package/src/components/collapsible/collapsible.tsx +93 -6
  63. package/src/components/color-picker/color-picker.meta.md +12 -7
  64. package/src/components/color-picker/color-picker.stories.tsx +86 -7
  65. package/src/components/color-picker/color-picker.tsx +20 -9
  66. package/src/components/command/command.meta.md +29 -13
  67. package/src/components/command/command.stories.tsx +4 -4
  68. package/src/components/command/command.tsx +19 -8
  69. package/src/components/context-menu/context-menu.meta.md +11 -8
  70. package/src/components/context-menu/context-menu.stories.tsx +11 -3
  71. package/src/components/context-menu/context-menu.tsx +21 -8
  72. package/src/components/data-table/data-table.meta.md +6 -5
  73. package/src/components/data-table/data-table.stories.tsx +13 -6
  74. package/src/components/data-table/data-table.tsx +2 -2
  75. package/src/components/date-picker/date-picker.meta.md +88 -19
  76. package/src/components/date-picker/date-picker.stories.tsx +55 -5
  77. package/src/components/date-picker/date-picker.tsx +1489 -91
  78. package/src/components/descriptions/descriptions.meta.md +10 -5
  79. package/src/components/descriptions/descriptions.stories.tsx +3 -3
  80. package/src/components/descriptions/descriptions.tsx +22 -14
  81. package/src/components/dialog/dialog.meta.md +76 -13
  82. package/src/components/dialog/dialog.stories.tsx +182 -20
  83. package/src/components/dialog/dialog.tsx +67 -15
  84. package/src/components/dialog/imperative.tsx +252 -0
  85. package/src/components/drawer/drawer.meta.md +33 -34
  86. package/src/components/drawer/drawer.stories.tsx +29 -12
  87. package/src/components/drawer/drawer.tsx +22 -113
  88. package/src/components/dropdown-menu/dropdown-menu.meta.md +78 -10
  89. package/src/components/dropdown-menu/dropdown-menu.stories.tsx +88 -2
  90. package/src/components/dropdown-menu/dropdown-menu.tsx +24 -10
  91. package/src/components/ellipsis/ellipsis.meta.md +87 -0
  92. package/src/components/ellipsis/ellipsis.stories.tsx +72 -0
  93. package/src/components/ellipsis/ellipsis.tsx +153 -0
  94. package/src/components/empty/empty.meta.md +9 -4
  95. package/src/components/empty/empty.stories.tsx +4 -4
  96. package/src/components/empty/empty.tsx +10 -3
  97. package/src/components/field/field.meta.md +47 -9
  98. package/src/components/field/field.stories.tsx +385 -5
  99. package/src/components/field/field.tsx +263 -35
  100. package/src/components/filter-bar/filter-bar.meta.md +92 -0
  101. package/src/components/filter-bar/filter-bar.stories.tsx +1083 -0
  102. package/src/components/filter-bar/filter-bar.tsx +568 -0
  103. package/src/components/flex/flex.meta.md +54 -6
  104. package/src/components/flex/flex.stories.tsx +107 -20
  105. package/src/components/flex/flex.tsx +27 -4
  106. package/src/components/float-button/float-button.meta.md +8 -3
  107. package/src/components/float-button/float-button.stories.tsx +9 -7
  108. package/src/components/float-button/float-button.tsx +1 -1
  109. package/src/components/form/form.meta.md +39 -17
  110. package/src/components/form/form.stories.tsx +350 -3
  111. package/src/components/form/form.tsx +101 -35
  112. package/src/components/grid/grid.meta.md +7 -2
  113. package/src/components/grid/grid.stories.tsx +6 -4
  114. package/src/components/hover-card/hover-card.meta.md +20 -9
  115. package/src/components/hover-card/hover-card.stories.tsx +34 -5
  116. package/src/components/hover-card/hover-card.tsx +51 -13
  117. package/src/components/icon/DEVELOPMENT.md +809 -0
  118. package/src/components/icon/icon.meta.md +170 -0
  119. package/src/components/icon/icon.stories.tsx +344 -0
  120. package/src/components/icon/icon.tsx +248 -0
  121. package/src/components/image/image.meta.md +9 -4
  122. package/src/components/image/image.stories.tsx +3 -3
  123. package/src/components/image/image.tsx +6 -4
  124. package/src/components/input/demo/basic.tsx +12 -0
  125. package/src/components/input/demo/clearable.tsx +21 -0
  126. package/src/components/input/demo/show-count.tsx +18 -0
  127. package/src/components/input/demo/sizes.tsx +15 -0
  128. package/src/components/input/input.meta.md +39 -33
  129. package/src/components/input/input.stories.tsx +62 -35
  130. package/src/components/input/input.tsx +97 -98
  131. package/src/components/input-group/input-group.meta.md +54 -22
  132. package/src/components/input-group/input-group.stories.tsx +49 -16
  133. package/src/components/input-group/input-group.tsx +44 -8
  134. package/src/components/input-number/input-number.meta.md +64 -7
  135. package/src/components/input-number/input-number.stories.tsx +46 -8
  136. package/src/components/input-number/input-number.tsx +99 -26
  137. package/src/components/input-otp/input-otp.meta.md +4 -3
  138. package/src/components/input-otp/input-otp.stories.tsx +3 -3
  139. package/src/components/input-otp/input-otp.tsx +1 -1
  140. package/src/components/item/item.meta.md +8 -3
  141. package/src/components/item/item.stories.tsx +8 -5
  142. package/src/components/item/item.tsx +7 -6
  143. package/src/components/kbd/kbd.meta.md +13 -4
  144. package/src/components/kbd/kbd.stories.tsx +4 -4
  145. package/src/components/kbd/kbd.tsx +10 -5
  146. package/src/components/label/label.meta.md +18 -10
  147. package/src/components/label/label.stories.tsx +64 -6
  148. package/src/components/label/label.tsx +91 -19
  149. package/src/components/masonry/masonry.meta.md +8 -3
  150. package/src/components/masonry/masonry.stories.tsx +7 -5
  151. package/src/components/masonry/masonry.tsx +1 -0
  152. package/src/components/mentions/mentions.meta.md +36 -6
  153. package/src/components/mentions/mentions.stories.tsx +120 -6
  154. package/src/components/mentions/mentions.tsx +11 -5
  155. package/src/components/menubar/menubar.meta.md +30 -12
  156. package/src/components/menubar/menubar.stories.tsx +62 -2
  157. package/src/components/menubar/menubar.tsx +9 -9
  158. package/src/components/native-select/native-select.meta.md +8 -3
  159. package/src/components/native-select/native-select.stories.tsx +8 -5
  160. package/src/components/native-select/native-select.tsx +1 -1
  161. package/src/components/navigation-menu/navigation-menu.meta.md +19 -9
  162. package/src/components/navigation-menu/navigation-menu.stories.tsx +112 -9
  163. package/src/components/navigation-menu/navigation-menu.tsx +8 -4
  164. package/src/components/notification/notification.meta.md +52 -10
  165. package/src/components/notification/notification.stories.tsx +11 -9
  166. package/src/components/notification/notification.tsx +36 -21
  167. package/src/components/page-header/DEVELOPMENT.md +842 -0
  168. package/src/components/page-header/page-header.meta.md +208 -0
  169. package/src/components/page-header/page-header.stories.tsx +421 -0
  170. package/src/components/page-header/page-header.tsx +281 -0
  171. package/src/components/pagination/pagination.meta.md +140 -37
  172. package/src/components/pagination/pagination.stories.tsx +232 -10
  173. package/src/components/pagination/pagination.tsx +355 -63
  174. package/src/components/popconfirm/popconfirm.meta.md +9 -4
  175. package/src/components/popconfirm/popconfirm.stories.tsx +3 -4
  176. package/src/components/popconfirm/popconfirm.tsx +2 -2
  177. package/src/components/popover/popover.meta.md +62 -5
  178. package/src/components/popover/popover.stories.tsx +83 -7
  179. package/src/components/popover/popover.tsx +77 -28
  180. package/src/components/progress/progress.meta.md +38 -6
  181. package/src/components/progress/progress.stories.tsx +3 -3
  182. package/src/components/progress/progress.tsx +24 -16
  183. package/src/components/radio-group/radio-group.meta.md +79 -7
  184. package/src/components/radio-group/radio-group.stories.tsx +39 -3
  185. package/src/components/radio-group/radio-group.tsx +149 -18
  186. package/src/components/rate/rate.meta.md +35 -4
  187. package/src/components/rate/rate.stories.tsx +13 -5
  188. package/src/components/rate/rate.tsx +37 -10
  189. package/src/components/resizable/resizable.meta.md +7 -4
  190. package/src/components/resizable/resizable.stories.tsx +6 -6
  191. package/src/components/resizable/resizable.tsx +1 -1
  192. package/src/components/result/result.meta.md +7 -2
  193. package/src/components/result/result.stories.tsx +4 -8
  194. package/src/components/result/result.tsx +24 -15
  195. package/src/components/scroll-area/scroll-area.meta.md +4 -3
  196. package/src/components/scroll-area/scroll-area.stories.tsx +12 -4
  197. package/src/components/scroll-area/scroll-area.tsx +3 -3
  198. package/src/components/segmented/segmented.meta.md +7 -4
  199. package/src/components/segmented/segmented.stories.tsx +37 -8
  200. package/src/components/segmented/segmented.tsx +15 -7
  201. package/src/components/select/select.meta.md +197 -52
  202. package/src/components/select/select.stories.tsx +238 -63
  203. package/src/components/select/select.tsx +718 -171
  204. package/src/components/separator/separator.meta.md +4 -3
  205. package/src/components/separator/separator.stories.tsx +3 -3
  206. package/src/components/separator/separator.tsx +3 -7
  207. package/src/components/sheet/sheet.meta.md +32 -16
  208. package/src/components/sheet/sheet.stories.tsx +116 -10
  209. package/src/components/sheet/sheet.tsx +116 -29
  210. package/src/components/sidebar/sidebar.meta.md +37 -18
  211. package/src/components/sidebar/sidebar.stories.tsx +701 -29
  212. package/src/components/sidebar/sidebar.tsx +615 -142
  213. package/src/components/skeleton/skeleton.meta.md +4 -5
  214. package/src/components/skeleton/skeleton.stories.tsx +4 -4
  215. package/src/components/skeleton/skeleton.tsx +7 -7
  216. package/src/components/slider/slider.meta.md +57 -5
  217. package/src/components/slider/slider.stories.tsx +58 -6
  218. package/src/components/slider/slider.tsx +154 -13
  219. package/src/components/sonner/sonner.meta.md +58 -7
  220. package/src/components/sonner/sonner.stories.tsx +78 -5
  221. package/src/components/sonner/sonner.tsx +137 -8
  222. package/src/components/spinner/spinner.meta.md +62 -13
  223. package/src/components/spinner/spinner.stories.tsx +66 -14
  224. package/src/components/spinner/spinner.tsx +111 -9
  225. package/src/components/statistic/statistic.meta.md +7 -2
  226. package/src/components/statistic/statistic.stories.tsx +3 -7
  227. package/src/components/statistic/statistic.tsx +5 -6
  228. package/src/components/steps/steps.meta.md +18 -4
  229. package/src/components/steps/steps.stories.tsx +43 -3
  230. package/src/components/steps/steps.tsx +15 -12
  231. package/src/components/switch/switch.meta.md +51 -5
  232. package/src/components/switch/switch.stories.tsx +6 -6
  233. package/src/components/switch/switch.tsx +109 -41
  234. package/src/components/table/table.meta.md +17 -6
  235. package/src/components/table/table.stories.tsx +10 -5
  236. package/src/components/table/table.tsx +4 -4
  237. package/src/components/tabs/tabs.meta.md +38 -25
  238. package/src/components/tabs/tabs.stories.tsx +111 -25
  239. package/src/components/tabs/tabs.tsx +125 -54
  240. package/src/components/tag/tag.meta.md +105 -40
  241. package/src/components/tag/tag.stories.tsx +189 -16
  242. package/src/components/tag/tag.tsx +222 -21
  243. package/src/components/textarea/textarea.meta.md +35 -19
  244. package/src/components/textarea/textarea.stories.tsx +32 -6
  245. package/src/components/textarea/textarea.tsx +33 -9
  246. package/src/components/time-picker/time-picker.meta.md +124 -32
  247. package/src/components/time-picker/time-picker.stories.tsx +85 -15
  248. package/src/components/time-picker/time-picker.tsx +913 -61
  249. package/src/components/timeline/timeline.meta.md +14 -6
  250. package/src/components/timeline/timeline.stories.tsx +37 -7
  251. package/src/components/timeline/timeline.tsx +35 -14
  252. package/src/components/toggle/toggle.meta.md +5 -4
  253. package/src/components/toggle/toggle.stories.tsx +4 -4
  254. package/src/components/toggle/toggle.tsx +4 -3
  255. package/src/components/toggle-group/toggle-group.meta.md +5 -4
  256. package/src/components/toggle-group/toggle-group.stories.tsx +3 -3
  257. package/src/components/toggle-group/toggle-group.tsx +2 -2
  258. package/src/components/tooltip/tooltip.meta.md +55 -5
  259. package/src/components/tooltip/tooltip.stories.tsx +42 -5
  260. package/src/components/tooltip/tooltip.tsx +81 -21
  261. package/src/components/tour/tour.meta.md +9 -4
  262. package/src/components/tour/tour.stories.tsx +3 -3
  263. package/src/components/tour/tour.tsx +4 -4
  264. package/src/components/transfer/transfer.meta.md +11 -6
  265. package/src/components/transfer/transfer.stories.tsx +4 -8
  266. package/src/components/transfer/transfer.tsx +28 -21
  267. package/src/components/tree/tree.meta.md +63 -5
  268. package/src/components/tree/tree.stories.tsx +31 -12
  269. package/src/components/tree/tree.tsx +9 -8
  270. package/src/components/tree-select/tree-select.meta.md +59 -8
  271. package/src/components/tree-select/tree-select.stories.tsx +3 -3
  272. package/src/components/tree-select/tree-select.tsx +42 -7
  273. package/src/components/typography/typography.meta.md +61 -14
  274. package/src/components/typography/typography.stories.tsx +12 -11
  275. package/src/components/typography/typography.tsx +43 -28
  276. package/src/components/upload/upload.meta.md +49 -4
  277. package/src/components/upload/upload.stories.tsx +72 -12
  278. package/src/components/upload/upload.tsx +170 -37
  279. package/src/components/watermark/watermark.meta.md +7 -2
  280. package/src/components/watermark/watermark.stories.tsx +101 -9
  281. package/src/components/watermark/watermark.tsx +1 -0
  282. package/src/hooks/use-breakpoint.ts +117 -0
  283. package/src/hooks/use-debounce-callback.ts +52 -0
  284. package/src/hooks/use-mobile.ts +23 -0
  285. package/src/stories/theme-tokens.stories.tsx +747 -0
  286. package/src/utils/trigger-input.ts +53 -0
  287. package/src/components/button-group/button-group.meta.md +0 -92
  288. package/src/components/button-group/button-group.stories.tsx +0 -90
  289. package/src/components/button-group/button-group.tsx +0 -75
  290. package/src/components/combobox/combobox.meta.md +0 -93
  291. package/src/components/combobox/combobox.stories.tsx +0 -55
  292. package/src/components/combobox/combobox.tsx +0 -130
  293. package/src/components/space/space.meta.md +0 -94
  294. package/src/components/space/space.stories.tsx +0 -94
  295. package/src/components/space/space.tsx +0 -106
@@ -177,12 +177,12 @@ const TreeRow: React.FC<NodeProps> = ({
177
177
  <li role="treeitem" aria-expanded={hasChildren ? isOpen : undefined}>
178
178
  <div
179
179
  className={cn(
180
- 'flex items-center gap-2 rounded-md py-1 pr-2 text-sm transition-colors',
181
- selectable && !node.disabled && 'hover:bg-accent',
182
- isSelected && 'bg-accent text-accent-foreground',
180
+ 'group/tree-row flex items-center gap-1.5 rounded-md py-1 pr-2 text-xs transition-colors',
181
+ selectable && !node.disabled && 'hover:bg-accent/50',
182
+ isSelected && 'bg-accent font-medium text-accent-foreground',
183
183
  node.disabled && 'cursor-not-allowed opacity-50',
184
184
  )}
185
- style={{ paddingLeft: `${depth * 16 + 4}px` }}
185
+ style={{ paddingLeft: `${depth * 20 + 4}px` }}
186
186
  >
187
187
  {hasChildren ? (
188
188
  <button
@@ -190,11 +190,11 @@ const TreeRow: React.FC<NodeProps> = ({
190
190
  aria-label={isOpen ? '收起' : '展开'}
191
191
  onClick={() => onToggleExpand(node.key)}
192
192
  disabled={node.disabled}
193
- className="flex size-5 shrink-0 items-center justify-center rounded-sm transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
193
+ className="flex size-5 shrink-0 items-center justify-center rounded-sm text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
194
194
  >
195
195
  <ChevronRight
196
196
  className={cn(
197
- 'size-3.5 transition-transform',
197
+ 'size-3 transition-transform duration-150',
198
198
  isOpen && 'rotate-90',
199
199
  )}
200
200
  />
@@ -282,7 +282,8 @@ const Tree = React.forwardRef<HTMLDivElement, TreeProps>(
282
282
  return [];
283
283
  }, [defaultExpandAll, defaultExpandedKeys, data]);
284
284
 
285
- const [internalExpanded, setInternalExpanded] = React.useState<string[]>(initialExpanded);
285
+ const [internalExpanded, setInternalExpanded] =
286
+ React.useState<string[]>(initialExpanded);
286
287
  const [internalSelected, setInternalSelected] = React.useState<string[]>(
287
288
  defaultSelectedKeys ?? [],
288
289
  );
@@ -339,7 +340,7 @@ const Tree = React.forwardRef<HTMLDivElement, TreeProps>(
339
340
  };
340
341
 
341
342
  return (
342
- <div ref={ref} className={cn('text-sm', className)} {...props}>
343
+ <div ref={ref} className={cn('text-xs', className)} {...props}>
343
344
  <ul role="tree" className="flex flex-col gap-0.5">
344
345
  {data.map((n) => (
345
346
  <TreeRow
@@ -1,13 +1,14 @@
1
1
  ---
2
2
  id: tree-select
3
3
  name: TreeSelect
4
+ displayName: 树选择
4
5
  type: component
5
- category: form
6
+ category: data-entry
6
7
  since: 0.1.0
7
- package: "@teamix-evo/ui"
8
+ package: '@teamix-evo/ui'
8
9
  ---
9
10
 
10
- # TreeSelect
11
+ # TreeSelect 树选择
11
12
 
12
13
  树形下拉选择 — antd 独有补足。**等价 antd `TreeSelect`**。把 `Tree` 嵌入 Popover,提供**单选**(selectable)或**多选**(checkable)两种模式 — 组织架构 / 分类树形选择 / 文件夹路径选择常用。
13
14
 
@@ -23,6 +24,8 @@ package: "@teamix-evo/ui"
23
24
  - 严格级联(每层必选一个,不可跨层) → `Cascader`
24
25
  - 树形浏览(不需要"选中"语义) → `Tree`
25
26
 
27
+ ## Props
28
+
26
29
  <!-- auto:props:begin -->
27
30
  | 名称 | 类型 | 默认值 | 必填 | 说明 |
28
31
  | --- | --- | --- | --- | --- |
@@ -35,9 +38,12 @@ package: "@teamix-evo/ui"
35
38
  | `placeholder` | `string` | `"请选择"` | – | 占位文本。 |
36
39
  | `disabled` | `boolean` | – | – | 整体禁用。 |
37
40
  | `className` | `string` | – | – | 触发器 className。 |
38
- | `size` | `'sm' \| 'default' \| 'lg'` | `"default"` | – | 触发器尺寸。 |
41
+ | `size` | `'sm' \| 'md' \| 'default' \| 'lg'` | `"default"` | – | 触发器尺寸。 |
42
+ | `allowClear` | `boolean` | `false` | – | 显示清除按钮(antd `allowClear` 并集) — 触发器有值时右侧出现 ✕,点击清空。 |
39
43
  <!-- auto:props:end -->
40
44
 
45
+ ## 依赖
46
+
41
47
  <!-- auto:deps:begin -->
42
48
  ### 同库依赖
43
49
 
@@ -46,8 +52,8 @@ package: "@teamix-evo/ui"
46
52
  | Entry | 类型 | 描述 |
47
53
  | --- | --- | --- |
48
54
  | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
49
- | `button` | component | 通用按钮 — shadcn 实现 + antd 功能扩展(loading / icon / shape / block / dashed variant) |
50
- | `popover` | component | 可交互浮层 — Radix Popover + antd arrow 并集 |
55
+ | `button` | component | 通用按钮 — shadcn 实现 + cloud-design 能力并集(loading / icon / shape / block / dashed variant / color 语义双 prop / disabledTooltip)。同文件合一导出 ButtonGroup + ButtonGroupText(等价 antd Space.Compact + cd SplitButton)。 |
56
+ | `popover` | component | 可交互浮层 — Radix Popover + antd arrow 并集,使用 showArrow 控制尖角(与 Tooltip / HoverCard 命名统一) |
51
57
  | `tree` | component | 树形控件 — antd 独有补足。递归层级展示(目录、组织、分类),可展开 / 可选 / 可勾选(父子级联 + 半选),受控与非受控并存 |
52
58
 
53
59
  ### npm 依赖
@@ -92,9 +98,54 @@ const data = [
92
98
  ];
93
99
 
94
100
  // 单选
95
- <TreeSelect data={data} defaultExpandAll />
101
+ <TreeSelect data={data} defaultExpandAll />;
96
102
 
97
103
  // 多选 + 受控
98
104
  const [v, setV] = React.useState<string[]>(['fe', 'be']);
99
- <TreeSelect data={data} multiple defaultExpandAll value={v} onChange={(next) => setV(next as string[])} />
105
+ <TreeSelect
106
+ data={data}
107
+ multiple
108
+ defaultExpandAll
109
+ value={v}
110
+ onChange={(next) => setV(next as string[])}
111
+ />;
112
+
113
+ // 可清除(hover 时右侧出现 ✕)
114
+ <TreeSelect data={data} allowClear defaultValue="fe" />;
100
115
  ```
116
+
117
+ ## TreeSelect 形态 — 旧库 API → 新库映射
118
+
119
+ > 旧库 `TreeSelect`(hybridcloud) → 新库 `TreeSelect`(命名一致)。
120
+ > 新库基于 Radix Popover + 内嵌 `Tree` 组件,触发器复用 `Button outline variant`。
121
+
122
+ ### 命名映射
123
+
124
+ | 旧库 API | 新库 API | 备注 |
125
+ | --- | --- | --- |
126
+ | `dataSource` | `data` | 字段命名简化(对齐 React 习惯) |
127
+ | `treeDefaultExpandAll` | `defaultExpandAll` | 去 `tree` 前缀 |
128
+ | `treeCheckable` | `multiple` | 与 Select 多选 prop 命名统一 |
129
+ | `value` / `onChange(value, data)` | `value` / `onChange(value)` | 单参数化 |
130
+ | `size="small\|medium\|large"` | `size="sm\|md\|lg"` | 三档对齐 Button(24/32/36) |
131
+ | `hasClear` | `allowClear` | ✅ 本波次落地 — hover 触发器右侧显示 ✕ |
132
+ | `placeholder` | `placeholder` | 同名 |
133
+ | `disabled` | `disabled` | 同名 |
134
+
135
+ ### 不修复 / 后续工序清单(报告 §3 P1)
136
+
137
+ > 以下 P1 缺失项**未在 TreeSelect 层补**,因为它们都依赖底层 `Tree` 组件先具备相应能力。**业务真有需求时**优先在 Tree 层做,然后 TreeSelect 透传 prop 即可。
138
+
139
+ - **showSearch + onSearch 搜索过滤**(P1):Tree 层先实现节点筛选高亮,TreeSelect 在 Popover 顶部加搜索框
140
+ - **loadData 异步加载**(P1):Tree 层先实现节点点击触发异步加载子节点,TreeSelect 透传
141
+ - **treeCheckStrictly 父子不关联**(P1):Tree 层 checkable 模式增 `checkStrictly` prop 关掉父子级联
142
+ - **treeCheckedStrategy 回填策略**(P1):Tree 层暴露 `checkedStrategy: 'all' \| 'parent' \| 'child'`,影响 onCheck 返回的 value 集合
143
+ - **useVirtual 虚拟滚动**(P2):Tree 层加 react-virtual 支持(> 500 节点时显著优化)
144
+
145
+ ### 不修复(报告 §5 已明确)
146
+
147
+ - **`hasArrow` / `hasBorder`**:统一走 Button outline variant 视觉
148
+ - **`label` 内联标签**:外层用 `<Label>` 配合,组件内不内置
149
+ - **`popupStyle` / `popupClassName` / `popupProps`**:Popover 自身已有 `className`,无需中转
150
+ - **`isPreview` / `renderPreview`**:无预览态(antd 也已废弃)
151
+ - **`preserveNonExistentValue`**:简化处理,不识别的 key 直接舍去
@@ -1,16 +1,16 @@
1
1
  import * as React from 'react';
2
- import type { Meta, StoryObj } from '@storybook/react';
2
+ import type { Meta, StoryObj } from '@storybook/react-vite';
3
3
  import { TreeSelect } from './tree-select';
4
4
 
5
5
  const meta: Meta<typeof TreeSelect> = {
6
- title: '表单与输入 · Form/TreeSelect',
6
+ title: '数据录入 · Data Entry/TreeSelect',
7
7
  component: TreeSelect,
8
8
  tags: ['autodocs'],
9
9
  parameters: {
10
10
  docs: {
11
11
  description: {
12
12
  component:
13
- '树形下拉 — Tree 嵌入 Popover,单选(selectable)或多选(checkable)两种模式。组织架构 / 分类树形选择 / 文件夹路径选择常用。等价 antd `TreeSelect`。视觉走 OpenTrek tokens,所有样式来自 `@teamix-evo/design`,无 mock。',
13
+ '树形下拉 — Tree 嵌入 Popover,单选(selectable)或多选(checkable)两种模式。组织架构 / 分类树形选择 / 文件夹路径选择常用。等价 antd `TreeSelect`。',
14
14
  },
15
15
  },
16
16
  },
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { ChevronDown } from 'lucide-react';
2
+ import { ChevronDown, X } from 'lucide-react';
3
3
 
4
4
  import { cn } from '@/utils/cn';
5
5
  import { Button } from '@/components/button/button';
@@ -43,7 +43,12 @@ export interface TreeSelectProps {
43
43
  * 触发器尺寸。
44
44
  * @default "default"
45
45
  */
46
- size?: 'sm' | 'default' | 'lg';
46
+ size?: 'sm' | 'md' | 'default' | 'lg';
47
+ /**
48
+ * 显示清除按钮(antd `allowClear` 并集) — 触发器有值时右侧出现 ✕,点击清空。
49
+ * @default false
50
+ */
51
+ allowClear?: boolean;
47
52
  }
48
53
 
49
54
  function flattenLabelMap(nodes: TreeNode[]): Map<string, React.ReactNode> {
@@ -72,7 +77,8 @@ const TreeSelect = React.forwardRef<HTMLButtonElement, TreeSelectProps>(
72
77
  placeholder = '请选择',
73
78
  disabled = false,
74
79
  className,
75
- size = 'default',
80
+ size = 'md',
81
+ allowClear = false,
76
82
  },
77
83
  ref,
78
84
  ) => {
@@ -105,7 +111,7 @@ const TreeSelect = React.forwardRef<HTMLButtonElement, TreeSelectProps>(
105
111
  {display.map((d, i) => (
106
112
  <span
107
113
  key={i}
108
- className="inline-flex rounded-sm bg-muted px-1.5 py-0.5 text-xs"
114
+ className="inline-flex items-center rounded-md bg-muted px-1.5 py-0.5 text-xs text-muted-foreground"
109
115
  >
110
116
  {d}
111
117
  </span>
@@ -116,6 +122,18 @@ const TreeSelect = React.forwardRef<HTMLButtonElement, TreeSelectProps>(
116
122
  return <span className="truncate">{display}</span>;
117
123
  };
118
124
 
125
+ const hasValue = multiple
126
+ ? Array.isArray(current) && current.length > 0
127
+ : !!current;
128
+
129
+ const handleClear = (e: React.MouseEvent) => {
130
+ e.preventDefault();
131
+ e.stopPropagation();
132
+ const next = multiple ? [] : '';
133
+ if (!isControlled) setInternal(next);
134
+ onChange?.(next);
135
+ };
136
+
119
137
  return (
120
138
  <Popover open={open} onOpenChange={setOpen}>
121
139
  <PopoverTrigger asChild>
@@ -126,16 +144,33 @@ const TreeSelect = React.forwardRef<HTMLButtonElement, TreeSelectProps>(
126
144
  size={size}
127
145
  disabled={disabled}
128
146
  className={cn(
129
- 'min-w-[200px] justify-between font-normal',
147
+ 'group/treeselect min-w-panel-sm justify-between font-normal',
130
148
  !display && 'text-muted-foreground',
131
149
  className,
132
150
  )}
133
151
  >
134
152
  <span className="min-w-0 flex-1 text-left">{renderDisplay()}</span>
135
- <ChevronDown className="ml-2 size-4 shrink-0 opacity-50" />
153
+ {allowClear && hasValue && !disabled ? (
154
+ <span
155
+ role="button"
156
+ tabIndex={-1}
157
+ aria-label="清除"
158
+ onClick={handleClear}
159
+ onMouseDown={(e) => e.stopPropagation()}
160
+ className="ml-2 hidden shrink-0 rounded-sm text-muted-foreground transition-colors hover:text-foreground group-hover/treeselect:inline-flex"
161
+ >
162
+ <X className="size-3.5" />
163
+ </span>
164
+ ) : null}
165
+ <ChevronDown
166
+ className={cn(
167
+ 'ml-2 size-4 shrink-0 opacity-50',
168
+ allowClear && hasValue && 'group-hover/treeselect:hidden',
169
+ )}
170
+ />
136
171
  </Button>
137
172
  </PopoverTrigger>
138
- <PopoverContent className="w-72 p-2" align="start">
173
+ <PopoverContent className="w-72 p-1" align="start">
139
174
  {multiple ? (
140
175
  <Tree
141
176
  data={data}
@@ -1,25 +1,26 @@
1
1
  ---
2
2
  id: typography
3
3
  name: Typography
4
+ displayName: 排版
4
5
  type: component
5
- category: data-display
6
+ category: general
6
7
  since: 0.1.0
7
- package: "@teamix-evo/ui"
8
+ package: '@teamix-evo/ui'
8
9
  ---
9
10
 
10
- # Typography
11
+ # Typography 排版
11
12
 
12
- 排版组件 — `Prose`(富文本容器)+ shadcn 风格 `Title / Paragraph / Text / Link` + antd `Text` 的 `type / strong / delete / disabled / code / ellipsis / copyable` 并集。
13
+ 排版组件 — `Prose`(富文本容器)+ shadcn 风格 `Title / Paragraph / Text / Link` + antd `Text` 的 `strong / delete / disabled / code / ellipsis / copyable` 并集。语义色采用 [ADR 0021](../../../../../docs/adr/0021-semantic-color-api-unification.md) 统一 `color` API。
13
14
 
14
15
  > Prose 不依赖 `@tailwindcss/typography` 插件,样式手写并对齐 OpenTrek tokens。
15
16
 
16
17
  ## When to use
17
18
 
18
19
  - **Prose**:Markdown / CMS 富文本渲染容器(自动套排版样式)
19
- - **Title**:页面 / 区块标题(`level={1..5}` 自动映射 `<h1>~<h5>`)
20
+ - **Title**:页面 / 区块标题(`level={1..6}` 自动映射 `<h1>~<h6>`,对齐 antd `Typography.Title.level`)
20
21
  - **Paragraph**:正文段落(行高 / 字号 / 颜色统一)
21
- - **Text**:行内文本带语义色 / 强调 / 复制
22
- - **Link**:语义化链接(类型 + 默认下划线 hover)
22
+ - **Text**:行内文本带语义色(`color`) / 强调 / 复制
23
+ - **Link**:语义化链接(`color` + 默认下划线 hover)
23
24
 
24
25
  ## When NOT to use
25
26
 
@@ -27,10 +28,14 @@ package: "@teamix-evo/ui"
27
28
  - 单一颜色文本 → 直接 `<span className="text-...">`,无需包装
28
29
  - 多行 ellipsis(2 行 / 3 行) → 自行 `line-clamp-N`(本组件 ellipsis 仅单行)
29
30
 
31
+ ## Props
32
+
33
+ > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`typography.tsx`](./typography.tsx) 的 `TextProps` interface JSDoc。
34
+
30
35
  <!-- auto:props:begin -->
31
36
  | 名称 | 类型 | 默认值 | 必填 | 说明 |
32
37
  | --- | --- | --- | --- | --- |
33
- | `type` | `TextType` | `"default"` | – | 语义色(antd `type` 并集)。 |
38
+ | `color` | `TextColor` | `"default"` | – | 语义色 — 6 档枚举,字面与 OpenTrek tokens 对齐(见 [ADR 0021](../../../../../docs/adr/0021-semantic-color-api-unification.md))。 antd `type` 迁移:`secondary`→`muted`、`danger`→`destructive`。 |
34
39
  | `delete` | `boolean` | `false` | – | 删除线。 |
35
40
  | `disabled` | `boolean` | `false` | – | 不可用(灰色 + 不可选)。 |
36
41
  | `strong` | `boolean` | `false` | – | 加粗。 |
@@ -39,6 +44,10 @@ package: "@teamix-evo/ui"
39
44
  | `copyable` | `boolean \| { text: string; tooltips?: [string, string] }` | `false` | – | 可复制(antd `copyable` 并集)— 末尾追加复制图标按钮。 传对象时可指定要复制的文本(默认是 children 的纯文本);传 `true` 用 children。 |
40
45
  <!-- auto:props:end -->
41
46
 
47
+ ## 依赖
48
+
49
+ > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`manifest.json`](../../../manifest.json)。**手工编辑 marker 之间的内容会在下次生成时被覆盖**。
50
+
42
51
  <!-- auto:deps:begin -->
43
52
  ### 同库依赖
44
53
 
@@ -57,16 +66,54 @@ pnpm add lucide-react@^0.460.0
57
66
  ```
58
67
  <!-- auto:deps:end -->
59
68
 
60
- > 子组件:`Prose` / `Title`(level 1~5)/ `Paragraph` / `Text`(type / strong / delete / disabled / code / ellipsis / copyable)/ `Link`。各自的 props 详见 [`typography.tsx`](./typography.tsx)。
61
-
62
69
  ## AI 生成纪律
63
70
 
64
71
  - **`Title level` 决定标签**:不要用 `<h2>` 配 `level={1}`,语义会冲突
65
- - **`Text type` 优先于 className 颜色**:语义色让暗色模式自动适配
72
+ - **`Text color` 优先于 className 颜色**:语义色让暗色模式自动适配
66
73
  - **`copyable` 仅当 children 是 string**:富节点请显式传 `copyable={{ text: '...' }}`
67
74
  - **`ellipsis` 单行**:多行省略请直接 `className="line-clamp-2"`
68
75
  - **Prose 内部不要嵌套 Prose**:嵌套排版会双倍间距
69
76
 
77
+ ## Typography 形态 — 旧库 API → 新库映射
78
+
79
+ 旧库(Teamix 1.0 / `@alifd/next.Typography` + `Typography.Text` / `Typography.Paragraph` / `Typography.H1`~`H6`)与新库(`Typography` / `Title` / `Paragraph` / `Text` / `Link` / `Prose`)逐项对应。
80
+
81
+ ### 组件拆合
82
+
83
+ | 旧库 | 新库 | 备注 |
84
+ | --- | --- | --- |
85
+ | `Typography` | `Prose` | 富文本容器,渲染 Markdown / CMS 输出 |
86
+ | `Typography.H1` ~ `Typography.H6` | `<Title level={1..6}>` | level 决定字号 + 标签;新增 level=6 对齐 antd |
87
+ | `Typography.Paragraph` | `Paragraph` | 同义 |
88
+ | `Typography.Text` | `Text` | 行内文本 |
89
+ | — | `Link` | 新增 — 语义化 `<a>` 元素 |
90
+
91
+ ### Props / 值映射
92
+
93
+ | 旧库 | 新库 | 备注 |
94
+ | --- | --- | --- |
95
+ | `<Text type="secondary">` | `<Text color="muted">` | ADR 0021 语义色重命名 |
96
+ | `<Text type="danger">` | `<Text color="destructive">` | ADR 0021 — 不收 antd `error` / `danger` 别名 |
97
+ | `<Text strong>` | `<Text strong>` | 行为一致 |
98
+ | `<Text delete>` | `<Text delete>` | 行为一致 |
99
+ | `<Text code>` | `<Text code>` | 行为一致 |
100
+ | `<Text disabled>` | `<Text disabled>` | 行为一致 |
101
+ | `<Text ellipsis>` | `<Text ellipsis>` | P0 已实现 — 单行 truncate;多行用 `className="line-clamp-N"` |
102
+ | `<Text copyable>` | `<Text copyable>` | P0 已实现 — 默认复制 children;传对象指定 `text` |
103
+ | `<Text copyable={{ text }}>` | `<Text copyable={{ text }}>` | 对象签名一致 |
104
+ | `size="body1/body2/caption/overline"` | className `text-sm/text-xs/...` | shadcn 字号通过 Tailwind 直控,不抽 prop |
105
+ | `mark` 黄色高亮 | 直接用 `<mark>` 标签 | HTML 原生 |
106
+ | `underline` | `className="underline"` | Tailwind utility |
107
+ | `editable` 行内编辑 | 不修复 — 用 Tiptap / Lexical / Input + state | 复杂度高,业务低频 |
108
+
109
+ ### 不修复清单
110
+
111
+ | 旧库能力 | 理由 |
112
+ | --- | --- |
113
+ | `mark` / `underline` / `delete` / `code` 全 prop | 直接用 HTML 原生 / Tailwind utility 更简洁,只保留 `delete` / `code` 的便捷 prop |
114
+ | `editable` 行内编辑 | 业务低频 + 复杂度高,推荐用 Tiptap 等编辑器 |
115
+ | `component` 自定义根标签 | shadcn 走 `asChild` (Slot) 替代 — 需要时用 `<Title asChild><span>...</span></Title>` |
116
+
70
117
  ## Examples
71
118
 
72
119
  ```tsx
@@ -80,8 +127,8 @@ import { Prose, Title, Paragraph, Text, Link } from '@/components/ui/typography'
80
127
  <Paragraph>正文段落,统一字号 / 行高 / 颜色。</Paragraph>
81
128
 
82
129
  // 行内文本
83
- <Text type="success" strong>成功</Text>
84
- <Text type="danger" delete>已废弃</Text>
130
+ <Text color="success" strong>成功</Text>
131
+ <Text color="destructive" delete>已废弃</Text>
85
132
  <Text disabled>不可用</Text>
86
133
  <Text code>const x = 1</Text>
87
134
  <Text ellipsis>这是一段非常长的文字...被截断</Text>
@@ -90,7 +137,7 @@ import { Prose, Title, Paragraph, Text, Link } from '@/components/ui/typography'
90
137
 
91
138
  // 链接
92
139
  <Link href="/docs">文档</Link>
93
- <Link href="/danger" type="danger">危险链接</Link>
140
+ <Link href="/danger" color="destructive">危险链接</Link>
94
141
 
95
142
  // Prose 容器(渲染 Markdown 等富文本)
96
143
  <Prose>
@@ -1,15 +1,15 @@
1
- import type { Meta, StoryObj } from '@storybook/react';
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
2
  import { Prose, Title, Paragraph, Text, Link } from './typography';
3
3
 
4
4
  const meta: Meta<typeof Text> = {
5
- title: '数据展示 · Data Display/Typography',
5
+ title: '通用 · General/Typography',
6
6
  component: Text,
7
7
  tags: ['autodocs'],
8
8
  parameters: {
9
9
  docs: {
10
10
  description: {
11
11
  component:
12
- '排版组件 — Prose 富文本容器 + Title/Paragraph/Text/Link,合并 antd 的 type/strong/delete/disabled/code/ellipsis/copyable 能力。OpenTrek tokens 适配,无 mock。',
12
+ '排版组件 — Prose 富文本容器 + Title / Paragraph / Text / Link,合并 antd 的 `type` / `strong` / `delete` / `disabled` / `code` / `ellipsis` / `copyable` 能力。语义色采用 [ADR 0021](../../../../../docs/adr/0021-semantic-color-api-unification.md) 统一 `color` API(antd `type` 的 secondary/success/warning/danger 合并为 `color` 的 muted/success/warning/destructive)。',
13
13
  },
14
14
  },
15
15
  },
@@ -31,15 +31,16 @@ export const Titles: Story = {
31
31
  ),
32
32
  };
33
33
 
34
- export const TextTypes: Story = {
34
+ export const TextColors: Story = {
35
35
  parameters: { controls: { disable: true } },
36
36
  render: () => (
37
37
  <div className="flex flex-col gap-2 text-sm">
38
38
  <Text>默认</Text>
39
- <Text type="secondary">次要</Text>
40
- <Text type="success">成功</Text>
41
- <Text type="warning">警告</Text>
42
- <Text type="danger">危险</Text>
39
+ <Text color="muted">次要</Text>
40
+ <Text color="primary">信息 / 主颜色</Text>
41
+ <Text color="success">成功</Text>
42
+ <Text color="warning">警告</Text>
43
+ <Text color="destructive">危险</Text>
43
44
  <Text strong>加粗</Text>
44
45
  <Text delete>已废弃</Text>
45
46
  <Text disabled>不可用</Text>
@@ -78,7 +79,7 @@ export const Links: Story = {
78
79
  </Link>
79
80
  <Link
80
81
  href="#delete"
81
- type="danger"
82
+ color="destructive"
82
83
  onClick={(e) => e.preventDefault()}
83
84
  >
84
85
  危险操作链接
@@ -98,8 +99,8 @@ export const ProseDemo: Story = {
98
99
  </p>
99
100
  <h2>子标题</h2>
100
101
  <p>
101
- 访问 <a href="#">链接</a> 查看更多。<strong>强调</strong>{' '}
102
- <em>斜体</em> <code>inline-code</code>。
102
+ 访问 <a href="#">链接</a> 查看更多。<strong>强调</strong> <em>斜体</em>{' '}
103
+ <code>inline-code</code>。
103
104
  </p>
104
105
  <ul>
105
106
  <li>列表项 1</li>
@@ -35,6 +35,7 @@ const Prose = React.forwardRef<HTMLDivElement, ProseProps>(
35
35
  '[&_strong]:font-semibold',
36
36
  '[&_em]:italic',
37
37
  // code
38
+ // eslint-disable-next-line teamix-evo/no-arbitrary-tw-value -- inline `<code>` uses em-relative size to scale with surrounding text; not tokenizable since it depends on parent context.
38
39
  '[&_code]:rounded [&_code]:bg-muted [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-[0.875em]',
39
40
  '[&_pre]:my-4 [&_pre]:overflow-x-auto [&_pre]:rounded-md [&_pre]:bg-muted [&_pre]:p-4',
40
41
  '[&_pre_code]:bg-transparent [&_pre_code]:p-0',
@@ -57,25 +58,22 @@ const titleSizes = {
57
58
  3: 'text-xl font-semibold',
58
59
  4: 'text-lg font-medium',
59
60
  5: 'text-base font-medium',
61
+ 6: 'text-sm font-medium',
60
62
  } as const;
61
63
 
62
64
  export interface TitleProps extends React.HTMLAttributes<HTMLHeadingElement> {
63
65
  /**
64
- * 层级(1~5),决定字号 / 粗细;同时映射为 `<h1>~<h5>` 标签。
66
+ * 层级(1~6),决定字号 / 粗细;同时映射为 `<h1>~<h6>` 标签 — 对齐 antd `Typography.Title.level`。
65
67
  * @default 1
66
68
  */
67
- level?: 1 | 2 | 3 | 4 | 5;
69
+ level?: 1 | 2 | 3 | 4 | 5 | 6;
68
70
  }
69
71
 
70
72
  const Title = React.forwardRef<HTMLHeadingElement, TitleProps>(
71
73
  ({ level = 1, className, ...props }, ref) => {
72
- const Comp = `h${level}` as 'h1' | 'h2' | 'h3' | 'h4' | 'h5';
74
+ const Comp = `h${level}` as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
73
75
  return (
74
- <Comp
75
- ref={ref}
76
- className={cn(titleSizes[level], className)}
77
- {...props}
78
- />
76
+ <Comp ref={ref} className={cn(titleSizes[level], className)} {...props} />
79
77
  );
80
78
  },
81
79
  );
@@ -97,16 +95,30 @@ const Paragraph = React.forwardRef<HTMLParagraphElement, ParagraphProps>(
97
95
  );
98
96
  Paragraph.displayName = 'Paragraph';
99
97
 
100
- // ─── Text(行内文本,支持 antd ellipsis / copyable / type)──────────────────
98
+ // ─── Text(行内文本,支持 antd ellipsis / copyable / color)──────────────────
101
99
 
102
- export type TextType = 'default' | 'secondary' | 'success' | 'warning' | 'danger';
100
+ /**
101
+ * Text 语义色 6 档(见 [ADR 0021](../../../../../docs/adr/0021-semantic-color-api-unification.md))。
102
+ * 字面与 OpenTrek tokens 对齐:
103
+ * - antd `secondary` → `muted`(对齐 `--muted-foreground`)
104
+ * - antd `danger` → `destructive`(对齐 `--destructive`)
105
+ * - **不收 `info`** — 如需信息色,用 `primary`。
106
+ */
107
+ export type TextColor =
108
+ | 'default'
109
+ | 'muted'
110
+ | 'primary'
111
+ | 'success'
112
+ | 'warning'
113
+ | 'destructive';
103
114
 
104
115
  export interface TextProps extends React.HTMLAttributes<HTMLSpanElement> {
105
116
  /**
106
- * 语义色(antd `type` 并集)。
117
+ * 语义色 — 6 档枚举,字面与 OpenTrek tokens 对齐( [ADR 0021](../../../../../docs/adr/0021-semantic-color-api-unification.md))
118
+ * antd `type` 迁移:`secondary`→`muted`、`danger`→`destructive`。
107
119
  * @default "default"
108
120
  */
109
- type?: TextType;
121
+ color?: TextColor;
110
122
  /**
111
123
  * 删除线。
112
124
  * @default false
@@ -140,18 +152,19 @@ export interface TextProps extends React.HTMLAttributes<HTMLSpanElement> {
140
152
  copyable?: boolean | { text: string; tooltips?: [string, string] };
141
153
  }
142
154
 
143
- const typeColor: Record<TextType, string> = {
155
+ const colorClass: Record<TextColor, string> = {
144
156
  default: 'text-foreground',
145
- secondary: 'text-muted-foreground',
146
- success: 'text-emerald-600',
147
- warning: 'text-amber-600',
148
- danger: 'text-destructive',
157
+ muted: 'text-muted-foreground',
158
+ primary: 'text-primary',
159
+ success: 'text-success',
160
+ warning: 'text-warning',
161
+ destructive: 'text-destructive',
149
162
  };
150
163
 
151
164
  const Text = React.forwardRef<HTMLSpanElement, TextProps>(
152
165
  (
153
166
  {
154
- type = 'default',
167
+ color = 'default',
155
168
  delete: del = false,
156
169
  disabled = false,
157
170
  strong = false,
@@ -170,8 +183,8 @@ const Text = React.forwardRef<HTMLSpanElement, TextProps>(
170
183
  typeof copyable === 'object' && copyable.text
171
184
  ? copyable.text
172
185
  : typeof children === 'string'
173
- ? children
174
- : '';
186
+ ? children
187
+ : '';
175
188
  void navigator.clipboard?.writeText(text).then(() => {
176
189
  setCopied(true);
177
190
  window.setTimeout(() => setCopied(false), 1500);
@@ -179,12 +192,13 @@ const Text = React.forwardRef<HTMLSpanElement, TextProps>(
179
192
  };
180
193
 
181
194
  const cls = cn(
182
- typeColor[type],
195
+ colorClass[color],
183
196
  strong && 'font-semibold',
184
197
  del && 'line-through',
185
198
  disabled && 'cursor-not-allowed select-none opacity-50',
186
199
  ellipsis && 'inline-block max-w-full truncate align-bottom',
187
200
  code &&
201
+ // eslint-disable-next-line teamix-evo/no-arbitrary-tw-value -- inline `<code>` uses em-relative size to scale with surrounding text; not tokenizable.
188
202
  'rounded bg-muted px-1.5 py-0.5 font-mono text-[0.875em]',
189
203
  className,
190
204
  );
@@ -199,10 +213,10 @@ const Text = React.forwardRef<HTMLSpanElement, TextProps>(
199
213
  type="button"
200
214
  onClick={handleCopy}
201
215
  aria-label={copied ? '已复制' : '复制'}
202
- className="rounded-sm p-0.5 text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
216
+ className="cursor-pointer rounded-sm p-0.5 text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
203
217
  >
204
218
  {copied ? (
205
- <Check className="size-3.5 text-emerald-600" />
219
+ <Check className="size-3.5 text-success" />
206
220
  ) : (
207
221
  <Copy className="size-3.5" />
208
222
  )}
@@ -222,18 +236,19 @@ Text.displayName = 'Text';
222
236
 
223
237
  // ─── Link(antd 风格,默认下划线 hover)────────────────────────────────────
224
238
 
225
- export interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
226
- /** 语义色(同 Text 的 type)。 @default "default" */
227
- type?: TextType;
239
+ export interface LinkProps
240
+ extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
241
+ /** 语义色(同 Text 的 color)。 @default "default" */
242
+ color?: TextColor;
228
243
  }
229
244
 
230
245
  const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(
231
- ({ className, type = 'default', ...props }, ref) => (
246
+ ({ className, color = 'default', ...props }, ref) => (
232
247
  <a
233
248
  ref={ref}
234
249
  className={cn(
235
250
  'underline-offset-4 transition-colors hover:underline',
236
- type === 'default' ? 'text-primary' : typeColor[type],
251
+ color === 'default' ? 'text-primary' : colorClass[color],
237
252
  className,
238
253
  )}
239
254
  {...props}