@teamix-evo/ui 0.1.1 → 0.2.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 (229) hide show
  1. package/README.md +1 -1
  2. package/package.json +8 -4
  3. package/src/components/accordion/accordion.meta.md +10 -5
  4. package/src/components/accordion/accordion.stories.tsx +11 -6
  5. package/src/components/affix/affix.meta.md +19 -10
  6. package/src/components/affix/affix.stories.tsx +4 -2
  7. package/src/components/alert/alert.meta.md +19 -14
  8. package/src/components/alert/alert.stories.tsx +1 -1
  9. package/src/components/alert/alert.tsx +5 -5
  10. package/src/components/alert-dialog/alert-dialog.meta.md +23 -10
  11. package/src/components/alert-dialog/alert-dialog.stories.tsx +1 -1
  12. package/src/components/alert-dialog/alert-dialog.tsx +1 -1
  13. package/src/components/anchor/anchor.meta.md +20 -11
  14. package/src/components/anchor/anchor.stories.tsx +1 -1
  15. package/src/components/app/app.meta.md +19 -10
  16. package/src/components/app/app.stories.tsx +4 -2
  17. package/src/components/aspect-ratio/aspect-ratio.meta.md +10 -5
  18. package/src/components/aspect-ratio/aspect-ratio.stories.tsx +1 -1
  19. package/src/components/auto-complete/auto-complete.meta.md +25 -16
  20. package/src/components/auto-complete/auto-complete.stories.tsx +4 -2
  21. package/src/components/avatar/avatar.meta.md +23 -11
  22. package/src/components/avatar/avatar.stories.tsx +1 -1
  23. package/src/components/badge/badge.meta.md +26 -21
  24. package/src/components/badge/badge.tsx +7 -13
  25. package/src/components/breadcrumb/breadcrumb.meta.md +21 -10
  26. package/src/components/breadcrumb/breadcrumb.stories.tsx +8 -0
  27. package/src/components/button/button.meta.md +22 -17
  28. package/src/components/button/button.stories.tsx +1 -1
  29. package/src/components/button/demo/as-child.tsx +24 -0
  30. package/src/components/button/demo/basic.tsx +8 -0
  31. package/src/components/button/demo/block.tsx +16 -0
  32. package/src/components/button/demo/loading.tsx +19 -0
  33. package/src/components/button/demo/shapes.tsx +18 -0
  34. package/src/components/button/demo/sizes.tsx +19 -0
  35. package/src/components/button/demo/variants.tsx +19 -0
  36. package/src/components/button/demo/with-icon.tsx +20 -0
  37. package/src/components/button-group/button-group.meta.md +18 -9
  38. package/src/components/button-group/button-group.stories.tsx +5 -2
  39. package/src/components/calendar/calendar.meta.md +14 -9
  40. package/src/components/calendar/calendar.stories.tsx +1 -1
  41. package/src/components/calendar/calendar.tsx +1 -1
  42. package/src/components/card/card.meta.md +36 -11
  43. package/src/components/card/card.stories.tsx +8 -0
  44. package/src/components/carousel/carousel.meta.md +16 -11
  45. package/src/components/carousel/carousel.stories.tsx +10 -5
  46. package/src/components/cascader/cascader.meta.md +28 -19
  47. package/src/components/cascader/cascader.stories.tsx +9 -8
  48. package/src/components/cascader/cascader.tsx +2 -2
  49. package/src/components/checkbox/checkbox.meta.md +26 -8
  50. package/src/components/checkbox/checkbox.stories.tsx +1 -1
  51. package/src/components/collapsible/collapsible.meta.md +11 -4
  52. package/src/components/collapsible/collapsible.stories.tsx +8 -0
  53. package/src/components/color-picker/color-picker.meta.md +27 -18
  54. package/src/components/color-picker/color-picker.stories.tsx +1 -1
  55. package/src/components/color-picker/color-picker.tsx +1 -0
  56. package/src/components/combobox/combobox.meta.md +29 -20
  57. package/src/components/combobox/combobox.stories.tsx +1 -1
  58. package/src/components/combobox/combobox.tsx +3 -3
  59. package/src/components/command/command.meta.md +32 -12
  60. package/src/components/command/command.stories.tsx +1 -1
  61. package/src/components/command/command.tsx +1 -1
  62. package/src/components/context-menu/context-menu.meta.md +34 -11
  63. package/src/components/context-menu/context-menu.stories.tsx +8 -0
  64. package/src/components/context-menu/context-menu.tsx +2 -2
  65. package/src/components/data-table/data-table.meta.md +24 -19
  66. package/src/components/data-table/data-table.stories.tsx +12 -5
  67. package/src/components/date-picker/date-picker.meta.md +40 -20
  68. package/src/components/date-picker/date-picker.stories.tsx +1 -1
  69. package/src/components/descriptions/descriptions.meta.md +23 -14
  70. package/src/components/descriptions/descriptions.stories.tsx +1 -1
  71. package/src/components/dialog/dialog.meta.md +25 -12
  72. package/src/components/dialog/dialog.stories.tsx +1 -1
  73. package/src/components/dialog/dialog.tsx +1 -1
  74. package/src/components/drawer/drawer.meta.md +19 -8
  75. package/src/components/drawer/drawer.stories.tsx +1 -1
  76. package/src/components/drawer/drawer.tsx +1 -0
  77. package/src/components/dropdown-menu/dropdown-menu.meta.md +42 -14
  78. package/src/components/dropdown-menu/dropdown-menu.stories.tsx +8 -0
  79. package/src/components/dropdown-menu/dropdown-menu.tsx +2 -2
  80. package/src/components/empty/empty.meta.md +20 -11
  81. package/src/components/empty/empty.stories.tsx +1 -1
  82. package/src/components/field/field.meta.md +27 -10
  83. package/src/components/field/field.stories.tsx +6 -3
  84. package/src/components/flex/flex.meta.md +23 -14
  85. package/src/components/flex/flex.stories.tsx +46 -14
  86. package/src/components/float-button/float-button.meta.md +35 -11
  87. package/src/components/float-button/float-button.stories.tsx +4 -2
  88. package/src/components/float-button/float-button.tsx +1 -1
  89. package/src/components/form/form.meta.md +57 -14
  90. package/src/components/form/form.stories.tsx +1 -1
  91. package/src/components/grid/grid.meta.md +31 -6
  92. package/src/components/grid/grid.stories.tsx +4 -2
  93. package/src/components/hover-card/hover-card.meta.md +21 -9
  94. package/src/components/hover-card/hover-card.stories.tsx +6 -2
  95. package/src/components/image/image.meta.md +24 -15
  96. package/src/components/image/image.stories.tsx +1 -1
  97. package/src/components/image/image.tsx +4 -4
  98. package/src/components/input/demo/addon.tsx +15 -0
  99. package/src/components/input/demo/basic.tsx +12 -0
  100. package/src/components/input/demo/clearable.tsx +21 -0
  101. package/src/components/input/demo/show-count.tsx +18 -0
  102. package/src/components/input/demo/sizes.tsx +15 -0
  103. package/src/components/input/demo/with-prefix-suffix.tsx +19 -0
  104. package/src/components/input/input.meta.md +21 -16
  105. package/src/components/input/input.stories.tsx +1 -1
  106. package/src/components/input/input.tsx +51 -47
  107. package/src/components/input-group/input-group.meta.md +26 -8
  108. package/src/components/input-group/input-group.stories.tsx +1 -1
  109. package/src/components/input-group/input-group.tsx +4 -3
  110. package/src/components/input-number/input-number.meta.md +26 -17
  111. package/src/components/input-number/input-number.stories.tsx +14 -3
  112. package/src/components/input-number/input-number.tsx +20 -6
  113. package/src/components/input-otp/input-otp.meta.md +22 -9
  114. package/src/components/input-otp/input-otp.stories.tsx +1 -1
  115. package/src/components/item/item.meta.md +32 -9
  116. package/src/components/item/item.stories.tsx +5 -2
  117. package/src/components/kbd/kbd.meta.md +29 -8
  118. package/src/components/kbd/kbd.stories.tsx +1 -1
  119. package/src/components/kbd/kbd.tsx +2 -1
  120. package/src/components/label/label.meta.md +14 -9
  121. package/src/components/masonry/masonry.meta.md +18 -9
  122. package/src/components/masonry/masonry.stories.tsx +4 -2
  123. package/src/components/masonry/masonry.tsx +1 -0
  124. package/src/components/mentions/mentions.meta.md +28 -19
  125. package/src/components/mentions/mentions.stories.tsx +1 -1
  126. package/src/components/mentions/mentions.tsx +2 -1
  127. package/src/components/menubar/menubar.meta.md +36 -14
  128. package/src/components/menubar/menubar.stories.tsx +8 -0
  129. package/src/components/menubar/menubar.tsx +2 -2
  130. package/src/components/native-select/native-select.meta.md +17 -8
  131. package/src/components/native-select/native-select.stories.tsx +6 -3
  132. package/src/components/navigation-menu/navigation-menu.meta.md +25 -11
  133. package/src/components/navigation-menu/navigation-menu.stories.tsx +11 -11
  134. package/src/components/navigation-menu/navigation-menu.tsx +3 -2
  135. package/src/components/notification/notification.meta.md +14 -5
  136. package/src/components/notification/notification.stories.tsx +5 -3
  137. package/src/components/notification/notification.tsx +3 -3
  138. package/src/components/pagination/pagination.meta.md +59 -28
  139. package/src/components/pagination/pagination.stories.tsx +9 -3
  140. package/src/components/popconfirm/popconfirm.meta.md +30 -21
  141. package/src/components/popconfirm/popconfirm.stories.tsx +1 -2
  142. package/src/components/popconfirm/popconfirm.tsx +1 -1
  143. package/src/components/popover/popover.meta.md +13 -8
  144. package/src/components/popover/popover.stories.tsx +1 -1
  145. package/src/components/progress/progress.meta.md +28 -13
  146. package/src/components/progress/progress.stories.tsx +1 -1
  147. package/src/components/progress/progress.tsx +6 -6
  148. package/src/components/radio-group/radio-group.meta.md +17 -12
  149. package/src/components/radio-group/radio-group.stories.tsx +1 -1
  150. package/src/components/rate/rate.meta.md +25 -16
  151. package/src/components/rate/rate.stories.tsx +11 -3
  152. package/src/components/rate/rate.tsx +2 -2
  153. package/src/components/resizable/resizable.meta.md +19 -8
  154. package/src/components/resizable/resizable.stories.tsx +1 -1
  155. package/src/components/result/result.meta.md +21 -12
  156. package/src/components/result/result.stories.tsx +2 -6
  157. package/src/components/result/result.tsx +3 -3
  158. package/src/components/scroll-area/scroll-area.meta.md +10 -5
  159. package/src/components/scroll-area/scroll-area.stories.tsx +8 -0
  160. package/src/components/scroll-area/scroll-area.tsx +3 -3
  161. package/src/components/segmented/segmented.meta.md +19 -14
  162. package/src/components/segmented/segmented.stories.tsx +35 -6
  163. package/src/components/select/select.meta.md +22 -9
  164. package/src/components/select/select.stories.tsx +1 -1
  165. package/src/components/select/select.tsx +2 -2
  166. package/src/components/separator/separator.meta.md +16 -11
  167. package/src/components/separator/separator.stories.tsx +1 -1
  168. package/src/components/sheet/sheet.meta.md +22 -11
  169. package/src/components/sheet/sheet.stories.tsx +1 -1
  170. package/src/components/sidebar/sidebar.meta.md +47 -18
  171. package/src/components/sidebar/sidebar.stories.tsx +10 -5
  172. package/src/components/skeleton/skeleton.meta.md +33 -10
  173. package/src/components/skeleton/skeleton.stories.tsx +1 -1
  174. package/src/components/slider/slider.meta.md +12 -7
  175. package/src/components/slider/slider.stories.tsx +1 -1
  176. package/src/components/sonner/sonner.meta.md +8 -3
  177. package/src/components/sonner/sonner.stories.tsx +13 -8
  178. package/src/components/space/space.meta.md +22 -13
  179. package/src/components/space/space.stories.tsx +20 -6
  180. package/src/components/spinner/spinner.meta.md +23 -10
  181. package/src/components/spinner/spinner.stories.tsx +1 -1
  182. package/src/components/statistic/statistic.meta.md +37 -16
  183. package/src/components/statistic/statistic.stories.tsx +2 -6
  184. package/src/components/statistic/statistic.tsx +1 -1
  185. package/src/components/steps/steps.meta.md +21 -12
  186. package/src/components/steps/steps.stories.tsx +7 -2
  187. package/src/components/switch/switch.meta.md +16 -11
  188. package/src/components/switch/switch.stories.tsx +1 -1
  189. package/src/components/switch/switch.tsx +58 -36
  190. package/src/components/table/table.meta.md +24 -9
  191. package/src/components/table/table.stories.tsx +9 -4
  192. package/src/components/tabs/tabs.meta.md +14 -9
  193. package/src/components/tabs/tabs.stories.tsx +8 -0
  194. package/src/components/tag/tag.meta.md +39 -10
  195. package/src/components/tag/tag.stories.tsx +7 -2
  196. package/src/components/tag/tag.tsx +3 -3
  197. package/src/components/textarea/textarea.meta.md +17 -12
  198. package/src/components/textarea/textarea.stories.tsx +1 -1
  199. package/src/components/textarea/textarea.tsx +1 -1
  200. package/src/components/time-picker/time-picker.meta.md +38 -15
  201. package/src/components/time-picker/time-picker.stories.tsx +44 -6
  202. package/src/components/time-picker/time-picker.tsx +74 -10
  203. package/src/components/timeline/timeline.meta.md +20 -11
  204. package/src/components/timeline/timeline.stories.tsx +14 -4
  205. package/src/components/timeline/timeline.tsx +3 -2
  206. package/src/components/toggle/toggle.meta.md +14 -9
  207. package/src/components/toggle/toggle.stories.tsx +1 -1
  208. package/src/components/toggle-group/toggle-group.meta.md +16 -11
  209. package/src/components/toggle-group/toggle-group.stories.tsx +1 -1
  210. package/src/components/tooltip/tooltip.meta.md +18 -13
  211. package/src/components/tooltip/tooltip.stories.tsx +1 -1
  212. package/src/components/tour/tour.meta.md +25 -16
  213. package/src/components/tour/tour.stories.tsx +1 -1
  214. package/src/components/tour/tour.tsx +1 -1
  215. package/src/components/transfer/transfer.meta.md +29 -20
  216. package/src/components/transfer/transfer.stories.tsx +2 -6
  217. package/src/components/tree/tree.meta.md +36 -23
  218. package/src/components/tree/tree.stories.tsx +30 -11
  219. package/src/components/tree-select/tree-select.meta.md +37 -22
  220. package/src/components/tree-select/tree-select.stories.tsx +1 -1
  221. package/src/components/tree-select/tree-select.tsx +1 -1
  222. package/src/components/typography/typography.meta.md +41 -16
  223. package/src/components/typography/typography.stories.tsx +4 -8
  224. package/src/components/typography/typography.tsx +5 -3
  225. package/src/components/upload/upload.meta.md +31 -22
  226. package/src/components/upload/upload.stories.tsx +8 -14
  227. package/src/components/watermark/watermark.meta.md +26 -17
  228. package/src/components/watermark/watermark.stories.tsx +4 -2
  229. package/src/components/watermark/watermark.tsx +1 -0
@@ -4,14 +4,16 @@ name: HoverCard
4
4
  type: component
5
5
  category: feedback
6
6
  since: 0.1.0
7
- package: "@teamix-evo/ui"
7
+ package: '@teamix-evo/ui'
8
+ displayName: 悬浮卡片
8
9
  ---
9
10
 
10
- # HoverCard
11
+ # HoverCard 悬浮卡片
11
12
 
12
13
  悬浮信息卡 — Radix HoverCard 包装。**shadcn-only**(antd 无对标 — antd Tooltip 仅文字,Popover 是 click 触发,HoverCard 是 hover 触发的富内容)。
13
14
 
14
15
  `Tooltip` 与 `HoverCard` 的边界:
16
+
15
17
  - 1 行简短文字 → `Tooltip`
16
18
  - 多行 / 含图片 / 含弱交互(链接 / Avatar)→ `HoverCard`
17
19
 
@@ -32,7 +34,9 @@ package: "@teamix-evo/ui"
32
34
  > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成。下表为 `HoverCardContent` 的 props;`HoverCard` Root 透传 `openDelay / closeDelay / open / defaultOpen / onOpenChange`。
33
35
 
34
36
  <!-- auto:props:begin -->
37
+
35
38
  _(no props)_
39
+
36
40
  <!-- auto:props:end -->
37
41
 
38
42
  ## 依赖
@@ -40,13 +44,14 @@ _(no props)_
40
44
  > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`manifest.json`](../../../manifest.json)。**手工编辑 marker 之间的内容会在下次生成时被覆盖**。
41
45
 
42
46
  <!-- auto:deps:begin -->
47
+
43
48
  ### 同库依赖
44
49
 
45
50
  > `teamix-evo ui add hover-card` 时,以下 entry 会被自动连带安装(无需手动 add)。
46
51
 
47
- | Entry | 类型 | 描述 |
48
- | --- | --- | --- |
49
- | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
52
+ | Entry | 类型 | 描述 |
53
+ | ----- | ---- | -------------------------------------------------- |
54
+ | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
50
55
 
51
56
  ### npm 依赖
52
57
 
@@ -55,6 +60,7 @@ _(no props)_
55
60
  ```bash
56
61
  pnpm add @radix-ui/react-hover-card@^1.1.0
57
62
  ```
63
+
58
64
  <!-- auto:deps:end -->
59
65
 
60
66
  ## AI 生成纪律
@@ -68,13 +74,17 @@ pnpm add @radix-ui/react-hover-card@^1.1.0
68
74
 
69
75
  ```tsx
70
76
  import {
71
- HoverCard, HoverCardTrigger, HoverCardContent,
77
+ HoverCard,
78
+ HoverCardTrigger,
79
+ HoverCardContent,
72
80
  } from '@/components/ui/hover-card';
73
81
  import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar';
74
82
 
75
83
  <HoverCard>
76
84
  <HoverCardTrigger asChild>
77
- <a href="/u/lyca" className="font-medium text-primary hover:underline">@lyca</a>
85
+ <a href="/u/lyca" className="font-medium text-primary hover:underline">
86
+ @lyca
87
+ </a>
78
88
  </HoverCardTrigger>
79
89
  <HoverCardContent>
80
90
  <div className="flex gap-3">
@@ -84,9 +94,11 @@ import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar';
84
94
  </Avatar>
85
95
  <div className="space-y-1">
86
96
  <h4 className="text-sm font-semibold">@lyca</h4>
87
- <p className="text-xs text-muted-foreground">Frontend engineer · Joined 2020</p>
97
+ <p className="text-xs text-muted-foreground">
98
+ Frontend engineer · Joined 2020
99
+ </p>
88
100
  </div>
89
101
  </div>
90
102
  </HoverCardContent>
91
- </HoverCard>
103
+ </HoverCard>;
92
104
  ```
@@ -1,6 +1,10 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
2
  import { HoverCard, HoverCardTrigger, HoverCardContent } from './hover-card';
3
- import { Avatar, AvatarImage, AvatarFallback } from '@/components/avatar/avatar';
3
+ import {
4
+ Avatar,
5
+ AvatarImage,
6
+ AvatarFallback,
7
+ } from '@/components/avatar/avatar';
4
8
 
5
9
  const meta: Meta<typeof HoverCardContent> = {
6
10
  title: '反馈与浮层 · Feedback/HoverCard',
@@ -10,7 +14,7 @@ const meta: Meta<typeof HoverCardContent> = {
10
14
  docs: {
11
15
  description: {
12
16
  component:
13
- '悬浮卡片 — 鼠标悬停时延迟展示更多信息(常用于用户名片、链接预览)。基于 Radix HoverCard,**仅鼠标悬停触发**(键盘聚焦不触发,交互场景与 Tooltip / Popover 互补);支持 `side` / `align` 定位与 `openDelay` / `closeDelay`。shadcn 专有,antd 可由 `Popover` 的 trigger="hover" 近似实现。视觉走 OpenTrek semantic tokens,所有样式来自 `@teamix-evo/design`,无 mock。',
17
+ '悬浮卡片 — 鼠标悬停时延迟展示更多信息(常用于用户名片、链接预览)。基于 Radix HoverCard,**仅鼠标悬停触发**(键盘聚焦不触发,交互场景与 Tooltip / Popover 互补);支持 `side` / `align` 定位与 `openDelay` / `closeDelay`。shadcn 专有,antd 可由 `Popover` 的 trigger="hover" 近似实现。',
14
18
  },
15
19
  },
16
20
  },
@@ -1,13 +1,14 @@
1
1
  ---
2
2
  id: image
3
3
  name: Image
4
+ displayName: 图片
4
5
  type: component
5
6
  category: foundation
6
7
  since: 0.1.0
7
- package: "@teamix-evo/ui"
8
+ package: '@teamix-evo/ui'
8
9
  ---
9
10
 
10
- # Image
11
+ # Image 图片
11
12
 
12
13
  图片 — antd 独有补足。**自动处理加载态(Skeleton 占位)+ 失败态(图标)+ 点击预览**(Dialog 模态展示原图)。
13
14
 
@@ -23,27 +24,34 @@ package: "@teamix-evo/ui"
23
24
  - 强需求 lazy-load + 优化 → 用框架自带(Next.js `<Image>`)
24
25
  - 仅显示固定尺寸图标 → `<img>` 直接用
25
26
 
27
+ ## Props
28
+
26
29
  <!-- auto:props:begin -->
27
- | 名称 | 类型 | 默认值 | 必填 | 说明 |
28
- | --- | --- | --- | --- | --- |
29
- | `src` | `string` | | | |
30
- | `alt` | `string` | – | ✓ | – |
31
- | `preview` | `boolean` | `true` | – | 是否启用点击预览(antd `preview` 并集) — 点击后弹模态展示原图。 |
32
- | `fallback` | `React.ReactNode` | | – | 加载失败时显示的占位元素;不传则用默认 `ImageOff` 图标。 |
33
- | `placeholder` | `React.ReactNode` | – | – | 加载中显示的占位 默认 Skeleton 占位与图片同尺寸。 |
34
- | `className` | `string` | – | – | 容器 className(图片本身用 `imgClassName`)。 |
35
- | `imgClassName` | `string` | – | – | 真实 `<img>` 的 className(尺寸 / 圆角 / object-fit)。 |
30
+
31
+ | 名称 | 类型 | 默认值 | 必填 | 说明 |
32
+ | -------------- | ----------------- | ------ | ---- | -------------------------------------------------------------- |
33
+ | `src` | `string` | – | ✓ | – |
34
+ | `alt` | `string` | | | – |
35
+ | `preview` | `boolean` | `true` | – | 是否启用点击预览(antd `preview` 并集) — 点击后弹模态展示原图。 |
36
+ | `fallback` | `React.ReactNode` | – | – | 加载失败时显示的占位元素;不传则用默认 `ImageOff` 图标。 |
37
+ | `placeholder` | `React.ReactNode` | – | – | 加载中显示的占位 默认 Skeleton 占位与图片同尺寸。 |
38
+ | `className` | `string` | – | – | 容器 className(图片本身用 `imgClassName`)。 |
39
+ | `imgClassName` | `string` | – | – | 真实 `<img>` 的 className(尺寸 / 圆角 / object-fit)。 |
40
+
36
41
  <!-- auto:props:end -->
37
42
 
43
+ ## 依赖
44
+
38
45
  <!-- auto:deps:begin -->
46
+
39
47
  ### 同库依赖
40
48
 
41
49
  > `teamix-evo ui add image` 时,以下 entry 会被自动连带安装(无需手动 add)。
42
50
 
43
- | Entry | 类型 | 描述 |
44
- | --- | --- | --- |
45
- | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
46
- | `dialog` | component | 模态对话框 — Radix Dialog + antd Modal 并集(组合式 Header/Footer/Title/Description) |
51
+ | Entry | 类型 | 描述 |
52
+ | ---------- | --------- | ------------------------------------------------------------------------------------------------- |
53
+ | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
54
+ | `dialog` | component | 模态对话框 — Radix Dialog + antd Modal 并集(组合式 Header/Footer/Title/Description) |
47
55
  | `skeleton` | component | 骨架屏 — shadcn pulse 单元素 + antd Avatar/Image/Button/Input/Paragraph 子家族,自动 motion-reduce |
48
56
 
49
57
  ### npm 依赖
@@ -53,6 +61,7 @@ package: "@teamix-evo/ui"
53
61
  ```bash
54
62
  pnpm add lucide-react@^0.460.0
55
63
  ```
64
+
56
65
  <!-- auto:deps:end -->
57
66
 
58
67
  ## AI 生成纪律
@@ -9,7 +9,7 @@ const meta: Meta<typeof Image> = {
9
9
  docs: {
10
10
  description: {
11
11
  component:
12
- '图片 — 自动处理加载(Skeleton 占位)+ 失败(图标占位)+ 点击预览(Dialog 模态原图)。alt 必填(无障碍)。OpenTrek tokens 适配,等价 antd Image。',
12
+ '图片 — 自动处理加载(Skeleton 占位)+ 失败(图标占位)+ 点击预览(Dialog 模态原图)。alt 必填(无障碍)。等价 antd Image。',
13
13
  },
14
14
  },
15
15
  },
@@ -78,11 +78,11 @@ const Image = React.forwardRef<HTMLImageElement, ImageProps>(
78
78
  <>
79
79
  {status === 'loading' ? (
80
80
  <div className="absolute inset-0">
81
- {placeholder ?? <Skeleton className="size-full rounded-[inherit]" />}
81
+ {placeholder ?? <Skeleton className="size-full rounded-inherit" />}
82
82
  </div>
83
83
  ) : null}
84
84
  {status === 'error' ? (
85
- <div className="absolute inset-0 flex flex-col items-center justify-center gap-1 rounded-[inherit] bg-muted text-muted-foreground">
85
+ <div className="absolute inset-0 flex flex-col items-center justify-center gap-1 rounded-inherit bg-muted text-muted-foreground">
86
86
  {fallback ?? (
87
87
  <>
88
88
  <ImageOff className="size-6" />
@@ -115,14 +115,14 @@ const Image = React.forwardRef<HTMLImageElement, ImageProps>(
115
115
  <Dialog>
116
116
  <DialogTrigger asChild>{inner}</DialogTrigger>
117
117
  <DialogContent
118
- className="max-w-[90vw] border-0 bg-transparent p-0 shadow-none"
118
+ className="max-w-image-preview border-0 bg-transparent p-0 shadow-none"
119
119
  showClose={false}
120
120
  >
121
121
  <div className="relative">
122
122
  <img
123
123
  src={src}
124
124
  alt={alt}
125
- className="max-h-[85vh] w-auto rounded-md object-contain"
125
+ className="max-h-image-preview w-auto rounded-md object-contain"
126
126
  />
127
127
  <div className="pointer-events-none absolute -top-3 -right-3 flex size-8 items-center justify-center rounded-full bg-background text-foreground shadow">
128
128
  <X className="size-4" />
@@ -0,0 +1,15 @@
1
+ import { Input } from '@/components/ui/input';
2
+
3
+ /**
4
+ * 前后置标签:通过 `addonBefore` / `addonAfter` 形成 input-group。
5
+ * 常用于域名拼接、协议前缀、单位后缀。
6
+ */
7
+ export default function Demo() {
8
+ return (
9
+ <div className="flex w-96 flex-col gap-3">
10
+ <Input addonBefore="https://" placeholder="example.com" />
11
+ <Input addonAfter=".teamix.com" placeholder="alice" />
12
+ <Input addonBefore="https://" addonAfter=".com" placeholder="my-site" />
13
+ </div>
14
+ );
15
+ }
@@ -0,0 +1,12 @@
1
+ import { Input } from '@/components/ui/input';
2
+
3
+ /**
4
+ * 最简用法:原生 input 的并集语义,直接当受控/非受控输入框使用。
5
+ */
6
+ export default function Demo() {
7
+ return (
8
+ <div className="w-80">
9
+ <Input placeholder="请输入用户名" />
10
+ </div>
11
+ );
12
+ }
@@ -0,0 +1,21 @@
1
+ import { useState } from 'react';
2
+ import { Input } from '@/components/ui/input';
3
+
4
+ /**
5
+ * 一键清空:受控时点 X 会触发 onChange(""),非受控时直接清掉 DOM 值并派发 input 事件。
6
+ * 适合搜索框、过滤器场景。
7
+ */
8
+ export default function Demo() {
9
+ const [value, setValue] = useState('Teamix Evo');
10
+ return (
11
+ <div className="flex w-80 flex-col gap-3">
12
+ <Input
13
+ clearable
14
+ value={value}
15
+ onChange={(e) => setValue(e.target.value)}
16
+ placeholder="受控 + clearable"
17
+ />
18
+ <Input clearable defaultValue="非受控示例" />
19
+ </div>
20
+ );
21
+ }
@@ -0,0 +1,18 @@
1
+ import { Input } from '@/components/ui/input';
2
+
3
+ /**
4
+ * 字符计数:必须配合 `maxLength` 一起使用。
5
+ * 适合给社交平台发文、签名等限长场景。
6
+ */
7
+ export default function Demo() {
8
+ return (
9
+ <div className="w-80">
10
+ <Input
11
+ showCount
12
+ maxLength={20}
13
+ defaultValue="hello teamix"
14
+ placeholder="最多 20 字"
15
+ />
16
+ </div>
17
+ );
18
+ }
@@ -0,0 +1,15 @@
1
+ import { Input } from '@/components/ui/input';
2
+
3
+ /**
4
+ * 三种尺寸:sm / default / lg。
5
+ * 高度通过 internal class 控制,不要再外部覆盖 `h-*`。
6
+ */
7
+ export default function Demo() {
8
+ return (
9
+ <div className="flex w-80 flex-col gap-3">
10
+ <Input size="sm" placeholder="Small" />
11
+ <Input size="default" placeholder="Default" />
12
+ <Input size="lg" placeholder="Large" />
13
+ </div>
14
+ );
15
+ }
@@ -0,0 +1,19 @@
1
+ import { Search, Mail } from 'lucide-react';
2
+ import { Input } from '@/components/ui/input';
3
+
4
+ /**
5
+ * 前置 / 后置图标:通过 `prefix` / `suffix` 传任意 ReactNode(图标或文本)。
6
+ * 视觉对齐由组件内部处理,不要再额外用 padding 兼容图标。
7
+ */
8
+ export default function Demo() {
9
+ return (
10
+ <div className="flex w-80 flex-col gap-3">
11
+ <Input prefix={<Search />} placeholder="搜索..." />
12
+ <Input
13
+ prefix={<Mail />}
14
+ suffix={<span className="text-xs">@teamix.com</span>}
15
+ placeholder="alice"
16
+ />
17
+ </div>
18
+ );
19
+ }
@@ -4,10 +4,11 @@ name: Input
4
4
  type: component
5
5
  category: form
6
6
  since: 0.1.0
7
- package: "@teamix-evo/ui"
7
+ package: '@teamix-evo/ui'
8
+ displayName: 输入框
8
9
  ---
9
10
 
10
- # Input
11
+ # Input 输入框
11
12
 
12
13
  文本输入框 — shadcn 简洁版基底 + antd 的 `prefix / suffix / clearable / showCount / addonBefore / addonAfter / size`。
13
14
  单组件覆盖大部分表单输入场景,保持 forwardRef + 原生 `<input>` 透传。
@@ -32,17 +33,19 @@ package: "@teamix-evo/ui"
32
33
  > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成。
33
34
 
34
35
  <!-- auto:props:begin -->
35
- | 名称 | 类型 | 默认值 | 必填 | 说明 |
36
- | --- | --- | --- | --- | --- |
37
- | `prefix` | `React.ReactNode` | | | 输入框前置图标 / 文本(antd `prefix` 并集)。 |
38
- | `suffix` | `React.ReactNode` | – | – | 输入框后置图标 / 文本(antd `suffix` 并集)。 |
39
- | `clearable` | `boolean` | `false` | – | 显示清除按钮,有内容时点击清空(antd `allowClear` 并集)。 |
40
- | `showCount` | `boolean` | `false` | – | 显示字符计数(antd `showCount` 并集);需配合 `maxLength` 一起使用。 |
41
- | `addonBefore` | `React.ReactNode` | | – | 输入框前置标签(antd `addonBefore` 并集),与外层组合形成 input-group。 |
42
- | `addonAfter` | `React.ReactNode` | – | – | 输入框后置标签(antd `addonAfter` 并集)。 |
43
- | `size` | `'sm' \| 'default' \| 'lg'` | `"default"` | – | 尺寸。 |
44
- | `value` | `string` | | – | 受控值,用于 clearable / showCount 的逻辑;未传时回退到 uncontrolled 行为。 |
45
- | `defaultValue` | `string` | – | – | uncontrolled 初始值。 |
36
+
37
+ | 名称 | 类型 | 默认值 | 必填 | 说明 |
38
+ | -------------- | --------------------------- | ----------- | ---- | ------------------------------------------------------------------------- |
39
+ | `prefix` | `React.ReactNode` | – | – | 输入框前置图标 / 文本(antd `prefix` 并集)。 |
40
+ | `suffix` | `React.ReactNode` | | – | 输入框后置图标 / 文本(antd `suffix` 并集)。 |
41
+ | `clearable` | `boolean` | `false` | – | 显示清除按钮,有内容时点击清空(antd `allowClear` 并集)|
42
+ | `showCount` | `boolean` | `false` | – | 显示字符计数(antd `showCount` 并集);需配合 `maxLength` 一起使用。 |
43
+ | `addonBefore` | `React.ReactNode` | – | – | 输入框前置标签(antd `addonBefore` 并集),与外层组合形成 input-group |
44
+ | `addonAfter` | `React.ReactNode` | | – | 输入框后置标签(antd `addonAfter` 并集)。 |
45
+ | `size` | `'sm' \| 'default' \| 'lg'` | `"default"` | – | 尺寸。 |
46
+ | `value` | `string` | – | – | 受控值,用于 clearable / showCount 的逻辑;未传时回退到 uncontrolled 行为。 |
47
+ | `defaultValue` | `string` | – | – | uncontrolled 初始值。 |
48
+
46
49
  <!-- auto:props:end -->
47
50
 
48
51
  ## 依赖
@@ -50,13 +53,14 @@ package: "@teamix-evo/ui"
50
53
  > 以下表格由 `pnpm --filter @teamix-evo/ui gen:meta` 自动生成,数据源是 [`manifest.json`](../../../manifest.json)。**手工编辑 marker 之间的内容会在下次生成时被覆盖**。
51
54
 
52
55
  <!-- auto:deps:begin -->
56
+
53
57
  ### 同库依赖
54
58
 
55
59
  > `teamix-evo ui add input` 时,以下 entry 会被自动连带安装(无需手动 add)。
56
60
 
57
- | Entry | 类型 | 描述 |
58
- | --- | --- | --- |
59
- | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
61
+ | Entry | 类型 | 描述 |
62
+ | ----- | ---- | -------------------------------------------------- |
63
+ | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
60
64
 
61
65
  ### npm 依赖
62
66
 
@@ -65,6 +69,7 @@ package: "@teamix-evo/ui"
65
69
  ```bash
66
70
  pnpm add lucide-react@^0.460.0
67
71
  ```
72
+
68
73
  <!-- auto:deps:end -->
69
74
 
70
75
  > 透传所有 `<input>` 原生属性(`type` / `placeholder` / `name` / `id` / `aria-*` / `onChange` / ...)。
@@ -11,7 +11,7 @@ const meta: Meta<typeof Input> = {
11
11
  docs: {
12
12
  description: {
13
13
  component:
14
- '输入框 — 文本 / 邮箱 / 密码 / 搜索等单行输入。shadcn 原生 `<input>` 风格 + antd 扩展:`size` 三档、`prefix` / `suffix` 前后缀、`addonBefore` / `addonAfter` 外联组、`clearable` 一键清空、`showCount` + `maxLength` 字数统计。视觉走 OpenTrek semantic tokens,所有样式来自 `@teamix-evo/design`,无 mock。',
14
+ '输入框 — 文本 / 邮箱 / 密码 / 搜索等单行输入。shadcn 原生 `<input>` 风格 + antd 扩展:`size` 三档、`prefix` / `suffix` 前后缀、`addonBefore` / `addonAfter` 外联组、`clearable` 一键清空、`showCount` + `maxLength` 字数统计。',
15
15
  },
16
16
  },
17
17
  },
@@ -61,25 +61,21 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
61
61
  // Track the current value for clearable / showCount; mirror uncontrolled
62
62
  // input via internal state when `value` prop isn't provided.
63
63
  const isControlled = value !== undefined;
64
- const [internal, setInternal] = React.useState<string>(
65
- defaultValue ?? '',
66
- );
64
+ const [internal, setInternal] = React.useState<string>(defaultValue ?? '');
67
65
  const current = isControlled ? value : internal;
68
66
 
69
67
  const innerRef = React.useRef<HTMLInputElement | null>(null);
70
- React.useImperativeHandle(
71
- ref,
72
- () => innerRef.current as HTMLInputElement,
73
- );
68
+ React.useImperativeHandle(ref, () => innerRef.current as HTMLInputElement);
74
69
 
75
70
  const h =
76
71
  size === 'sm'
77
72
  ? 'h-8 text-xs'
78
73
  : size === 'lg'
79
- ? 'h-10 text-base'
80
- : 'h-9 text-sm';
74
+ ? 'h-10 text-base'
75
+ : 'h-9 text-sm';
81
76
 
82
77
  const hasAffix = prefix != null || suffix != null || clearable;
78
+ const hasAddon = addonBefore != null || addonAfter != null;
83
79
 
84
80
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
85
81
  if (!isControlled) setInternal(e.target.value);
@@ -99,17 +95,18 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
99
95
  };
100
96
 
101
97
  // Inner input + (optional) prefix/suffix wrapper
98
+ // 当存在 addon 时,外层 addonWrapper 持有 border + rounded + focus-within ring,
99
+ // 内层 wrapper / input 完全去掉自身的 border / shadow / ring,避免出现
100
+ // "内部输入框单独一圈黑框" 的视觉。
102
101
  const innerInput = hasAffix ? (
103
102
  <div
104
103
  className={cn(
105
104
  'flex items-center gap-2 rounded-md border border-input bg-background px-3 shadow-sm transition-colors focus-within:ring-1 focus-within:ring-ring',
106
105
  h,
107
106
  disabled && 'cursor-not-allowed opacity-50',
108
- (addonBefore || addonAfter) && 'rounded-none border-x-0',
109
- addonBefore && !addonAfter && 'rounded-l-none border-l-0',
110
- addonAfter && !addonBefore && 'rounded-r-none border-r-0',
111
- !addonBefore && !addonAfter && '',
112
- className,
107
+ hasAddon &&
108
+ 'min-w-0 flex-1 rounded-none border-0 shadow-none transition-none focus-within:ring-0',
109
+ !hasAddon && className,
113
110
  )}
114
111
  >
115
112
  {prefix ? (
@@ -156,44 +153,51 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
156
153
  className={cn(
157
154
  'flex w-full rounded-md border border-input bg-background px-3 py-1 shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
158
155
  h,
159
- (addonBefore || addonAfter) && 'rounded-none',
160
- addonBefore && !addonAfter && 'rounded-l-none',
161
- addonAfter && !addonBefore && 'rounded-r-none',
162
- className,
156
+ hasAddon &&
157
+ 'min-w-0 flex-1 rounded-none border-0 shadow-none transition-none focus-visible:ring-0',
158
+ !hasAddon && className,
163
159
  )}
164
160
  {...props}
165
161
  />
166
162
  );
167
163
 
168
- // Wrap with addons if any
169
- const addonWrapper =
170
- addonBefore || addonAfter ? (
171
- <div className="flex">
172
- {addonBefore ? (
173
- <span
174
- className={cn(
175
- 'inline-flex shrink-0 items-center rounded-l-md border border-r-0 border-input bg-muted px-3 text-muted-foreground',
176
- h,
177
- )}
178
- >
179
- {addonBefore}
180
- </span>
181
- ) : null}
182
- {innerInput}
183
- {addonAfter ? (
184
- <span
185
- className={cn(
186
- 'inline-flex shrink-0 items-center rounded-r-md border border-l-0 border-input bg-muted px-3 text-muted-foreground',
187
- h,
188
- )}
189
- >
190
- {addonAfter}
191
- </span>
192
- ) : null}
193
- </div>
194
- ) : (
195
- innerInput
196
- );
164
+ // Wrap with addons if any.
165
+ // addonWrapper 是带 addon 时的统一外壳:持有 border + rounded + shadow +
166
+ // focus-within ring;addon 自身只用浅灰分隔边 (border-input),input 主体
167
+ // 不再持有任何边框 / ring,避免内部 "双重黑框" 视觉。
168
+ const addonWrapper = hasAddon ? (
169
+ <div
170
+ className={cn(
171
+ 'flex w-full overflow-hidden rounded-md border border-input bg-background shadow-sm transition-colors focus-within:ring-1 focus-within:ring-ring',
172
+ disabled && 'cursor-not-allowed opacity-50',
173
+ className,
174
+ )}
175
+ >
176
+ {addonBefore ? (
177
+ <span
178
+ className={cn(
179
+ 'inline-flex shrink-0 items-center border-r border-input bg-muted px-3 text-muted-foreground',
180
+ h,
181
+ )}
182
+ >
183
+ {addonBefore}
184
+ </span>
185
+ ) : null}
186
+ {innerInput}
187
+ {addonAfter ? (
188
+ <span
189
+ className={cn(
190
+ 'inline-flex shrink-0 items-center border-l border-input bg-muted px-3 text-muted-foreground',
191
+ h,
192
+ )}
193
+ >
194
+ {addonAfter}
195
+ </span>
196
+ ) : null}
197
+ </div>
198
+ ) : (
199
+ innerInput
200
+ );
197
201
 
198
202
  if (showCount && maxLength) {
199
203
  return (
@@ -4,10 +4,11 @@ name: InputGroup
4
4
  type: component
5
5
  category: form
6
6
  since: 0.1.0
7
- package: "@teamix-evo/ui"
7
+ package: '@teamix-evo/ui'
8
+ displayName: 输入框组
8
9
  ---
9
10
 
10
- # InputGroup
11
+ # InputGroup 输入框组
11
12
 
12
13
  输入框 + addon 统一容器 — shadcn 2025-10 新增。**等价 antd `Input` 的 `prefix` / `suffix` / `addonBefore` / `addonAfter` 集合**,但拆为更通用的复合插槽:`InputGroupAddon`(图标 / 文本 / 按钮)+ `InputGroupInput` / `InputGroupTextarea`(主体)。
13
14
 
@@ -24,24 +25,41 @@ package: "@teamix-evo/ui"
24
25
  - 仅需 textarea → `Textarea`
25
26
  - 多个按钮拼接 → `ButtonGroup`
26
27
 
28
+ ## Props
29
+
27
30
  <!-- auto:props:begin -->
28
- | 名称 | 类型 | 默认值 | 必填 | 说明 |
29
- | --- | --- | --- | --- | --- |
30
- | `disabled` | `boolean` | – | – | 整组禁用样式(子项请单独传 `disabled`,这里仅影响视觉上的 opacity)。 |
31
+
32
+ #### InputGroup
33
+
34
+ | 名称 | 类型 | 默认值 | 必填 | 说明 |
35
+ | ---------- | --------- | ------ | ---- | --------------------------------------------------------------------- |
36
+ | `disabled` | `boolean` | – | – | 整组禁用样式(子项请单独传 `disabled`,这里仅影响视觉上的 opacity)。 |
37
+
38
+ #### InputGroupAddon
39
+
40
+ | 名称 | 类型 | 默认值 | 必填 | 说明 |
41
+ | ---------- | ------------------------------ | ---------- | ---- | ---------------------------------------------------------------------------------------------------------------- |
42
+ | `position` | `'before' \| 'after'` | `"before"` | – | 位于输入框的哪一侧。 |
43
+ | `variant` | `'text' \| 'icon' \| 'button'` | `"text"` | – | `text` = 默认 muted 文本背景 / `icon` = 紧凑、透明背景(图标专用)/ `button` = 用于嵌入 `<Button>`(去内边距)。 |
44
+
31
45
  <!-- auto:props:end -->
32
46
 
47
+ ## 依赖
48
+
33
49
  <!-- auto:deps:begin -->
50
+
34
51
  ### 同库依赖
35
52
 
36
53
  > `teamix-evo ui add input-group` 时,以下 entry 会被自动连带安装(无需手动 add)。
37
54
 
38
- | Entry | 类型 | 描述 |
39
- | --- | --- | --- |
40
- | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
55
+ | Entry | 类型 | 描述 |
56
+ | ----- | ---- | -------------------------------------------------- |
57
+ | `cn` | util | Tailwind className 合并工具(clsx + tailwind-merge) |
41
58
 
42
59
  ### npm 依赖
43
60
 
44
61
  _无 — 本组件不依赖任何 npm 包。_
62
+
45
63
  <!-- auto:deps:end -->
46
64
 
47
65
  ## AI 生成纪律
@@ -16,7 +16,7 @@ const meta: Meta<typeof InputGroup> = {
16
16
  docs: {
17
17
  description: {
18
18
  component:
19
- '输入框 + addon 统一容器 — 拆为通用复合插槽:InputGroupAddon(图标 / 文本 / 按钮)+ InputGroupInput / InputGroupTextarea(主体)。shadcn 2025-10 新增,等价 antd Input 的 prefix / suffix / addonBefore / addonAfter 集合。视觉走 OpenTrek tokens,所有样式来自 `@teamix-evo/design`,无 mock。',
19
+ '输入框 + addon 统一容器 — 拆为通用复合插槽:InputGroupAddon(图标 / 文本 / 按钮)+ InputGroupInput / InputGroupTextarea(主体)。shadcn 2025-10 新增,等价 antd Input 的 prefix / suffix / addonBefore / addonAfter 集合。',
20
20
  },
21
21
  },
22
22
  },