@teamix-evo/ui 0.7.1 → 0.7.2
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/manifest.json +16 -7
- package/package.json +4 -4
- package/src/_design-system/theme-tokens/stories.tsx +2 -2
- package/src/components/accordion/index.tsx +1 -1
- package/src/components/affix/meta.md +26 -0
- package/src/components/alert/index.tsx +2 -2
- package/src/components/alert-dialog/index.tsx +3 -3
- package/src/components/alert-dialog/meta.md +52 -0
- package/src/components/alert-dialog/stories.tsx +45 -48
- package/src/components/avatar/index.tsx +1 -1
- package/src/components/badge/index.tsx +2 -2
- package/src/components/badge/meta.md +48 -0
- package/src/components/button/index.tsx +2 -2
- package/src/components/button/meta.md +15 -0
- package/src/components/button/stories.tsx +1 -1
- package/src/components/calendar/index.tsx +2 -2
- package/src/components/card/index.tsx +1 -1
- package/src/components/carousel/index.tsx +2 -2
- package/src/components/carousel/meta.md +34 -2
- package/src/components/carousel/stories.tsx +2 -2
- package/src/components/cascader-select/index.tsx +2 -1
- package/src/components/cascader-select/meta.md +46 -0
- package/src/components/checkbox/meta.md +47 -0
- package/src/components/color-picker/index.tsx +3 -3
- package/src/components/color-picker/meta.md +80 -0
- package/src/components/combobox/index.tsx +2 -2
- package/src/components/combobox/meta.md +130 -0
- package/src/components/data-table/index.tsx +2 -2
- package/src/components/data-table/meta.md +419 -0
- package/src/components/date-picker/meta.md +91 -0
- package/src/components/descriptions/index.tsx +1 -1
- package/src/components/descriptions/meta.md +245 -0
- package/src/components/dialog/index.tsx +4 -4
- package/src/components/dialog/meta.md +47 -1
- package/src/components/dialog/stories.tsx +38 -41
- package/src/components/dropdown-menu/index.tsx +5 -5
- package/src/components/empty/index.tsx +2 -2
- package/src/components/field/index.tsx +4 -4
- package/src/components/filter-bar/index.tsx +6 -6
- package/src/components/filter-bar/meta.md +323 -0
- package/src/components/float-button/index.tsx +2 -2
- package/src/components/form/index.tsx +1 -1
- package/src/components/form/meta.md +119 -0
- package/src/components/hover-card/index.tsx +1 -1
- package/src/components/hover-card/meta.md +21 -0
- package/src/components/input/meta.md +16 -0
- package/src/components/input-group/index.tsx +1 -1
- package/src/components/input-group/meta.md +118 -0
- package/src/components/input-group/stories.tsx +6 -6
- package/src/components/input-ip/index.tsx +2 -2
- package/src/components/input-ip/meta.md +30 -0
- package/src/components/input-ip/stories.tsx +2 -2
- package/src/components/input-number/index.tsx +3 -2
- package/src/components/input-number/meta.md +67 -0
- package/src/components/input-number/stories.tsx +2 -2
- package/src/components/item/index.tsx +4 -4
- package/src/components/label/meta.md +8 -0
- package/src/components/mentions/meta.md +15 -0
- package/src/components/menubar/index.tsx +4 -4
- package/src/components/navigation-menu/index.tsx +4 -4
- package/src/components/page-header/index.tsx +1 -1
- package/src/components/page-header/meta.md +145 -0
- package/src/components/page-shell/index.tsx +2 -2
- package/src/components/pagination/index.tsx +1 -1
- package/src/components/pagination/meta.md +203 -0
- package/src/components/popconfirm/meta.md +45 -0
- package/src/components/popover/index.tsx +2 -2
- package/src/components/popover/meta.md +47 -0
- package/src/components/progress/index.tsx +1 -1
- package/src/components/progress/meta.md +36 -0
- package/src/components/progress/stories.tsx +1 -1
- package/src/components/radio-group/meta.md +69 -0
- package/src/components/rate/index.tsx +1 -1
- package/src/components/rate/meta.md +50 -0
- package/src/components/resizable/index.tsx +1 -1
- package/src/components/select/index.tsx +2 -2
- package/src/components/select/meta.md +20 -0
- package/src/components/separator/index.tsx +1 -1
- package/src/components/sheet/index.tsx +13 -14
- package/src/components/sheet/meta.md +124 -0
- package/src/components/sheet/stories.tsx +110 -119
- package/src/components/sidebar/index.tsx +5 -5
- package/src/components/sidebar/meta.md +383 -0
- package/src/components/skeleton/meta.md +13 -0
- package/src/components/slider/index.tsx +2 -2
- package/src/components/sonner/meta.md +86 -0
- package/src/components/spinner/meta.md +46 -0
- package/src/components/spinner/stories.tsx +2 -2
- package/src/components/steps/meta.md +20 -0
- package/src/components/steps/stories.tsx +1 -1
- package/src/components/switch/index.tsx +2 -2
- package/src/components/switch/meta.md +33 -0
- package/src/components/table/index.tsx +2 -2
- package/src/components/table/meta.md +11 -0
- package/src/components/tabs/index.tsx +7 -7
- package/src/components/tabs/meta.md +52 -0
- package/src/components/tag/index.tsx +8 -8
- package/src/components/tag/meta.md +194 -0
- package/src/components/textarea/index.tsx +1 -1
- package/src/components/textarea/meta.md +27 -0
- package/src/components/textarea/stories.tsx +1 -1
- package/src/components/time-picker/index.tsx +3 -3
- package/src/components/time-picker/meta.md +76 -0
- package/src/components/timeline/index.tsx +1 -0
- package/src/components/toggle/index.tsx +1 -1
- package/src/components/toggle-group/index.tsx +1 -1
- package/src/components/tooltip/index.tsx +1 -1
- package/src/components/tooltip/meta.md +23 -0
- package/src/components/transfer/index.tsx +2 -2
- package/src/components/transfer/meta.md +97 -0
- package/src/components/tree/index.tsx +245 -15
- package/src/components/tree/meta.md +151 -0
- package/src/components/tree-select/index.tsx +16 -2
- package/src/components/tree-select/meta.md +150 -0
- package/src/components/typography/index.tsx +3 -3
- package/src/components/upload/index.tsx +3 -3
- package/src/components/upload/meta.md +82 -0
- package/src/components/tree/utils.ts +0 -269
- package/src/examples/built-in-assets/stories.tsx +0 -572
- package/src/examples/evaluators/stories.tsx +0 -502
|
@@ -45,6 +45,81 @@ DescriptionsContent 自由组合,label 与 content 都是 ReactNode 槽位,
|
|
|
45
45
|
|
|
46
46
|
## 示例
|
|
47
47
|
|
|
48
|
+
### Vertical
|
|
49
|
+
|
|
50
|
+
垂直布局:label 与 content 上下堆叠。
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
<Descriptions {...args}>
|
|
54
|
+
<DescriptionsItem>
|
|
55
|
+
<DescriptionsLabel>CPU</DescriptionsLabel>
|
|
56
|
+
<DescriptionsContent>8 核</DescriptionsContent>
|
|
57
|
+
</DescriptionsItem>
|
|
58
|
+
<DescriptionsItem>
|
|
59
|
+
<DescriptionsLabel>内存</DescriptionsLabel>
|
|
60
|
+
<DescriptionsContent>16 GB</DescriptionsContent>
|
|
61
|
+
</DescriptionsItem>
|
|
62
|
+
<DescriptionsItem>
|
|
63
|
+
<DescriptionsLabel>硬盘</DescriptionsLabel>
|
|
64
|
+
<DescriptionsContent>512 GB SSD</DescriptionsContent>
|
|
65
|
+
</DescriptionsItem>
|
|
66
|
+
<DescriptionsItem>
|
|
67
|
+
<DescriptionsLabel>网络</DescriptionsLabel>
|
|
68
|
+
<DescriptionsContent>千兆</DescriptionsContent>
|
|
69
|
+
</DescriptionsItem>
|
|
70
|
+
</Descriptions>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Bordered
|
|
74
|
+
|
|
75
|
+
带边框矩阵:经典 antd 风格。
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
<Descriptions {...args}>
|
|
79
|
+
<DescriptionsItem>
|
|
80
|
+
<DescriptionsLabel>订单号</DescriptionsLabel>
|
|
81
|
+
<DescriptionsContent>ORD-20260601-001</DescriptionsContent>
|
|
82
|
+
</DescriptionsItem>
|
|
83
|
+
<DescriptionsItem>
|
|
84
|
+
<DescriptionsLabel>金额</DescriptionsLabel>
|
|
85
|
+
<DescriptionsContent>¥1,299.00</DescriptionsContent>
|
|
86
|
+
</DescriptionsItem>
|
|
87
|
+
<DescriptionsItem>
|
|
88
|
+
<DescriptionsLabel>收货人</DescriptionsLabel>
|
|
89
|
+
<DescriptionsContent>李四</DescriptionsContent>
|
|
90
|
+
</DescriptionsItem>
|
|
91
|
+
<DescriptionsItem>
|
|
92
|
+
<DescriptionsLabel>联系电话</DescriptionsLabel>
|
|
93
|
+
<DescriptionsContent>138****0001</DescriptionsContent>
|
|
94
|
+
</DescriptionsItem>
|
|
95
|
+
<DescriptionsItem span={2}>
|
|
96
|
+
<DescriptionsLabel>收货地址</DescriptionsLabel>
|
|
97
|
+
<DescriptionsContent>杭州市余杭区文一西路</DescriptionsContent>
|
|
98
|
+
</DescriptionsItem>
|
|
99
|
+
</Descriptions>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### BorderedVertical
|
|
103
|
+
|
|
104
|
+
带边框 + 垂直布局:label 在上 content 在下。
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
<Descriptions {...args}>
|
|
108
|
+
<DescriptionsItem>
|
|
109
|
+
<DescriptionsLabel>实例 ID</DescriptionsLabel>
|
|
110
|
+
<DescriptionsContent>i-2zee0xxxxxxx</DescriptionsContent>
|
|
111
|
+
</DescriptionsItem>
|
|
112
|
+
<DescriptionsItem>
|
|
113
|
+
<DescriptionsLabel>可用区</DescriptionsLabel>
|
|
114
|
+
<DescriptionsContent>cn-hangzhou-h</DescriptionsContent>
|
|
115
|
+
</DescriptionsItem>
|
|
116
|
+
<DescriptionsItem>
|
|
117
|
+
<DescriptionsLabel>镜像</DescriptionsLabel>
|
|
118
|
+
<DescriptionsContent>AnolisOS 8.6</DescriptionsContent>
|
|
119
|
+
</DescriptionsItem>
|
|
120
|
+
</Descriptions>
|
|
121
|
+
```
|
|
122
|
+
|
|
48
123
|
### Sizes
|
|
49
124
|
|
|
50
125
|
不同尺寸:sm / default 对比。
|
|
@@ -102,3 +177,173 @@ DescriptionsContent 自由组合,label 与 content 都是 ReactNode 槽位,
|
|
|
102
177
|
</Descriptions>
|
|
103
178
|
</div>
|
|
104
179
|
```
|
|
180
|
+
|
|
181
|
+
### Responsive
|
|
182
|
+
|
|
183
|
+
响应式列数:viewport 断点驱动。在 Storybook viewport 切换查看。
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
<Descriptions {...args}>
|
|
187
|
+
<BaseItems />
|
|
188
|
+
</Descriptions>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### WithSpan
|
|
192
|
+
|
|
193
|
+
跨列:通过 span 合并多列。
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
<Descriptions {...args}>
|
|
197
|
+
<DescriptionsItem>
|
|
198
|
+
<DescriptionsLabel>名称</DescriptionsLabel>
|
|
199
|
+
<DescriptionsContent>Teamix Evo</DescriptionsContent>
|
|
200
|
+
</DescriptionsItem>
|
|
201
|
+
<DescriptionsItem>
|
|
202
|
+
<DescriptionsLabel>版本</DescriptionsLabel>
|
|
203
|
+
<DescriptionsContent>v0.8</DescriptionsContent>
|
|
204
|
+
</DescriptionsItem>
|
|
205
|
+
<DescriptionsItem>
|
|
206
|
+
<DescriptionsLabel>语言</DescriptionsLabel>
|
|
207
|
+
<DescriptionsContent>TypeScript</DescriptionsContent>
|
|
208
|
+
</DescriptionsItem>
|
|
209
|
+
<DescriptionsItem span={3}>
|
|
210
|
+
<DescriptionsLabel>描述</DescriptionsLabel>
|
|
211
|
+
<DescriptionsContent>
|
|
212
|
+
面向 AI Coding 的研发套件,覆盖设计、组件、技能。
|
|
213
|
+
</DescriptionsContent>
|
|
214
|
+
</DescriptionsItem>
|
|
215
|
+
</Descriptions>
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### WithTooltip
|
|
219
|
+
|
|
220
|
+
label 旁带 Tooltip 图标:在 `<DescriptionsLabel>` 子树内直接拼装 `<Tooltip>`。 高频使用建议在自己工程抽一个 `<HelpLabel label tip />` helper(5 行即可)。
|
|
221
|
+
|
|
222
|
+
```tsx
|
|
223
|
+
<Descriptions {...args}>
|
|
224
|
+
<DescriptionsItem>
|
|
225
|
+
<DescriptionsLabel>
|
|
226
|
+
实例 ID
|
|
227
|
+
<Tooltip>
|
|
228
|
+
<TooltipTrigger asChild>
|
|
229
|
+
<button
|
|
230
|
+
type="button"
|
|
231
|
+
aria-label="字段说明"
|
|
232
|
+
className="inline-flex cursor-pointer items-center text-muted-foreground transition-colors hover:text-foreground"
|
|
233
|
+
>
|
|
234
|
+
<InfoIcon className="size-3.5" />
|
|
235
|
+
</button>
|
|
236
|
+
</TooltipTrigger>
|
|
237
|
+
<TooltipContent>云资源唯一标识</TooltipContent>
|
|
238
|
+
</Tooltip>
|
|
239
|
+
</DescriptionsLabel>
|
|
240
|
+
<DescriptionsContent>i-2zee0xxx</DescriptionsContent>
|
|
241
|
+
</DescriptionsItem>
|
|
242
|
+
<DescriptionsItem>
|
|
243
|
+
<DescriptionsLabel>
|
|
244
|
+
收藏
|
|
245
|
+
<Tooltip>
|
|
246
|
+
<TooltipTrigger asChild>
|
|
247
|
+
<button
|
|
248
|
+
type="button"
|
|
249
|
+
aria-label="字段说明"
|
|
250
|
+
className="inline-flex cursor-pointer items-center text-muted-foreground transition-colors hover:text-foreground"
|
|
251
|
+
>
|
|
252
|
+
<StarIcon className="size-3.5" />
|
|
253
|
+
</button>
|
|
254
|
+
</TooltipTrigger>
|
|
255
|
+
<TooltipContent>收藏后可在工作台直接进入</TooltipContent>
|
|
256
|
+
</Tooltip>
|
|
257
|
+
</DescriptionsLabel>
|
|
258
|
+
<DescriptionsContent>已收藏</DescriptionsContent>
|
|
259
|
+
</DescriptionsItem>
|
|
260
|
+
</Descriptions>
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### WithRichContent
|
|
264
|
+
|
|
265
|
+
content 内部混排其他组件(Tag / 行内按钮等)—— 全部直接塞进 `<DescriptionsContent>`。
|
|
266
|
+
|
|
267
|
+
```tsx
|
|
268
|
+
<Descriptions {...args}>
|
|
269
|
+
<DescriptionsItem>
|
|
270
|
+
<DescriptionsLabel>实例 ID</DescriptionsLabel>
|
|
271
|
+
<DescriptionsContent>
|
|
272
|
+
<span className="inline-flex items-center gap-2">
|
|
273
|
+
i-2zee0xxxxxxx
|
|
274
|
+
<Button variant="ghost" size="sm" aria-label="复制">
|
|
275
|
+
<CopyIcon />
|
|
276
|
+
</Button>
|
|
277
|
+
</span>
|
|
278
|
+
</DescriptionsContent>
|
|
279
|
+
</DescriptionsItem>
|
|
280
|
+
<DescriptionsItem>
|
|
281
|
+
<DescriptionsLabel>状态</DescriptionsLabel>
|
|
282
|
+
<DescriptionsContent>
|
|
283
|
+
<Tag color="success">运行中</Tag>
|
|
284
|
+
</DescriptionsContent>
|
|
285
|
+
</DescriptionsItem>
|
|
286
|
+
</Descriptions>
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### ControlAlignment
|
|
290
|
+
|
|
291
|
+
控件高度对齐:horizontal 非 bordered 模式下label 默认 `min-h-6`(24px)与 sm Button / Tag 同高,顶对齐 = 视觉基线对齐。若 content 是 h-8 / h-10 等更高控件, 用 `<DescriptionsItem align="center">` 让 label 与控件整体居中。
|
|
292
|
+
|
|
293
|
+
```tsx
|
|
294
|
+
<Descriptions {...args}>
|
|
295
|
+
{/* sm 控件 24px:label min-h-6 同高,默认 align="start" 即可对齐 */}
|
|
296
|
+
<DescriptionsItem>
|
|
297
|
+
<DescriptionsLabel>状态</DescriptionsLabel>
|
|
298
|
+
<DescriptionsContent>
|
|
299
|
+
<Tag color="success">运行中</Tag>
|
|
300
|
+
</DescriptionsContent>
|
|
301
|
+
</DescriptionsItem>
|
|
302
|
+
<DescriptionsItem>
|
|
303
|
+
<DescriptionsLabel>实例 ID</DescriptionsLabel>
|
|
304
|
+
<DescriptionsContent>
|
|
305
|
+
<span className="inline-flex items-center gap-2">
|
|
306
|
+
i-2zee0xxxxxxx
|
|
307
|
+
<Button variant="ghost" size="sm" aria-label="复制">
|
|
308
|
+
<CopyIcon />
|
|
309
|
+
</Button>
|
|
310
|
+
</span>
|
|
311
|
+
</DescriptionsContent>
|
|
312
|
+
</DescriptionsItem>
|
|
313
|
+
{/* default 控件 32px:需 align="center" 让 label 与控件整体居中 */}
|
|
314
|
+
<DescriptionsItem align="center">
|
|
315
|
+
<DescriptionsLabel>操作</DescriptionsLabel>
|
|
316
|
+
<DescriptionsContent>
|
|
317
|
+
<Button variant="outline">重启实例</Button>
|
|
318
|
+
</DescriptionsContent>
|
|
319
|
+
</DescriptionsItem>
|
|
320
|
+
<DescriptionsItem align="center">
|
|
321
|
+
<DescriptionsLabel>变更</DescriptionsLabel>
|
|
322
|
+
<DescriptionsContent>
|
|
323
|
+
<Button variant="ghost">
|
|
324
|
+
<RefreshCwIcon /> 同步配置
|
|
325
|
+
</Button>
|
|
326
|
+
</DescriptionsContent>
|
|
327
|
+
</DescriptionsItem>
|
|
328
|
+
</Descriptions>
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### WithHeaderExtra
|
|
332
|
+
|
|
333
|
+
顶部 extra 槽:放刷新等操作。
|
|
334
|
+
|
|
335
|
+
```tsx
|
|
336
|
+
<Descriptions {...args}>
|
|
337
|
+
<BaseItems />
|
|
338
|
+
</Descriptions>
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Collapsible
|
|
342
|
+
|
|
343
|
+
折叠:头部点击展开收起。
|
|
344
|
+
|
|
345
|
+
```tsx
|
|
346
|
+
<Descriptions {...args}>
|
|
347
|
+
<BaseItems />
|
|
348
|
+
</Descriptions>
|
|
349
|
+
```
|
|
@@ -74,7 +74,7 @@ function DialogOverlay({
|
|
|
74
74
|
<DialogPrimitive.Overlay
|
|
75
75
|
data-slot="dialog-overlay"
|
|
76
76
|
className={cn(
|
|
77
|
-
'fixed inset-0 isolate z-50 bg-black/10 duration-100
|
|
77
|
+
'fixed inset-0 isolate z-50 bg-black/10 duration-100 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0 supports-backdrop-filter:backdrop-blur-xs',
|
|
78
78
|
className,
|
|
79
79
|
)}
|
|
80
80
|
{...props}
|
|
@@ -118,7 +118,7 @@ function DialogContent({
|
|
|
118
118
|
}}
|
|
119
119
|
className={cn(
|
|
120
120
|
// eslint-disable-next-line teamix-evo/no-arbitrary-tw-value -- mobile viewport needs calc(100% - 2rem) for safe inset; box-shadow drives via component-level token --dialog-shadow per ADR 0026.
|
|
121
|
-
'fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-
|
|
121
|
+
'fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-1/2 rounded-md bg-popover text-sm text-popover-foreground shadow-[var(--dialog-shadow,0px_6px_24px_0px_rgba(0,0,0,0.1))] duration-100 outline-none data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[size=lg]:sm:max-w-3xl data-[size=md]:sm:max-w-xl data-[size=sm]:sm:max-w-md data-[size=xl]:sm:max-w-6xl',
|
|
122
122
|
className,
|
|
123
123
|
)}
|
|
124
124
|
{...props}
|
|
@@ -150,7 +150,7 @@ function DialogHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
|
|
150
150
|
<div
|
|
151
151
|
data-slot="dialog-header"
|
|
152
152
|
className={cn(
|
|
153
|
-
'flex flex-col gap-1.5 border-b border-border
|
|
153
|
+
'flex flex-col gap-1.5 border-b border-border py-3 pr-14 pl-5 has-data-[slot=dialog-header-extra]:grid has-data-[slot=dialog-header-extra]:grid-cols-[1fr_auto] has-data-[slot=dialog-header-extra]:items-start has-data-[slot=dialog-header-extra]:gap-x-3',
|
|
154
154
|
className,
|
|
155
155
|
)}
|
|
156
156
|
{...props}
|
|
@@ -207,7 +207,7 @@ function DialogFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
|
|
207
207
|
<div
|
|
208
208
|
data-slot="dialog-footer"
|
|
209
209
|
className={cn(
|
|
210
|
-
|
|
210
|
+
|
|
211
211
|
'flex flex-col-reverse gap-2 border-t border-footer-separator px-5 py-4 sm:flex-row sm:justify-end',
|
|
212
212
|
className,
|
|
213
213
|
)}
|
|
@@ -165,6 +165,52 @@
|
|
|
165
165
|
</Dialog>
|
|
166
166
|
```
|
|
167
167
|
|
|
168
|
+
### AsyncSubmit
|
|
169
|
+
|
|
170
|
+
异步提交 — onSubmit 返回 Promise,按钮 loading 期间禁止关闭。
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
const [open, setOpen] = React.useState(false);
|
|
174
|
+
const [loading, setLoading] = React.useState(false);
|
|
175
|
+
const onConfirm = async () => {
|
|
176
|
+
setLoading(true);
|
|
177
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
178
|
+
setLoading(false);
|
|
179
|
+
setOpen(false);
|
|
180
|
+
};
|
|
181
|
+
return (
|
|
182
|
+
<Dialog
|
|
183
|
+
open={open}
|
|
184
|
+
onOpenChange={(next) => {
|
|
185
|
+
if (loading) return;
|
|
186
|
+
setOpen(next);
|
|
187
|
+
}}
|
|
188
|
+
>
|
|
189
|
+
<DialogTrigger asChild>
|
|
190
|
+
<Button>打开</Button>
|
|
191
|
+
</DialogTrigger>
|
|
192
|
+
<DialogContent
|
|
193
|
+
onPointerDownOutside={(e) => loading && e.preventDefault()}
|
|
194
|
+
onEscapeKeyDown={(e) => loading && e.preventDefault()}
|
|
195
|
+
>
|
|
196
|
+
<DialogHeader>
|
|
197
|
+
<DialogTitle>确认删除?</DialogTitle>
|
|
198
|
+
</DialogHeader>
|
|
199
|
+
<DialogFooter>
|
|
200
|
+
<DialogClose asChild>
|
|
201
|
+
<Button variant="outline" disabled={loading}>
|
|
202
|
+
取消
|
|
203
|
+
</Button>
|
|
204
|
+
</DialogClose>
|
|
205
|
+
<Button loading={loading} onClick={onConfirm}>
|
|
206
|
+
确认
|
|
207
|
+
</Button>
|
|
208
|
+
</DialogFooter>
|
|
209
|
+
</DialogContent>
|
|
210
|
+
</Dialog>
|
|
211
|
+
);
|
|
212
|
+
```
|
|
213
|
+
|
|
168
214
|
### NoCloseButton
|
|
169
215
|
|
|
170
216
|
隐藏关闭按钮 — 强制通过底部操作关闭,常用于流程类强引导。
|
|
@@ -196,7 +242,7 @@
|
|
|
196
242
|
<DialogTrigger asChild>
|
|
197
243
|
<Button>全屏打开</Button>
|
|
198
244
|
</DialogTrigger>
|
|
199
|
-
<DialogContent className="inset-0 top-0 left-0 max-w-none
|
|
245
|
+
<DialogContent className="inset-0 top-0 left-0 max-w-none grid-rows-[auto_1fr_auto] rounded-none data-[state=open]:zoom-in-100 data-[state=open]:slide-in-from-bottom-2 data-[state=closed]:zoom-out-100 data-[state=closed]:slide-out-to-bottom-2 sm:max-w-none -translate-0">
|
|
200
246
|
<DialogHeader>
|
|
201
247
|
<DialogTitle>全屏编辑</DialogTitle>
|
|
202
248
|
</DialogHeader>
|
|
@@ -206,48 +206,45 @@ export const LargeContent: Story = {
|
|
|
206
206
|
export const AsyncSubmit: Story = {
|
|
207
207
|
name: '异步提交',
|
|
208
208
|
render: () => {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
209
|
+
const [open, setOpen] = React.useState(false);
|
|
210
|
+
const [loading, setLoading] = React.useState(false);
|
|
211
|
+
const onConfirm = async () => {
|
|
212
|
+
setLoading(true);
|
|
213
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
214
|
+
setLoading(false);
|
|
215
|
+
setOpen(false);
|
|
216
|
+
};
|
|
217
|
+
return (
|
|
218
|
+
<Dialog
|
|
219
|
+
open={open}
|
|
220
|
+
onOpenChange={(next) => {
|
|
221
|
+
if (loading) return;
|
|
222
|
+
setOpen(next);
|
|
223
|
+
}}
|
|
224
|
+
>
|
|
225
|
+
<DialogTrigger asChild>
|
|
226
|
+
<Button>打开</Button>
|
|
227
|
+
</DialogTrigger>
|
|
228
|
+
<DialogContent
|
|
229
|
+
onPointerDownOutside={(e) => loading && e.preventDefault()}
|
|
230
|
+
onEscapeKeyDown={(e) => loading && e.preventDefault()}
|
|
225
231
|
>
|
|
226
|
-
<
|
|
227
|
-
<
|
|
228
|
-
</
|
|
229
|
-
<
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
<DialogHeader>
|
|
234
|
-
<DialogTitle>确认删除?</DialogTitle>
|
|
235
|
-
</DialogHeader>
|
|
236
|
-
<DialogFooter>
|
|
237
|
-
<DialogClose asChild>
|
|
238
|
-
<Button variant="outline" disabled={loading}>
|
|
239
|
-
取消
|
|
240
|
-
</Button>
|
|
241
|
-
</DialogClose>
|
|
242
|
-
<Button loading={loading} onClick={onConfirm}>
|
|
243
|
-
确认
|
|
232
|
+
<DialogHeader>
|
|
233
|
+
<DialogTitle>确认删除?</DialogTitle>
|
|
234
|
+
</DialogHeader>
|
|
235
|
+
<DialogFooter>
|
|
236
|
+
<DialogClose asChild>
|
|
237
|
+
<Button variant="outline" disabled={loading}>
|
|
238
|
+
取消
|
|
244
239
|
</Button>
|
|
245
|
-
</
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
240
|
+
</DialogClose>
|
|
241
|
+
<Button loading={loading} onClick={onConfirm}>
|
|
242
|
+
确认
|
|
243
|
+
</Button>
|
|
244
|
+
</DialogFooter>
|
|
245
|
+
</DialogContent>
|
|
246
|
+
</Dialog>
|
|
247
|
+
);
|
|
251
248
|
},
|
|
252
249
|
};
|
|
253
250
|
|
|
@@ -281,7 +278,7 @@ export const Fullscreen: Story = {
|
|
|
281
278
|
<DialogTrigger asChild>
|
|
282
279
|
<Button>全屏打开</Button>
|
|
283
280
|
</DialogTrigger>
|
|
284
|
-
<DialogContent className="inset-0 top-0 left-0 max-w-none
|
|
281
|
+
<DialogContent className="inset-0 top-0 left-0 max-w-none grid-rows-[auto_1fr_auto] rounded-none data-[state=open]:zoom-in-100 data-[state=open]:slide-in-from-bottom-2 data-[state=closed]:zoom-out-100 data-[state=closed]:slide-out-to-bottom-2 sm:max-w-none -translate-0">
|
|
285
282
|
<DialogHeader>
|
|
286
283
|
<DialogTitle>全屏编辑</DialogTitle>
|
|
287
284
|
</DialogHeader>
|
|
@@ -72,7 +72,7 @@ function DropdownMenuContent({
|
|
|
72
72
|
sideOffset={sideOffset}
|
|
73
73
|
align={align}
|
|
74
74
|
className={cn(
|
|
75
|
-
'z-50 max-h-(--radix-dropdown-menu-content-available-height) w-(--radix-dropdown-menu-trigger-width) min-w-32 origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:
|
|
75
|
+
'z-50 max-h-(--radix-dropdown-menu-content-available-height) w-(--radix-dropdown-menu-trigger-width) min-w-32 origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:overflow-hidden data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
|
|
76
76
|
className,
|
|
77
77
|
)}
|
|
78
78
|
{...props}
|
|
@@ -104,7 +104,7 @@ function DropdownMenuItem({
|
|
|
104
104
|
data-inset={inset}
|
|
105
105
|
data-variant={variant}
|
|
106
106
|
className={cn(
|
|
107
|
-
"group/dropdown-menu-item relative flex h-8 cursor-pointer items-center gap-1.5 rounded-md px-1.5 py-1 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive
|
|
107
|
+
"group/dropdown-menu-item relative flex h-8 cursor-pointer items-center gap-1.5 rounded-md px-1.5 py-1 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive",
|
|
108
108
|
className,
|
|
109
109
|
)}
|
|
110
110
|
{...props}
|
|
@@ -126,7 +126,7 @@ function DropdownMenuCheckboxItem({
|
|
|
126
126
|
data-slot="dropdown-menu-checkbox-item"
|
|
127
127
|
data-inset={inset}
|
|
128
128
|
className={cn(
|
|
129
|
-
"relative flex h-8 cursor-pointer items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-
|
|
129
|
+
"relative flex h-8 cursor-pointer items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
130
130
|
className,
|
|
131
131
|
)}
|
|
132
132
|
checked={checked}
|
|
@@ -169,7 +169,7 @@ function DropdownMenuRadioItem({
|
|
|
169
169
|
data-slot="dropdown-menu-radio-item"
|
|
170
170
|
data-inset={inset}
|
|
171
171
|
className={cn(
|
|
172
|
-
"relative flex h-8 cursor-pointer items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-
|
|
172
|
+
"relative flex h-8 cursor-pointer items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
173
173
|
className,
|
|
174
174
|
)}
|
|
175
175
|
{...props}
|
|
@@ -274,7 +274,7 @@ function DropdownMenuSubContent({
|
|
|
274
274
|
<DropdownMenuPrimitive.SubContent
|
|
275
275
|
data-slot="dropdown-menu-sub-content"
|
|
276
276
|
className={cn(
|
|
277
|
-
'z-50 min-w-24 origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=
|
|
277
|
+
'z-50 min-w-24 origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
|
|
278
278
|
className,
|
|
279
279
|
)}
|
|
280
280
|
{...props}
|
|
@@ -43,7 +43,7 @@ const emptyVariants = cva(
|
|
|
43
43
|
variants: {
|
|
44
44
|
layout: {
|
|
45
45
|
vertical: 'flex-col text-center',
|
|
46
|
-
horizontal: 'flex-row text-left
|
|
46
|
+
horizontal: 'min-h-80 flex-row text-left',
|
|
47
47
|
},
|
|
48
48
|
size: {
|
|
49
49
|
sm: 'p-4',
|
|
@@ -386,7 +386,7 @@ function EmptyTitle({ className, ...props }: React.ComponentProps<'div'>) {
|
|
|
386
386
|
<div
|
|
387
387
|
data-slot="empty-title"
|
|
388
388
|
className={cn(
|
|
389
|
-
'font-medium tracking-tight text-foreground group-data-[
|
|
389
|
+
'font-medium tracking-tight text-foreground group-data-[layout=horizontal]/empty:text-muted-foreground group-data-[size=default]/empty:text-base group-data-[size=lg]/empty:text-2xl group-data-[size=lg]/empty:leading-9 group-data-[size=sm]/empty:text-sm',
|
|
390
390
|
className,
|
|
391
391
|
)}
|
|
392
392
|
{...props}
|
|
@@ -158,7 +158,7 @@ function FieldGroup({ className, ...props }: React.ComponentProps<'div'>) {
|
|
|
158
158
|
<div
|
|
159
159
|
data-slot="field-group"
|
|
160
160
|
className={cn(
|
|
161
|
-
'group/field-group @container/field-group flex w-full flex-col gap-5
|
|
161
|
+
'group/field-group @container/field-group flex w-full flex-col gap-5 data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4 [&>[data-slot=field-set]+[data-slot=field-set]]:mt-3',
|
|
162
162
|
className,
|
|
163
163
|
)}
|
|
164
164
|
{...props}
|
|
@@ -173,7 +173,7 @@ const fieldVariants = cva(
|
|
|
173
173
|
orientation: {
|
|
174
174
|
vertical: 'flex-col gap-1 *:w-full [&>.sr-only]:w-auto',
|
|
175
175
|
responsive:
|
|
176
|
-
'flex-col gap-1 *:w-full @[30rem]/field-group:grid @[30rem]/field-group:grid-cols-12 @[30rem]/field-group:
|
|
176
|
+
'flex-col gap-1 *:w-full @[30rem]/field-group:grid @[30rem]/field-group:grid-cols-12 @[30rem]/field-group:items-start @[30rem]/field-group:gap-x-4 @[30rem]/field-group:gap-y-1 [&>.sr-only]:w-auto @[30rem]/field-group:[&>:not([data-slot=field-label])]:col-span-8 @[30rem]/field-group:[&>:not([data-slot=field-label])]:col-start-3 @[30rem]/field-group:[&>[data-slot=field-label]]:col-span-2',
|
|
177
177
|
inset: 'flex-col gap-1',
|
|
178
178
|
},
|
|
179
179
|
},
|
|
@@ -243,7 +243,7 @@ function FieldLabel({
|
|
|
243
243
|
className={cn(
|
|
244
244
|
'group/field-label peer/field-label flex w-fit gap-1 leading-8 group-data-[disabled=true]/field:opacity-50 has-data-[state=checked]:border-primary/30 has-data-[state=checked]:bg-primary/5 has-[>[data-slot=field]]:rounded-lg has-[>[data-slot=field]]:border *:data-[slot=field]:p-2.5',
|
|
245
245
|
'has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col',
|
|
246
|
-
'group-data-[orientation=inset]/field:h-full group-data-[orientation=inset]/field:shrink-0 group-data-[orientation=inset]/field:items-center group-data-[orientation=inset]/field:
|
|
246
|
+
'group-data-[orientation=inset]/field:h-full group-data-[orientation=inset]/field:shrink-0 group-data-[orientation=inset]/field:items-center group-data-[orientation=inset]/field:pr-2 group-data-[orientation=inset]/field:pl-3 group-data-[orientation=inset]/field:leading-normal group-data-[orientation=inset]/field:text-muted-foreground',
|
|
247
247
|
className,
|
|
248
248
|
)}
|
|
249
249
|
{...props}
|
|
@@ -351,7 +351,7 @@ function FieldError({
|
|
|
351
351
|
<div
|
|
352
352
|
role="alert"
|
|
353
353
|
data-slot="field-error"
|
|
354
|
-
className={cn('text-xs font-normal text-destructive
|
|
354
|
+
className={cn('-mt-1 text-xs font-normal text-destructive', className)}
|
|
355
355
|
{...props}
|
|
356
356
|
>
|
|
357
357
|
{content}
|
|
@@ -470,7 +470,7 @@ function FilterBarSearchKey({ options, className }: FilterBarSearchKeyProps) {
|
|
|
470
470
|
<SelectTrigger
|
|
471
471
|
size="sm"
|
|
472
472
|
className={cn(
|
|
473
|
-
'h-full rounded-none border-0 border-r border-r-input bg-transparent shadow-none focus-visible:ring-0
|
|
473
|
+
'h-full rounded-none border-0 border-r border-r-input bg-transparent shadow-none focus:border-r-input focus-visible:ring-0 data-[state=open]:border-r-input',
|
|
474
474
|
className,
|
|
475
475
|
)}
|
|
476
476
|
>
|
|
@@ -624,12 +624,12 @@ function FilterBarContent({
|
|
|
624
624
|
>
|
|
625
625
|
<div
|
|
626
626
|
className={cn(
|
|
627
|
-
'grid gap-x-4 gap-y-3 rounded-md bg-muted
|
|
628
|
-
'[&_[data-slot=input]]:bg-card [&_[data-slot=
|
|
627
|
+
'grid gap-x-4 gap-y-3 rounded-md bg-muted p-4',
|
|
628
|
+
'[&_[data-slot=input-number]]:bg-card [&_[data-slot=input]]:bg-card [&_[data-slot=select-trigger]]:bg-card [&_[data-slot=textarea]]:bg-card',
|
|
629
629
|
// 面板内表单控件统一全宽(仅作用于 FilterBarContent 子树)
|
|
630
|
-
'[&_[data-slot=input]]:w-full [&_[data-slot=input-
|
|
631
|
-
'[&_[data-slot=select-trigger]]:w-full [&_[data-slot=
|
|
632
|
-
'[&_[data-slot=date-picker]]:w-full [&_[data-slot=date-range-picker]]:w-full [&_[data-slot=
|
|
630
|
+
'[&_[data-slot=input-group]]:w-full [&_[data-slot=input-ip]]:w-full [&_[data-slot=input-number]]:w-full [&_[data-slot=input]]:w-full [&_[data-slot=textarea]]:w-full',
|
|
631
|
+
'[&_[data-slot=cascader-select-trigger]]:w-full [&_[data-slot=select-trigger]]:w-full [&_[data-slot=tree-select-trigger]]:w-full',
|
|
632
|
+
'[&_[data-slot=date-picker]]:w-full [&_[data-slot=date-range-picker]]:w-full [&_[data-slot=mentions]]:w-full [&_[data-slot=time-picker]]:w-full [&_[data-slot=time-range-picker]]:w-full',
|
|
633
633
|
colClass,
|
|
634
634
|
)}
|
|
635
635
|
>
|