@teamix-evo/ui 0.2.0 → 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.
- package/README.md +184 -184
- package/manifest.json +680 -492
- package/package.json +15 -9
- package/src/components/accordion/accordion.meta.md +5 -9
- package/src/components/accordion/accordion.stories.tsx +3 -3
- package/src/components/accordion/accordion.tsx +104 -8
- package/src/components/affix/affix.meta.md +21 -12
- package/src/components/affix/affix.stories.tsx +101 -26
- package/src/components/affix/affix.tsx +79 -9
- package/src/components/alert/alert.meta.md +52 -26
- package/src/components/alert/alert.stories.tsx +66 -21
- package/src/components/alert/alert.tsx +81 -34
- package/src/components/alert-dialog/alert-dialog.meta.md +48 -16
- package/src/components/alert-dialog/alert-dialog.stories.tsx +145 -3
- package/src/components/alert-dialog/alert-dialog.tsx +60 -13
- package/src/components/anchor/anchor.meta.md +10 -14
- package/src/components/anchor/anchor.stories.tsx +3 -3
- package/src/components/anchor/anchor.tsx +2 -2
- package/src/components/app/app.meta.md +10 -14
- package/src/components/app/app.stories.tsx +6 -6
- package/src/components/aspect-ratio/aspect-ratio.meta.md +4 -8
- package/src/components/aspect-ratio/aspect-ratio.stories.tsx +3 -3
- package/src/components/auto-complete/auto-complete.meta.md +19 -20
- package/src/components/auto-complete/auto-complete.stories.tsx +44 -3
- package/src/components/auto-complete/auto-complete.tsx +119 -71
- package/src/components/avatar/avatar.meta.md +9 -22
- package/src/components/avatar/avatar.stories.tsx +21 -3
- package/src/components/avatar/avatar.tsx +24 -23
- package/src/components/badge/badge.meta.md +14 -18
- package/src/components/badge/badge.stories.tsx +2 -2
- package/src/components/badge/badge.tsx +2 -2
- package/src/components/breadcrumb/breadcrumb.meta.md +29 -20
- package/src/components/breadcrumb/breadcrumb.stories.tsx +120 -5
- package/src/components/breadcrumb/breadcrumb.tsx +22 -8
- package/src/components/button/button.meta.md +261 -29
- package/src/components/button/button.stories.tsx +549 -41
- package/src/components/button/button.tsx +335 -33
- package/src/components/calendar/calendar.meta.md +19 -14
- package/src/components/calendar/calendar.stories.tsx +5 -5
- package/src/components/calendar/calendar.tsx +73 -8
- package/src/components/card/card.meta.md +31 -34
- package/src/components/card/card.stories.tsx +34 -3
- package/src/components/card/card.tsx +146 -63
- package/src/components/carousel/carousel.meta.md +10 -14
- package/src/components/carousel/carousel.stories.tsx +1 -1
- package/src/components/cascader/cascader.meta.md +43 -22
- package/src/components/cascader/cascader.stories.tsx +13 -2
- package/src/components/cascader/cascader.tsx +427 -84
- package/src/components/checkbox/checkbox.meta.md +74 -24
- package/src/components/checkbox/checkbox.stories.tsx +160 -2
- package/src/components/checkbox/checkbox.tsx +77 -9
- package/src/components/collapsible/collapsible.meta.md +7 -6
- package/src/components/collapsible/collapsible.stories.tsx +2 -2
- package/src/components/collapsible/collapsible.tsx +93 -6
- package/src/components/color-picker/color-picker.meta.md +16 -20
- package/src/components/color-picker/color-picker.stories.tsx +86 -7
- package/src/components/color-picker/color-picker.tsx +19 -9
- package/src/components/command/command.meta.md +7 -11
- package/src/components/command/command.stories.tsx +4 -4
- package/src/components/command/command.tsx +18 -7
- package/src/components/context-menu/context-menu.meta.md +5 -25
- package/src/components/context-menu/context-menu.stories.tsx +4 -4
- package/src/components/context-menu/context-menu.tsx +21 -8
- package/src/components/data-table/data-table.meta.md +14 -18
- package/src/components/data-table/data-table.stories.tsx +1 -1
- package/src/components/data-table/data-table.tsx +2 -2
- package/src/components/date-picker/date-picker.meta.md +90 -41
- package/src/components/date-picker/date-picker.stories.tsx +55 -5
- package/src/components/date-picker/date-picker.tsx +1489 -91
- package/src/components/descriptions/descriptions.meta.md +12 -16
- package/src/components/descriptions/descriptions.stories.tsx +2 -2
- package/src/components/descriptions/descriptions.tsx +22 -14
- package/src/components/dialog/dialog.meta.md +67 -17
- package/src/components/dialog/dialog.stories.tsx +182 -20
- package/src/components/dialog/dialog.tsx +67 -15
- package/src/components/dialog/imperative.tsx +252 -0
- package/src/components/drawer/drawer.meta.md +27 -39
- package/src/components/drawer/drawer.stories.tsx +29 -12
- package/src/components/drawer/drawer.tsx +22 -114
- package/src/components/dropdown-menu/dropdown-menu.meta.md +64 -24
- package/src/components/dropdown-menu/dropdown-menu.stories.tsx +81 -3
- package/src/components/dropdown-menu/dropdown-menu.tsx +24 -10
- package/src/components/ellipsis/ellipsis.meta.md +87 -0
- package/src/components/ellipsis/ellipsis.stories.tsx +72 -0
- package/src/components/ellipsis/ellipsis.tsx +153 -0
- package/src/components/empty/empty.meta.md +10 -14
- package/src/components/empty/empty.stories.tsx +3 -3
- package/src/components/empty/empty.tsx +10 -3
- package/src/components/field/field.meta.md +46 -25
- package/src/components/field/field.stories.tsx +380 -3
- package/src/components/field/field.tsx +263 -35
- package/src/components/filter-bar/filter-bar.meta.md +92 -0
- package/src/components/filter-bar/filter-bar.stories.tsx +1083 -0
- package/src/components/filter-bar/filter-bar.tsx +568 -0
- package/src/components/flex/flex.meta.md +59 -20
- package/src/components/flex/flex.stories.tsx +65 -10
- package/src/components/flex/flex.tsx +27 -4
- package/src/components/float-button/float-button.meta.md +10 -29
- package/src/components/float-button/float-button.stories.tsx +6 -6
- package/src/components/form/form.meta.md +31 -52
- package/src/components/form/form.stories.tsx +350 -3
- package/src/components/form/form.tsx +101 -35
- package/src/components/grid/grid.meta.md +4 -24
- package/src/components/grid/grid.stories.tsx +2 -2
- package/src/components/hover-card/hover-card.meta.md +9 -10
- package/src/components/hover-card/hover-card.stories.tsx +29 -4
- package/src/components/hover-card/hover-card.tsx +51 -13
- package/src/components/icon/DEVELOPMENT.md +809 -0
- package/src/components/icon/icon.meta.md +170 -0
- package/src/components/icon/icon.stories.tsx +344 -0
- package/src/components/icon/icon.tsx +248 -0
- package/src/components/image/image.meta.md +14 -18
- package/src/components/image/image.stories.tsx +3 -3
- package/src/components/image/image.tsx +2 -0
- package/src/components/input/demo/sizes.tsx +2 -2
- package/src/components/input/input.meta.md +44 -43
- package/src/components/input/input.stories.tsx +62 -35
- package/src/components/input/input.tsx +96 -101
- package/src/components/input-group/input-group.meta.md +53 -39
- package/src/components/input-group/input-group.stories.tsx +49 -16
- package/src/components/input-group/input-group.tsx +43 -8
- package/src/components/input-number/input-number.meta.md +68 -20
- package/src/components/input-number/input-number.stories.tsx +33 -6
- package/src/components/input-number/input-number.tsx +79 -20
- package/src/components/input-otp/input-otp.meta.md +8 -20
- package/src/components/input-otp/input-otp.stories.tsx +3 -3
- package/src/components/input-otp/input-otp.tsx +1 -1
- package/src/components/item/item.meta.md +8 -26
- package/src/components/item/item.stories.tsx +3 -3
- package/src/components/item/item.tsx +7 -6
- package/src/components/kbd/kbd.meta.md +7 -19
- package/src/components/kbd/kbd.stories.tsx +4 -4
- package/src/components/kbd/kbd.tsx +8 -4
- package/src/components/label/label.meta.md +21 -18
- package/src/components/label/label.stories.tsx +64 -6
- package/src/components/label/label.tsx +91 -19
- package/src/components/masonry/masonry.meta.md +8 -12
- package/src/components/masonry/masonry.stories.tsx +4 -4
- package/src/components/mentions/mentions.meta.md +42 -21
- package/src/components/mentions/mentions.stories.tsx +120 -6
- package/src/components/mentions/mentions.tsx +10 -5
- package/src/components/menubar/menubar.meta.md +4 -8
- package/src/components/menubar/menubar.stories.tsx +55 -3
- package/src/components/menubar/menubar.tsx +9 -9
- package/src/components/native-select/native-select.meta.md +7 -11
- package/src/components/native-select/native-select.stories.tsx +4 -4
- package/src/components/native-select/native-select.tsx +1 -1
- package/src/components/navigation-menu/navigation-menu.meta.md +4 -8
- package/src/components/navigation-menu/navigation-menu.stories.tsx +106 -3
- package/src/components/navigation-menu/navigation-menu.tsx +6 -3
- package/src/components/notification/notification.meta.md +41 -8
- package/src/components/notification/notification.stories.tsx +9 -9
- package/src/components/notification/notification.tsx +34 -19
- package/src/components/page-header/DEVELOPMENT.md +842 -0
- package/src/components/page-header/page-header.meta.md +208 -0
- package/src/components/page-header/page-header.stories.tsx +421 -0
- package/src/components/page-header/page-header.tsx +281 -0
- package/src/components/pagination/pagination.meta.md +122 -50
- package/src/components/pagination/pagination.stories.tsx +227 -11
- package/src/components/pagination/pagination.tsx +355 -63
- package/src/components/popconfirm/popconfirm.meta.md +19 -23
- package/src/components/popconfirm/popconfirm.stories.tsx +2 -2
- package/src/components/popconfirm/popconfirm.tsx +1 -1
- package/src/components/popover/popover.meta.md +64 -12
- package/src/components/popover/popover.stories.tsx +83 -7
- package/src/components/popover/popover.tsx +77 -28
- package/src/components/progress/progress.meta.md +43 -26
- package/src/components/progress/progress.stories.tsx +2 -2
- package/src/components/progress/progress.tsx +19 -11
- package/src/components/radio-group/radio-group.meta.md +78 -11
- package/src/components/radio-group/radio-group.stories.tsx +38 -2
- package/src/components/radio-group/radio-group.tsx +149 -18
- package/src/components/rate/rate.meta.md +41 -19
- package/src/components/rate/rate.stories.tsx +2 -2
- package/src/components/rate/rate.tsx +37 -10
- package/src/components/resizable/resizable.meta.md +4 -12
- package/src/components/resizable/resizable.stories.tsx +5 -5
- package/src/components/resizable/resizable.tsx +1 -1
- package/src/components/result/result.meta.md +10 -14
- package/src/components/result/result.stories.tsx +2 -2
- package/src/components/result/result.tsx +21 -12
- package/src/components/scroll-area/scroll-area.meta.md +4 -8
- package/src/components/scroll-area/scroll-area.stories.tsx +5 -5
- package/src/components/segmented/segmented.meta.md +15 -17
- package/src/components/segmented/segmented.stories.tsx +3 -3
- package/src/components/segmented/segmented.tsx +15 -7
- package/src/components/select/select.meta.md +199 -67
- package/src/components/select/select.stories.tsx +238 -63
- package/src/components/select/select.tsx +718 -171
- package/src/components/separator/separator.meta.md +10 -14
- package/src/components/separator/separator.stories.tsx +2 -2
- package/src/components/separator/separator.tsx +3 -7
- package/src/components/sheet/sheet.meta.md +26 -21
- package/src/components/sheet/sheet.stories.tsx +116 -10
- package/src/components/sheet/sheet.tsx +116 -29
- package/src/components/sidebar/sidebar.meta.md +28 -38
- package/src/components/sidebar/sidebar.stories.tsx +696 -29
- package/src/components/sidebar/sidebar.tsx +615 -142
- package/src/components/skeleton/skeleton.meta.md +7 -31
- package/src/components/skeleton/skeleton.stories.tsx +3 -3
- package/src/components/skeleton/skeleton.tsx +7 -7
- package/src/components/slider/slider.meta.md +60 -13
- package/src/components/slider/slider.stories.tsx +58 -6
- package/src/components/slider/slider.tsx +154 -13
- package/src/components/sonner/sonner.meta.md +54 -8
- package/src/components/sonner/sonner.stories.tsx +79 -11
- package/src/components/sonner/sonner.tsx +137 -8
- package/src/components/spinner/spinner.meta.md +57 -21
- package/src/components/spinner/spinner.stories.tsx +66 -14
- package/src/components/spinner/spinner.tsx +111 -9
- package/src/components/statistic/statistic.meta.md +14 -30
- package/src/components/statistic/statistic.stories.tsx +1 -1
- package/src/components/statistic/statistic.tsx +4 -5
- package/src/components/steps/steps.meta.md +20 -15
- package/src/components/steps/steps.stories.tsx +37 -2
- package/src/components/steps/steps.tsx +15 -12
- package/src/components/switch/switch.meta.md +56 -15
- package/src/components/switch/switch.stories.tsx +5 -5
- package/src/components/switch/switch.tsx +59 -13
- package/src/components/table/table.meta.md +3 -7
- package/src/components/table/table.stories.tsx +1 -1
- package/src/components/table/table.tsx +4 -4
- package/src/components/tabs/tabs.meta.md +40 -32
- package/src/components/tabs/tabs.stories.tsx +104 -26
- package/src/components/tabs/tabs.tsx +125 -54
- package/src/components/tag/tag.meta.md +104 -68
- package/src/components/tag/tag.stories.tsx +183 -15
- package/src/components/tag/tag.tsx +222 -21
- package/src/components/textarea/textarea.meta.md +42 -31
- package/src/components/textarea/textarea.stories.tsx +32 -6
- package/src/components/textarea/textarea.tsx +32 -8
- package/src/components/time-picker/time-picker.meta.md +119 -50
- package/src/components/time-picker/time-picker.stories.tsx +65 -33
- package/src/components/time-picker/time-picker.tsx +889 -101
- package/src/components/timeline/timeline.meta.md +16 -17
- package/src/components/timeline/timeline.stories.tsx +24 -4
- package/src/components/timeline/timeline.tsx +32 -12
- package/src/components/toggle/toggle.meta.md +8 -12
- package/src/components/toggle/toggle.stories.tsx +4 -4
- package/src/components/toggle/toggle.tsx +4 -3
- package/src/components/toggle-group/toggle-group.meta.md +10 -14
- package/src/components/toggle-group/toggle-group.stories.tsx +3 -3
- package/src/components/toggle-group/toggle-group.tsx +2 -2
- package/src/components/tooltip/tooltip.meta.md +63 -18
- package/src/components/tooltip/tooltip.stories.tsx +42 -5
- package/src/components/tooltip/tooltip.tsx +81 -21
- package/src/components/tour/tour.meta.md +16 -20
- package/src/components/tour/tour.stories.tsx +3 -3
- package/src/components/tour/tour.tsx +3 -3
- package/src/components/transfer/transfer.meta.md +18 -22
- package/src/components/transfer/transfer.stories.tsx +2 -2
- package/src/components/transfer/transfer.tsx +28 -21
- package/src/components/tree/tree.meta.md +67 -22
- package/src/components/tree/tree.stories.tsx +1 -1
- package/src/components/tree/tree.tsx +9 -8
- package/src/components/tree-select/tree-select.meta.md +59 -23
- package/src/components/tree-select/tree-select.stories.tsx +2 -2
- package/src/components/tree-select/tree-select.tsx +42 -7
- package/src/components/typography/typography.meta.md +61 -39
- package/src/components/typography/typography.stories.tsx +14 -9
- package/src/components/typography/typography.tsx +38 -25
- package/src/components/upload/upload.meta.md +61 -25
- package/src/components/upload/upload.stories.tsx +69 -3
- package/src/components/upload/upload.tsx +170 -37
- package/src/components/watermark/watermark.meta.md +15 -19
- package/src/components/watermark/watermark.stories.tsx +98 -8
- package/src/hooks/use-breakpoint.ts +117 -0
- package/src/hooks/use-debounce-callback.ts +52 -0
- package/src/hooks/use-mobile.ts +23 -0
- package/src/stories/theme-tokens.stories.tsx +747 -0
- package/src/utils/trigger-input.ts +53 -0
- package/src/components/button-group/button-group.meta.md +0 -101
- package/src/components/button-group/button-group.stories.tsx +0 -93
- package/src/components/button-group/button-group.tsx +0 -75
- package/src/components/combobox/combobox.meta.md +0 -102
- package/src/components/combobox/combobox.stories.tsx +0 -55
- package/src/components/combobox/combobox.tsx +0 -130
- package/src/components/input/demo/addon.tsx +0 -15
- package/src/components/input/demo/with-prefix-suffix.tsx +0 -19
- package/src/components/space/space.meta.md +0 -103
- package/src/components/space/space.stories.tsx +0 -108
- package/src/components/space/space.tsx +0 -106
|
@@ -27,36 +27,33 @@ package: '@teamix-evo/ui'
|
|
|
27
27
|
## Props
|
|
28
28
|
|
|
29
29
|
<!-- auto:props:begin -->
|
|
30
|
-
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
| `
|
|
34
|
-
| `
|
|
35
|
-
| `
|
|
36
|
-
| `
|
|
37
|
-
| `
|
|
38
|
-
| `
|
|
39
|
-
| `
|
|
40
|
-
| `
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `onExpand` | `(next: string[]) => void` | – | – | 展开变化回调。 |
|
|
46
|
-
|
|
30
|
+
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
31
|
+
| --- | --- | --- | --- | --- |
|
|
32
|
+
| `data` | `TreeNode[]` | – | ✓ | 树数据(antd `treeData` 并集)。 |
|
|
33
|
+
| `checkable` | `boolean` | `false` | – | 是否启用勾选 checkbox(antd `checkable` 并集) — 父子级联,半选状态自动计算。 |
|
|
34
|
+
| `selectable` | `boolean` | `true` | – | 是否启用单击高亮选择(antd `selectable` 并集)。 |
|
|
35
|
+
| `checkedKeys` | `string[]` | – | – | 受控已勾选 key 集合(checkable 时生效)。 |
|
|
36
|
+
| `defaultCheckedKeys` | `string[]` | – | – | uncontrolled 初值。 |
|
|
37
|
+
| `onCheck` | `(next: string[]) => void` | – | – | 勾选变化回调。 |
|
|
38
|
+
| `selectedKeys` | `string[]` | – | – | 受控已选中 key 集合(selectable 时生效;通常单选,数组形式与 antd 对齐)。 |
|
|
39
|
+
| `defaultSelectedKeys` | `string[]` | – | – | uncontrolled 初值。 |
|
|
40
|
+
| `onSelect` | `(next: string[]) => void` | – | – | 选中变化回调。 |
|
|
41
|
+
| `expandedKeys` | `string[]` | – | – | 受控已展开 key 集合。 |
|
|
42
|
+
| `defaultExpandedKeys` | `string[]` | – | – | uncontrolled 初值。 |
|
|
43
|
+
| `defaultExpandAll` | `boolean` | `false` | – | 默认展开全部(antd `defaultExpandAll` 并集) — 仅 uncontrolled 模式生效。 |
|
|
44
|
+
| `onExpand` | `(next: string[]) => void` | – | – | 展开变化回调。 |
|
|
47
45
|
<!-- auto:props:end -->
|
|
48
46
|
|
|
49
47
|
## 依赖
|
|
50
48
|
|
|
51
49
|
<!-- auto:deps:begin -->
|
|
52
|
-
|
|
53
50
|
### 同库依赖
|
|
54
51
|
|
|
55
52
|
> `teamix-evo ui add tree` 时,以下 entry 会被自动连带安装(无需手动 add)。
|
|
56
53
|
|
|
57
|
-
| Entry
|
|
58
|
-
|
|
|
59
|
-
| `cn`
|
|
54
|
+
| Entry | 类型 | 描述 |
|
|
55
|
+
| --- | --- | --- |
|
|
56
|
+
| `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
|
|
60
57
|
| `checkbox` | component | 复选框 — Radix Checkbox(原生 indeterminate)+ antd Checkbox.Group(options 数组驱动) |
|
|
61
58
|
|
|
62
59
|
### npm 依赖
|
|
@@ -66,7 +63,6 @@ package: '@teamix-evo/ui'
|
|
|
66
63
|
```bash
|
|
67
64
|
pnpm add lucide-react@^0.460.0
|
|
68
65
|
```
|
|
69
|
-
|
|
70
66
|
<!-- auto:deps:end -->
|
|
71
67
|
|
|
72
68
|
## AI 生成纪律
|
|
@@ -75,6 +71,9 @@ pnpm add lucide-react@^0.460.0
|
|
|
75
71
|
- **`checkable` 默认级联**:勾选父节点会勾选所有后代,勾选所有后代会自动勾选父节点 — **不要**自己写额外的级联逻辑;`onCheck` 给的是叶子+完全选中的父节点集合(半选不在内)
|
|
76
72
|
- **半选(indeterminate)**自动计算,不需要消费方维护
|
|
77
73
|
- **`selectable` + `checkable` 可共存**,但 UI 上选中高亮与勾选是两套独立状态(对齐 antd)
|
|
74
|
+
- **选中 ≠ hover**:hover 是 `accent/50`(半透明),选中是 `accent` 实色 + `font-medium`,视觉上明显区分;**不要**手动改为其他调色板
|
|
75
|
+
- **节点缩进**:每层 20px刷类 shadcn/cloud-design teamix 规范,**不要**手动调 padding
|
|
76
|
+
- **展开图标**:`size-3` 的 `ChevronRight` 旋转 90°,默认为 `text-muted-foreground` hover 变 `text-foreground` — 不要换 chevron 尺寸
|
|
78
77
|
- **大数据量警告**:节点数 ≥ 500 时建议拆分为"按需加载子节点"(在 `onExpand` 中拉取),否则首次渲染卡顿
|
|
79
78
|
- **`disabled` 节点**:展开按钮亦禁用,但**仍参与级联计算** — 父被勾选时禁用子也会变为 checked
|
|
80
79
|
|
|
@@ -122,3 +121,49 @@ const [checked, setChecked] = React.useState<string[]>([]);
|
|
|
122
121
|
onCheck={setChecked}
|
|
123
122
|
/>;
|
|
124
123
|
```
|
|
124
|
+
|
|
125
|
+
## Tree 形态 — 旧库 API → 新库映射
|
|
126
|
+
|
|
127
|
+
> 旧库 `Tree / Tree.Node`(hybridcloud,JSX 子组件式) → 新库 `Tree`(纯数据驱动)。
|
|
128
|
+
> 新库放弃 JSX `<Tree.Node>` 子组件嵌套,改用 `data: TreeNode[]` 数组(对齐 antd 5+ 的 `treeData` 风格)— tree-shake 友好 / 序列化方便 / 异步加载更直观。
|
|
129
|
+
|
|
130
|
+
### 命名映射
|
|
131
|
+
|
|
132
|
+
| 旧库 API | 新库 API | 备注 |
|
|
133
|
+
| --- | --- | --- |
|
|
134
|
+
| `<Tree>` + `<Tree.Node>` 子组件嵌套 | `<Tree data={[{ key, title, children }]} />` | **Breaking** — 改为数据驱动 |
|
|
135
|
+
| `dataSource` | `data` | 字段命名简化 |
|
|
136
|
+
| `Tree.Node` 的 `key/label/children` | `TreeNode.key/title/children` | `label` → `title`(对齐 antd) |
|
|
137
|
+
| `checkedKeys` / `selectedKeys` / `expandedKeys` | 同名保留 | 受控集合 |
|
|
138
|
+
| `defaultCheckedKeys` / `defaultSelectedKeys` / `defaultExpandedKeys` | 同名保留 | uncontrolled 初值 |
|
|
139
|
+
| `defaultExpandAll` | 同名保留 | 仅 uncontrolled 模式 |
|
|
140
|
+
| `onCheck(keys, extra)` | `onCheck(keys)` | 单参数化(extra 信息可在 data 里查) |
|
|
141
|
+
| `onSelect(keys, extra)` | `onSelect(keys)` | 同上 |
|
|
142
|
+
| `isLeaf`(Node prop) | `TreeNode.isLeaf`(data field) | 数据字段化 |
|
|
143
|
+
| `disabled`(Node prop) | `TreeNode.disabled`(data field) | 同上 |
|
|
144
|
+
| `icon`(Node prop) | `TreeNode.icon`(data field) | 同上 |
|
|
145
|
+
|
|
146
|
+
### Breaking Changes(从旧库迁移时需改写)
|
|
147
|
+
|
|
148
|
+
1. **JSX `<Tree.Node>` 全部改写为 `data` 数组** — 这是最大改动,业务工程需要重构数据结构
|
|
149
|
+
2. `dataSource` → `data`
|
|
150
|
+
3. `label` → `title`(节点字段)
|
|
151
|
+
4. `onCheck(keys, extra)` → `onCheck(keys)`(extra 信息消失,业务侧自查 data)
|
|
152
|
+
|
|
153
|
+
### 不修复 / 后续工序清单(报告 §3 P1/P2)
|
|
154
|
+
|
|
155
|
+
> 以下功能在新库未实现,**业务真有需求时**优先做。多数依赖外部库或较复杂的 source 改造。
|
|
156
|
+
|
|
157
|
+
- **`draggable` 拖拽排序**(P1):需集成 `@dnd-kit/core` + `@dnd-kit/sortable`,本组件不内置;业务侧自接 dnd-kit
|
|
158
|
+
- **`loadData` 异步加载子节点**(P1):点击展开时触发 fetch,目前业务侧用受控 `expandedKeys` + `onExpand` 自管异步;后续工序加 prop
|
|
159
|
+
- **`checkStrictly` 父子不关联**(P1):checkable 模式下严格独立勾选,目前固定级联;后续 prop
|
|
160
|
+
- **`useVirtual` 虚拟滚动**(P1):大数据量(> 1000 节点)首次渲染卡顿,后续可集成 `react-window` 或 `@tanstack/react-virtual`
|
|
161
|
+
- **`editable` 节点编辑**(P2):双击节点变 Input;业务侧用 `title: <Input />` 自定义渲染替代
|
|
162
|
+
- **`filterTreeNode` 过滤高亮**(P2):配合 TreeSelect 的 showSearch 使用,需在 Tree 层先支持
|
|
163
|
+
|
|
164
|
+
### 不修复(报告 §5 已明确)
|
|
165
|
+
|
|
166
|
+
- **JSX `<Tree.Node>`**:数据驱动是显式优势,不回退
|
|
167
|
+
- **`labelRender` vs `label(ReactNode)`**:`title` 直接接 ReactNode,无需另设 render prop
|
|
168
|
+
- **展开动画**:CSS transition 已内置(对齐 antd 默认)
|
|
169
|
+
- **`focusedKey` / `autoFocus`**:Radix-style 内管,不暴露
|
|
@@ -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-
|
|
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 *
|
|
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
|
|
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] =
|
|
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-
|
|
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
|
|
@@ -3,7 +3,7 @@ id: tree-select
|
|
|
3
3
|
name: TreeSelect
|
|
4
4
|
displayName: 树选择
|
|
5
5
|
type: component
|
|
6
|
-
category:
|
|
6
|
+
category: data-entry
|
|
7
7
|
since: 0.1.0
|
|
8
8
|
package: '@teamix-evo/ui'
|
|
9
9
|
---
|
|
@@ -27,36 +27,34 @@ package: '@teamix-evo/ui'
|
|
|
27
27
|
## Props
|
|
28
28
|
|
|
29
29
|
<!-- auto:props:begin -->
|
|
30
|
-
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
| `
|
|
34
|
-
| `
|
|
35
|
-
| `
|
|
36
|
-
| `
|
|
37
|
-
| `
|
|
38
|
-
| `
|
|
39
|
-
| `
|
|
40
|
-
| `
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
|
|
30
|
+
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
31
|
+
| --- | --- | --- | --- | --- |
|
|
32
|
+
| `data` | `TreeNode[]` | – | ✓ | 树形数据(antd `treeData` 并集)。 |
|
|
33
|
+
| `multiple` | `boolean` | `false` | – | 多选模式 — 启用后下拉内的 Tree 变为 checkable;value 是 key 数组。 |
|
|
34
|
+
| `value` | `string \| string[]` | – | – | 受控 value: - `multiple=false`:`string`(单 key)/ `undefined`(未选) - `multiple=true`:`string[]` |
|
|
35
|
+
| `defaultValue` | `string \| string[]` | – | – | uncontrolled 初值。 |
|
|
36
|
+
| `onChange` | `(value: string \| string[]) => void` | – | – | value 变化回调。 |
|
|
37
|
+
| `defaultExpandAll` | `boolean` | `false` | – | 默认展开全部节点(antd `treeDefaultExpandAll` 并集)。 |
|
|
38
|
+
| `placeholder` | `string` | `"请选择"` | – | 占位文本。 |
|
|
39
|
+
| `disabled` | `boolean` | – | – | 整体禁用。 |
|
|
40
|
+
| `className` | `string` | – | – | 触发器 className。 |
|
|
41
|
+
| `size` | `'sm' \| 'md' \| 'default' \| 'lg'` | `"default"` | – | 触发器尺寸。 |
|
|
42
|
+
| `allowClear` | `boolean` | `false` | – | 显示清除按钮(antd `allowClear` 并集) — 触发器有值时右侧出现 ✕,点击清空。 |
|
|
44
43
|
<!-- auto:props:end -->
|
|
45
44
|
|
|
46
45
|
## 依赖
|
|
47
46
|
|
|
48
47
|
<!-- auto:deps:begin -->
|
|
49
|
-
|
|
50
48
|
### 同库依赖
|
|
51
49
|
|
|
52
50
|
> `teamix-evo ui add tree-select` 时,以下 entry 会被自动连带安装(无需手动 add)。
|
|
53
51
|
|
|
54
|
-
| Entry
|
|
55
|
-
|
|
|
56
|
-
| `cn`
|
|
57
|
-
| `button`
|
|
58
|
-
| `popover` | component | 可交互浮层 — Radix Popover + antd arrow
|
|
59
|
-
| `tree`
|
|
52
|
+
| Entry | 类型 | 描述 |
|
|
53
|
+
| --- | --- | --- |
|
|
54
|
+
| `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
|
|
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 命名统一) |
|
|
57
|
+
| `tree` | component | 树形控件 — antd 独有补足。递归层级展示(目录、组织、分类),可展开 / 可选 / 可勾选(父子级联 + 半选),受控与非受控并存 |
|
|
60
58
|
|
|
61
59
|
### npm 依赖
|
|
62
60
|
|
|
@@ -65,7 +63,6 @@ package: '@teamix-evo/ui'
|
|
|
65
63
|
```bash
|
|
66
64
|
pnpm add lucide-react@^0.460.0
|
|
67
65
|
```
|
|
68
|
-
|
|
69
66
|
<!-- auto:deps:end -->
|
|
70
67
|
|
|
71
68
|
## AI 生成纪律
|
|
@@ -112,4 +109,43 @@ const [v, setV] = React.useState<string[]>(['fe', 'be']);
|
|
|
112
109
|
value={v}
|
|
113
110
|
onChange={(next) => setV(next as string[])}
|
|
114
111
|
/>;
|
|
112
|
+
|
|
113
|
+
// 可清除(hover 时右侧出现 ✕)
|
|
114
|
+
<TreeSelect data={data} allowClear defaultValue="fe" />;
|
|
115
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,9 +1,9 @@
|
|
|
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: '
|
|
6
|
+
title: '数据录入 · Data Entry/TreeSelect',
|
|
7
7
|
component: TreeSelect,
|
|
8
8
|
tags: ['autodocs'],
|
|
9
9
|
parameters: {
|
|
@@ -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 = '
|
|
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-
|
|
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-panel-sm 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
|
-
|
|
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-
|
|
173
|
+
<PopoverContent className="w-72 p-1" align="start">
|
|
139
174
|
{multiple ? (
|
|
140
175
|
<Tree
|
|
141
176
|
data={data}
|
|
@@ -3,24 +3,24 @@ id: typography
|
|
|
3
3
|
name: Typography
|
|
4
4
|
displayName: 排版
|
|
5
5
|
type: component
|
|
6
|
-
category:
|
|
6
|
+
category: general
|
|
7
7
|
since: 0.1.0
|
|
8
8
|
package: '@teamix-evo/ui'
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# Typography 排版
|
|
12
12
|
|
|
13
|
-
排版组件 — `Prose`(富文本容器)+ shadcn 风格 `Title / Paragraph / Text / Link` + antd `Text` 的 `
|
|
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。
|
|
14
14
|
|
|
15
15
|
> Prose 不依赖 `@tailwindcss/typography` 插件,样式手写并对齐 OpenTrek tokens。
|
|
16
16
|
|
|
17
17
|
## When to use
|
|
18
18
|
|
|
19
19
|
- **Prose**:Markdown / CMS 富文本渲染容器(自动套排版样式)
|
|
20
|
-
- **Title**:页面 / 区块标题(`level={1..
|
|
20
|
+
- **Title**:页面 / 区块标题(`level={1..6}` 自动映射 `<h1>~<h6>`,对齐 antd `Typography.Title.level`)
|
|
21
21
|
- **Paragraph**:正文段落(行高 / 字号 / 颜色统一)
|
|
22
|
-
- **Text**:行内文本带语义色 / 强调 / 复制
|
|
23
|
-
- **Link**:语义化链接(
|
|
22
|
+
- **Text**:行内文本带语义色(`color`) / 强调 / 复制
|
|
23
|
+
- **Link**:语义化链接(`color` + 默认下划线 hover)
|
|
24
24
|
|
|
25
25
|
## When NOT to use
|
|
26
26
|
|
|
@@ -33,31 +33,15 @@ package: '@teamix-evo/ui'
|
|
|
33
33
|
> 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`typography.tsx`](./typography.tsx) 的 `TextProps` interface JSDoc。
|
|
34
34
|
|
|
35
35
|
<!-- auto:props:begin -->
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `code` | `boolean` | `false` | – | 行内代码样式(`code`)。 |
|
|
46
|
-
| `ellipsis` | `boolean` | `false` | – | 单行省略(antd `ellipsis` 简化版 — 只支持 boolean,行数 / suffix 留 v0.x)。 |
|
|
47
|
-
| `copyable` | `boolean \| { text: string; tooltips?: [string, string] }` | `false` | – | 可复制(antd `copyable` 并集)— 末尾追加复制图标按钮。 传对象时可指定要复制的文本(默认是 children 的纯文本);传 `true` 用 children。 |
|
|
48
|
-
|
|
49
|
-
#### Title
|
|
50
|
-
|
|
51
|
-
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
52
|
-
| ------- | ----------------------- | ------ | ---- | ------------------------------------------------------- |
|
|
53
|
-
| `level` | `1 \| 2 \| 3 \| 4 \| 5` | `1` | – | 层级(1~5),决定字号 / 粗细;同时映射为 `<h1>~<h5>` 标签。 |
|
|
54
|
-
|
|
55
|
-
#### Link
|
|
56
|
-
|
|
57
|
-
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
58
|
-
| ------ | ---------- | ----------- | ---- | ------------------------- |
|
|
59
|
-
| `type` | `TextType` | `"default"` | – | 语义色(同 Text 的 type)。 |
|
|
60
|
-
|
|
36
|
+
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
37
|
+
| --- | --- | --- | --- | --- |
|
|
38
|
+
| `color` | `TextColor` | `"default"` | – | 语义色 — 6 档枚举,字面与 OpenTrek tokens 对齐(见 [ADR 0021](../../../../../docs/adr/0021-semantic-color-api-unification.md))。 antd `type` 迁移:`secondary`→`muted`、`danger`→`destructive`。 |
|
|
39
|
+
| `delete` | `boolean` | `false` | – | 删除线。 |
|
|
40
|
+
| `disabled` | `boolean` | `false` | – | 不可用(灰色 + 不可选)。 |
|
|
41
|
+
| `strong` | `boolean` | `false` | – | 加粗。 |
|
|
42
|
+
| `code` | `boolean` | `false` | – | 行内代码样式(`code`)。 |
|
|
43
|
+
| `ellipsis` | `boolean` | `false` | – | 单行省略(antd `ellipsis` 简化版 — 只支持 boolean,行数 / suffix 留 v0.x)。 |
|
|
44
|
+
| `copyable` | `boolean \| { text: string; tooltips?: [string, string] }` | `false` | – | 可复制(antd `copyable` 并集)— 末尾追加复制图标按钮。 传对象时可指定要复制的文本(默认是 children 的纯文本);传 `true` 用 children。 |
|
|
61
45
|
<!-- auto:props:end -->
|
|
62
46
|
|
|
63
47
|
## 依赖
|
|
@@ -65,14 +49,13 @@ package: '@teamix-evo/ui'
|
|
|
65
49
|
> 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`manifest.json`](../../../manifest.json)。**手工编辑 marker 之间的内容会在下次生成时被覆盖**。
|
|
66
50
|
|
|
67
51
|
<!-- auto:deps:begin -->
|
|
68
|
-
|
|
69
52
|
### 同库依赖
|
|
70
53
|
|
|
71
54
|
> `teamix-evo ui add typography` 时,以下 entry 会被自动连带安装(无需手动 add)。
|
|
72
55
|
|
|
73
|
-
| Entry | 类型 | 描述
|
|
74
|
-
|
|
|
75
|
-
| `cn`
|
|
56
|
+
| Entry | 类型 | 描述 |
|
|
57
|
+
| --- | --- | --- |
|
|
58
|
+
| `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
|
|
76
59
|
|
|
77
60
|
### npm 依赖
|
|
78
61
|
|
|
@@ -81,17 +64,56 @@ package: '@teamix-evo/ui'
|
|
|
81
64
|
```bash
|
|
82
65
|
pnpm add lucide-react@^0.460.0
|
|
83
66
|
```
|
|
84
|
-
|
|
85
67
|
<!-- auto:deps:end -->
|
|
86
68
|
|
|
87
69
|
## AI 生成纪律
|
|
88
70
|
|
|
89
71
|
- **`Title level` 决定标签**:不要用 `<h2>` 配 `level={1}`,语义会冲突
|
|
90
|
-
- **`Text
|
|
72
|
+
- **`Text color` 优先于 className 颜色**:语义色让暗色模式自动适配
|
|
91
73
|
- **`copyable` 仅当 children 是 string**:富节点请显式传 `copyable={{ text: '...' }}`
|
|
92
74
|
- **`ellipsis` 单行**:多行省略请直接 `className="line-clamp-2"`
|
|
93
75
|
- **Prose 内部不要嵌套 Prose**:嵌套排版会双倍间距
|
|
94
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
|
+
|
|
95
117
|
## Examples
|
|
96
118
|
|
|
97
119
|
```tsx
|
|
@@ -105,8 +127,8 @@ import { Prose, Title, Paragraph, Text, Link } from '@/components/ui/typography'
|
|
|
105
127
|
<Paragraph>正文段落,统一字号 / 行高 / 颜色。</Paragraph>
|
|
106
128
|
|
|
107
129
|
// 行内文本
|
|
108
|
-
<Text
|
|
109
|
-
<Text
|
|
130
|
+
<Text color="success" strong>成功</Text>
|
|
131
|
+
<Text color="destructive" delete>已废弃</Text>
|
|
110
132
|
<Text disabled>不可用</Text>
|
|
111
133
|
<Text code>const x = 1</Text>
|
|
112
134
|
<Text ellipsis>这是一段非常长的文字...被截断</Text>
|
|
@@ -115,7 +137,7 @@ import { Prose, Title, Paragraph, Text, Link } from '@/components/ui/typography'
|
|
|
115
137
|
|
|
116
138
|
// 链接
|
|
117
139
|
<Link href="/docs">文档</Link>
|
|
118
|
-
<Link href="/danger"
|
|
140
|
+
<Link href="/danger" color="destructive">危险链接</Link>
|
|
119
141
|
|
|
120
142
|
// Prose 容器(渲染 Markdown 等富文本)
|
|
121
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: '
|
|
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`
|
|
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
|
|
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
|
|
40
|
-
<Text
|
|
41
|
-
<Text
|
|
42
|
-
<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>
|
|
@@ -76,7 +77,11 @@ export const Links: Story = {
|
|
|
76
77
|
<Link href="#docs" onClick={(e) => e.preventDefault()}>
|
|
77
78
|
文档
|
|
78
79
|
</Link>
|
|
79
|
-
<Link
|
|
80
|
+
<Link
|
|
81
|
+
href="#delete"
|
|
82
|
+
color="destructive"
|
|
83
|
+
onClick={(e) => e.preventDefault()}
|
|
84
|
+
>
|
|
80
85
|
危险操作链接
|
|
81
86
|
</Link>
|
|
82
87
|
</div>
|