@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.
- package/README.md +1 -1
- package/package.json +8 -4
- package/src/components/accordion/accordion.meta.md +10 -5
- package/src/components/accordion/accordion.stories.tsx +11 -6
- package/src/components/affix/affix.meta.md +19 -10
- package/src/components/affix/affix.stories.tsx +4 -2
- package/src/components/alert/alert.meta.md +19 -14
- package/src/components/alert/alert.stories.tsx +1 -1
- package/src/components/alert/alert.tsx +5 -5
- package/src/components/alert-dialog/alert-dialog.meta.md +23 -10
- package/src/components/alert-dialog/alert-dialog.stories.tsx +1 -1
- package/src/components/alert-dialog/alert-dialog.tsx +1 -1
- package/src/components/anchor/anchor.meta.md +20 -11
- package/src/components/anchor/anchor.stories.tsx +1 -1
- package/src/components/app/app.meta.md +19 -10
- package/src/components/app/app.stories.tsx +4 -2
- package/src/components/aspect-ratio/aspect-ratio.meta.md +10 -5
- package/src/components/aspect-ratio/aspect-ratio.stories.tsx +1 -1
- package/src/components/auto-complete/auto-complete.meta.md +25 -16
- package/src/components/auto-complete/auto-complete.stories.tsx +4 -2
- package/src/components/avatar/avatar.meta.md +23 -11
- package/src/components/avatar/avatar.stories.tsx +1 -1
- package/src/components/badge/badge.meta.md +26 -21
- package/src/components/badge/badge.tsx +7 -13
- package/src/components/breadcrumb/breadcrumb.meta.md +21 -10
- package/src/components/breadcrumb/breadcrumb.stories.tsx +8 -0
- package/src/components/button/button.meta.md +22 -17
- package/src/components/button/button.stories.tsx +1 -1
- package/src/components/button/demo/as-child.tsx +24 -0
- package/src/components/button/demo/basic.tsx +8 -0
- package/src/components/button/demo/block.tsx +16 -0
- package/src/components/button/demo/loading.tsx +19 -0
- package/src/components/button/demo/shapes.tsx +18 -0
- package/src/components/button/demo/sizes.tsx +19 -0
- package/src/components/button/demo/variants.tsx +19 -0
- package/src/components/button/demo/with-icon.tsx +20 -0
- package/src/components/button-group/button-group.meta.md +18 -9
- package/src/components/button-group/button-group.stories.tsx +5 -2
- package/src/components/calendar/calendar.meta.md +14 -9
- package/src/components/calendar/calendar.stories.tsx +1 -1
- package/src/components/calendar/calendar.tsx +1 -1
- package/src/components/card/card.meta.md +36 -11
- package/src/components/card/card.stories.tsx +8 -0
- package/src/components/carousel/carousel.meta.md +16 -11
- package/src/components/carousel/carousel.stories.tsx +10 -5
- package/src/components/cascader/cascader.meta.md +28 -19
- package/src/components/cascader/cascader.stories.tsx +9 -8
- package/src/components/cascader/cascader.tsx +2 -2
- package/src/components/checkbox/checkbox.meta.md +26 -8
- package/src/components/checkbox/checkbox.stories.tsx +1 -1
- package/src/components/collapsible/collapsible.meta.md +11 -4
- package/src/components/collapsible/collapsible.stories.tsx +8 -0
- package/src/components/color-picker/color-picker.meta.md +27 -18
- package/src/components/color-picker/color-picker.stories.tsx +1 -1
- package/src/components/color-picker/color-picker.tsx +1 -0
- package/src/components/combobox/combobox.meta.md +29 -20
- package/src/components/combobox/combobox.stories.tsx +1 -1
- package/src/components/combobox/combobox.tsx +3 -3
- package/src/components/command/command.meta.md +32 -12
- package/src/components/command/command.stories.tsx +1 -1
- package/src/components/command/command.tsx +1 -1
- package/src/components/context-menu/context-menu.meta.md +34 -11
- package/src/components/context-menu/context-menu.stories.tsx +8 -0
- package/src/components/context-menu/context-menu.tsx +2 -2
- package/src/components/data-table/data-table.meta.md +24 -19
- package/src/components/data-table/data-table.stories.tsx +12 -5
- package/src/components/date-picker/date-picker.meta.md +40 -20
- package/src/components/date-picker/date-picker.stories.tsx +1 -1
- package/src/components/descriptions/descriptions.meta.md +23 -14
- package/src/components/descriptions/descriptions.stories.tsx +1 -1
- package/src/components/dialog/dialog.meta.md +25 -12
- package/src/components/dialog/dialog.stories.tsx +1 -1
- package/src/components/dialog/dialog.tsx +1 -1
- package/src/components/drawer/drawer.meta.md +19 -8
- package/src/components/drawer/drawer.stories.tsx +1 -1
- package/src/components/drawer/drawer.tsx +1 -0
- package/src/components/dropdown-menu/dropdown-menu.meta.md +42 -14
- package/src/components/dropdown-menu/dropdown-menu.stories.tsx +8 -0
- package/src/components/dropdown-menu/dropdown-menu.tsx +2 -2
- package/src/components/empty/empty.meta.md +20 -11
- package/src/components/empty/empty.stories.tsx +1 -1
- package/src/components/field/field.meta.md +27 -10
- package/src/components/field/field.stories.tsx +6 -3
- package/src/components/flex/flex.meta.md +23 -14
- package/src/components/flex/flex.stories.tsx +46 -14
- package/src/components/float-button/float-button.meta.md +35 -11
- package/src/components/float-button/float-button.stories.tsx +4 -2
- package/src/components/float-button/float-button.tsx +1 -1
- package/src/components/form/form.meta.md +57 -14
- package/src/components/form/form.stories.tsx +1 -1
- package/src/components/grid/grid.meta.md +31 -6
- package/src/components/grid/grid.stories.tsx +4 -2
- package/src/components/hover-card/hover-card.meta.md +21 -9
- package/src/components/hover-card/hover-card.stories.tsx +6 -2
- package/src/components/image/image.meta.md +24 -15
- package/src/components/image/image.stories.tsx +1 -1
- package/src/components/image/image.tsx +4 -4
- package/src/components/input/demo/addon.tsx +15 -0
- package/src/components/input/demo/basic.tsx +12 -0
- package/src/components/input/demo/clearable.tsx +21 -0
- package/src/components/input/demo/show-count.tsx +18 -0
- package/src/components/input/demo/sizes.tsx +15 -0
- package/src/components/input/demo/with-prefix-suffix.tsx +19 -0
- package/src/components/input/input.meta.md +21 -16
- package/src/components/input/input.stories.tsx +1 -1
- package/src/components/input/input.tsx +51 -47
- package/src/components/input-group/input-group.meta.md +26 -8
- package/src/components/input-group/input-group.stories.tsx +1 -1
- package/src/components/input-group/input-group.tsx +4 -3
- package/src/components/input-number/input-number.meta.md +26 -17
- package/src/components/input-number/input-number.stories.tsx +14 -3
- package/src/components/input-number/input-number.tsx +20 -6
- package/src/components/input-otp/input-otp.meta.md +22 -9
- package/src/components/input-otp/input-otp.stories.tsx +1 -1
- package/src/components/item/item.meta.md +32 -9
- package/src/components/item/item.stories.tsx +5 -2
- package/src/components/kbd/kbd.meta.md +29 -8
- package/src/components/kbd/kbd.stories.tsx +1 -1
- package/src/components/kbd/kbd.tsx +2 -1
- package/src/components/label/label.meta.md +14 -9
- package/src/components/masonry/masonry.meta.md +18 -9
- package/src/components/masonry/masonry.stories.tsx +4 -2
- package/src/components/masonry/masonry.tsx +1 -0
- package/src/components/mentions/mentions.meta.md +28 -19
- package/src/components/mentions/mentions.stories.tsx +1 -1
- package/src/components/mentions/mentions.tsx +2 -1
- package/src/components/menubar/menubar.meta.md +36 -14
- package/src/components/menubar/menubar.stories.tsx +8 -0
- package/src/components/menubar/menubar.tsx +2 -2
- package/src/components/native-select/native-select.meta.md +17 -8
- package/src/components/native-select/native-select.stories.tsx +6 -3
- package/src/components/navigation-menu/navigation-menu.meta.md +25 -11
- package/src/components/navigation-menu/navigation-menu.stories.tsx +11 -11
- package/src/components/navigation-menu/navigation-menu.tsx +3 -2
- package/src/components/notification/notification.meta.md +14 -5
- package/src/components/notification/notification.stories.tsx +5 -3
- package/src/components/notification/notification.tsx +3 -3
- package/src/components/pagination/pagination.meta.md +59 -28
- package/src/components/pagination/pagination.stories.tsx +9 -3
- package/src/components/popconfirm/popconfirm.meta.md +30 -21
- package/src/components/popconfirm/popconfirm.stories.tsx +1 -2
- package/src/components/popconfirm/popconfirm.tsx +1 -1
- package/src/components/popover/popover.meta.md +13 -8
- package/src/components/popover/popover.stories.tsx +1 -1
- package/src/components/progress/progress.meta.md +28 -13
- package/src/components/progress/progress.stories.tsx +1 -1
- package/src/components/progress/progress.tsx +6 -6
- package/src/components/radio-group/radio-group.meta.md +17 -12
- package/src/components/radio-group/radio-group.stories.tsx +1 -1
- package/src/components/rate/rate.meta.md +25 -16
- package/src/components/rate/rate.stories.tsx +11 -3
- package/src/components/rate/rate.tsx +2 -2
- package/src/components/resizable/resizable.meta.md +19 -8
- package/src/components/resizable/resizable.stories.tsx +1 -1
- package/src/components/result/result.meta.md +21 -12
- package/src/components/result/result.stories.tsx +2 -6
- package/src/components/result/result.tsx +3 -3
- package/src/components/scroll-area/scroll-area.meta.md +10 -5
- package/src/components/scroll-area/scroll-area.stories.tsx +8 -0
- package/src/components/scroll-area/scroll-area.tsx +3 -3
- package/src/components/segmented/segmented.meta.md +19 -14
- package/src/components/segmented/segmented.stories.tsx +35 -6
- package/src/components/select/select.meta.md +22 -9
- package/src/components/select/select.stories.tsx +1 -1
- package/src/components/select/select.tsx +2 -2
- package/src/components/separator/separator.meta.md +16 -11
- package/src/components/separator/separator.stories.tsx +1 -1
- package/src/components/sheet/sheet.meta.md +22 -11
- package/src/components/sheet/sheet.stories.tsx +1 -1
- package/src/components/sidebar/sidebar.meta.md +47 -18
- package/src/components/sidebar/sidebar.stories.tsx +10 -5
- package/src/components/skeleton/skeleton.meta.md +33 -10
- package/src/components/skeleton/skeleton.stories.tsx +1 -1
- package/src/components/slider/slider.meta.md +12 -7
- package/src/components/slider/slider.stories.tsx +1 -1
- package/src/components/sonner/sonner.meta.md +8 -3
- package/src/components/sonner/sonner.stories.tsx +13 -8
- package/src/components/space/space.meta.md +22 -13
- package/src/components/space/space.stories.tsx +20 -6
- package/src/components/spinner/spinner.meta.md +23 -10
- package/src/components/spinner/spinner.stories.tsx +1 -1
- package/src/components/statistic/statistic.meta.md +37 -16
- package/src/components/statistic/statistic.stories.tsx +2 -6
- package/src/components/statistic/statistic.tsx +1 -1
- package/src/components/steps/steps.meta.md +21 -12
- package/src/components/steps/steps.stories.tsx +7 -2
- package/src/components/switch/switch.meta.md +16 -11
- package/src/components/switch/switch.stories.tsx +1 -1
- package/src/components/switch/switch.tsx +58 -36
- package/src/components/table/table.meta.md +24 -9
- package/src/components/table/table.stories.tsx +9 -4
- package/src/components/tabs/tabs.meta.md +14 -9
- package/src/components/tabs/tabs.stories.tsx +8 -0
- package/src/components/tag/tag.meta.md +39 -10
- package/src/components/tag/tag.stories.tsx +7 -2
- package/src/components/tag/tag.tsx +3 -3
- package/src/components/textarea/textarea.meta.md +17 -12
- package/src/components/textarea/textarea.stories.tsx +1 -1
- package/src/components/textarea/textarea.tsx +1 -1
- package/src/components/time-picker/time-picker.meta.md +38 -15
- package/src/components/time-picker/time-picker.stories.tsx +44 -6
- package/src/components/time-picker/time-picker.tsx +74 -10
- package/src/components/timeline/timeline.meta.md +20 -11
- package/src/components/timeline/timeline.stories.tsx +14 -4
- package/src/components/timeline/timeline.tsx +3 -2
- package/src/components/toggle/toggle.meta.md +14 -9
- package/src/components/toggle/toggle.stories.tsx +1 -1
- package/src/components/toggle-group/toggle-group.meta.md +16 -11
- package/src/components/toggle-group/toggle-group.stories.tsx +1 -1
- package/src/components/tooltip/tooltip.meta.md +18 -13
- package/src/components/tooltip/tooltip.stories.tsx +1 -1
- package/src/components/tour/tour.meta.md +25 -16
- package/src/components/tour/tour.stories.tsx +1 -1
- package/src/components/tour/tour.tsx +1 -1
- package/src/components/transfer/transfer.meta.md +29 -20
- package/src/components/transfer/transfer.stories.tsx +2 -6
- package/src/components/tree/tree.meta.md +36 -23
- package/src/components/tree/tree.stories.tsx +30 -11
- package/src/components/tree-select/tree-select.meta.md +37 -22
- package/src/components/tree-select/tree-select.stories.tsx +1 -1
- package/src/components/tree-select/tree-select.tsx +1 -1
- package/src/components/typography/typography.meta.md +41 -16
- package/src/components/typography/typography.stories.tsx +4 -8
- package/src/components/typography/typography.tsx +5 -3
- package/src/components/upload/upload.meta.md +31 -22
- package/src/components/upload/upload.stories.tsx +8 -14
- package/src/components/watermark/watermark.meta.md +26 -17
- package/src/components/watermark/watermark.stories.tsx +4 -2
- 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:
|
|
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`
|
|
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,
|
|
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"
|
|
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">
|
|
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 {
|
|
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
|
-
'悬浮卡片 —
|
|
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:
|
|
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
|
-
|
|
|
30
|
-
| `
|
|
31
|
-
| `
|
|
32
|
-
| `
|
|
33
|
-
| `
|
|
34
|
-
| `
|
|
35
|
-
| `
|
|
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`
|
|
46
|
-
| `dialog`
|
|
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
|
-
'图片 —
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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,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:
|
|
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
|
-
|
|
|
38
|
-
| `
|
|
39
|
-
| `
|
|
40
|
-
| `
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
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`
|
|
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
|
|
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
|
-
|
|
80
|
-
|
|
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
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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:
|
|
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
|
-
|
|
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`
|
|
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 统一容器 —
|
|
19
|
+
'输入框 + addon 统一容器 — 拆为通用复合插槽:InputGroupAddon(图标 / 文本 / 按钮)+ InputGroupInput / InputGroupTextarea(主体)。shadcn 2025-10 新增,等价 antd Input 的 prefix / suffix / addonBefore / addonAfter 集合。',
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
22
|
},
|