@teamix-evo/ui 0.5.0 → 0.5.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/package.json +6 -4
- package/src/components/button/index.tsx +2 -2
- package/src/components/button/stories.tsx +3 -0
- package/src/components/data-table/index.tsx +10 -5
- package/src/components/input/index.tsx +1 -1
- package/src/components/input-group/index.tsx +30 -20
- package/src/components/item/meta.md +21 -53
- package/src/components/item/stories.tsx +12 -44
- package/src/components/table/index.tsx +6 -2
- package/src/components/transfer/index.tsx +12 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamix-evo/ui",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Source-injected UI components for Teamix Evo (shadcn-based, antd capabilities)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
"vite": "^5.4.0",
|
|
52
52
|
"vite-tsconfig-paths": "^6.1.1",
|
|
53
53
|
"zod": "^3",
|
|
54
|
+
"@teamix-evo/registry": "0.9.0",
|
|
54
55
|
"@teamix-evo/eslint-config": "0.2.3",
|
|
55
|
-
"@teamix-evo/tokens": "^0.7.
|
|
56
|
-
"@teamix-evo/registry": "0.7.0"
|
|
56
|
+
"@teamix-evo/tokens": "^0.7.1"
|
|
57
57
|
},
|
|
58
58
|
"publishConfig": {
|
|
59
59
|
"access": "public",
|
|
@@ -76,6 +76,8 @@
|
|
|
76
76
|
"build": "echo 'pure resource package, no build needed'",
|
|
77
77
|
"gen:theme-overrides": "tsx .storybook/gen-theme-overrides.ts",
|
|
78
78
|
"storybook": "pnpm gen:theme-overrides && storybook dev -p 6006",
|
|
79
|
-
"build-storybook": "pnpm gen:theme-overrides && storybook build"
|
|
79
|
+
"build-storybook": "pnpm gen:theme-overrides && storybook build",
|
|
80
|
+
"compare": "tsx compare/start.ts",
|
|
81
|
+
"compare:matrix": "tsx compare/scripts/extract-styles-matrix.ts && tsx compare/scripts/generate-style-mapping.ts"
|
|
80
82
|
}
|
|
81
83
|
}
|
|
@@ -19,7 +19,7 @@ import { Spinner } from '@/components/spinner';
|
|
|
19
19
|
// ─── Button cva ─────────────────────────────────────────────────────────────
|
|
20
20
|
//
|
|
21
21
|
// 视觉由 token 驱动,组件只用语义 utility:
|
|
22
|
-
// - 圆角 `rounded-md
|
|
22
|
+
// - 圆角 `rounded-md`:走 --radius-md(opentrek=8px / uni-manager=2px),各变体 theme.css 驱动
|
|
23
23
|
// - focus ring `ring-ring`:opentrek=品牌色 halo / uni-manager=transparent
|
|
24
24
|
// - shadow:组件不写,uni-manager 通过 theme.css scoped CSS [data-slot='button'] 注入
|
|
25
25
|
|
|
@@ -39,7 +39,7 @@ const buttonVariants = cva(
|
|
|
39
39
|
dashed:
|
|
40
40
|
'border border-dashed border-input bg-card hover:bg-muted hover:text-foreground aria-expanded:bg-muted',
|
|
41
41
|
ghost:
|
|
42
|
-
'hover:bg-
|
|
42
|
+
'hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground',
|
|
43
43
|
link: 'text-primary hover:text-primary-hover',
|
|
44
44
|
},
|
|
45
45
|
// 语义色 — 与 variant 双 prop 组合
|
|
@@ -442,17 +442,22 @@ function ColumnFilterPopover({
|
|
|
442
442
|
return (
|
|
443
443
|
<Popover open={open} onOpenChange={setOpen}>
|
|
444
444
|
<PopoverTrigger asChild>
|
|
445
|
-
<
|
|
446
|
-
|
|
445
|
+
<span
|
|
446
|
+
role="button"
|
|
447
447
|
aria-label="过滤"
|
|
448
|
+
tabIndex={-1}
|
|
448
449
|
className={cn(
|
|
449
|
-
'inline-flex size-
|
|
450
|
+
'inline-flex size-4 shrink-0 cursor-pointer items-center justify-center rounded-sm text-muted-foreground transition-colors hover:text-foreground',
|
|
450
451
|
active && 'text-primary',
|
|
451
452
|
)}
|
|
453
|
+
onPointerDown={(e) => {
|
|
454
|
+
e.preventDefault();
|
|
455
|
+
e.stopPropagation();
|
|
456
|
+
}}
|
|
452
457
|
onClick={(e) => e.stopPropagation()}
|
|
453
458
|
>
|
|
454
459
|
<FilterIcon className="size-3.5" />
|
|
455
|
-
</
|
|
460
|
+
</span>
|
|
456
461
|
</PopoverTrigger>
|
|
457
462
|
<PopoverContent align="start" className="w-44 gap-2 p-2">
|
|
458
463
|
{mode === 'multiple' ? (
|
|
@@ -498,7 +503,7 @@ function ColumnFilterPopover({
|
|
|
498
503
|
</RadioGroup>
|
|
499
504
|
)}
|
|
500
505
|
<div className="mt-1 flex justify-end gap-2 border-t border-border pt-2">
|
|
501
|
-
<Button variant="
|
|
506
|
+
<Button variant="outline" size="sm" onClick={handleReset}>
|
|
502
507
|
重置
|
|
503
508
|
</Button>
|
|
504
509
|
<Button size="sm" onClick={handleConfirm}>
|
|
@@ -17,7 +17,7 @@ import { cn } from '@/lib/utils';
|
|
|
17
17
|
// ─── Input cva ──────────────────────────────────────────────────────────────
|
|
18
18
|
|
|
19
19
|
const inputVariants = cva(
|
|
20
|
-
'w-full min-w-0 cursor-text rounded-md border border-input bg-transparent font-normal transition-colors outline-none file:inline-flex file:cursor-pointer file:border-0 file:bg-transparent file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-
|
|
20
|
+
'w-full min-w-0 cursor-text rounded-md border border-input bg-transparent font-normal transition-colors outline-none file:inline-flex file:cursor-pointer file:border-0 file:bg-transparent file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/20 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-1 aria-invalid:ring-destructive/20',
|
|
21
21
|
{
|
|
22
22
|
variants: {
|
|
23
23
|
size: {
|
|
@@ -163,10 +163,7 @@ function InputGroupTextarea({
|
|
|
163
163
|
// ─── InputGroupClear ──────────────────────────────────────────────────────────────
|
|
164
164
|
|
|
165
165
|
export interface InputGroupClearProps
|
|
166
|
-
extends Omit<
|
|
167
|
-
React.ComponentProps<typeof InputGroupButton>,
|
|
168
|
-
'children' | 'aria-label'
|
|
169
|
-
> {
|
|
166
|
+
extends Omit<React.ComponentProps<'span'>, 'children'> {
|
|
170
167
|
/** 是否显示。受控用法下一般绑定 `value.length > 0`。 @default true */
|
|
171
168
|
visible?: boolean;
|
|
172
169
|
/** 无障碍 label。 @default '清除' */
|
|
@@ -181,32 +178,36 @@ function InputGroupClear({
|
|
|
181
178
|
visible = true,
|
|
182
179
|
className,
|
|
183
180
|
'aria-label': ariaLabel = '清除',
|
|
181
|
+
onClick,
|
|
184
182
|
...props
|
|
185
183
|
}: InputGroupClearProps) {
|
|
186
184
|
if (!visible) return null;
|
|
187
185
|
return (
|
|
188
|
-
<
|
|
189
|
-
|
|
190
|
-
size="icon-xs"
|
|
186
|
+
<span
|
|
187
|
+
role="button"
|
|
191
188
|
aria-label={ariaLabel}
|
|
189
|
+
tabIndex={-1}
|
|
190
|
+
data-slot="input-group-clear"
|
|
191
|
+
onPointerDown={(e) => {
|
|
192
|
+
e.preventDefault();
|
|
193
|
+
e.stopPropagation();
|
|
194
|
+
}}
|
|
195
|
+
onClick={onClick}
|
|
192
196
|
className={cn(
|
|
193
|
-
'text-muted-foreground
|
|
197
|
+
'inline-flex size-4 shrink-0 cursor-pointer items-center justify-center rounded-sm text-muted-foreground transition-colors hover:text-foreground',
|
|
194
198
|
className,
|
|
195
199
|
)}
|
|
196
200
|
{...props}
|
|
197
201
|
>
|
|
198
|
-
<XIcon />
|
|
199
|
-
</
|
|
202
|
+
<XIcon className="size-3.5" />
|
|
203
|
+
</span>
|
|
200
204
|
);
|
|
201
205
|
}
|
|
202
206
|
|
|
203
207
|
// ─── InputGroupPasswordToggle ───────────────────────────────────────────────────────
|
|
204
208
|
|
|
205
209
|
export interface InputGroupPasswordToggleProps
|
|
206
|
-
extends Omit<
|
|
207
|
-
React.ComponentProps<typeof InputGroupButton>,
|
|
208
|
-
'children' | 'onClick'
|
|
209
|
-
> {
|
|
210
|
+
extends Omit<React.ComponentProps<'span'>, 'children' | 'onClick'> {
|
|
210
211
|
/** 当前密码是否可见。 */
|
|
211
212
|
visible: boolean;
|
|
212
213
|
/** 切换可见性,由父级同步修改 `<InputGroupInput type>` 。 */
|
|
@@ -224,20 +225,29 @@ function InputGroupPasswordToggle({
|
|
|
224
225
|
...props
|
|
225
226
|
}: InputGroupPasswordToggleProps) {
|
|
226
227
|
return (
|
|
227
|
-
<
|
|
228
|
-
|
|
229
|
-
size="icon-xs"
|
|
228
|
+
<span
|
|
229
|
+
role="button"
|
|
230
230
|
aria-label={visible ? '隐藏密码' : '显示密码'}
|
|
231
231
|
aria-pressed={visible}
|
|
232
|
+
tabIndex={-1}
|
|
233
|
+
data-slot="input-group-password-toggle"
|
|
234
|
+
onPointerDown={(e) => {
|
|
235
|
+
e.preventDefault();
|
|
236
|
+
e.stopPropagation();
|
|
237
|
+
}}
|
|
232
238
|
onClick={() => onVisibleChange(!visible)}
|
|
233
239
|
className={cn(
|
|
234
|
-
'text-muted-foreground
|
|
240
|
+
'inline-flex size-4 shrink-0 cursor-pointer items-center justify-center rounded-sm text-muted-foreground transition-colors hover:text-foreground',
|
|
235
241
|
className,
|
|
236
242
|
)}
|
|
237
243
|
{...props}
|
|
238
244
|
>
|
|
239
|
-
{visible ?
|
|
240
|
-
|
|
245
|
+
{visible ? (
|
|
246
|
+
<EyeOffIcon className="size-3.5" />
|
|
247
|
+
) : (
|
|
248
|
+
<EyeIcon className="size-3.5" />
|
|
249
|
+
)}
|
|
250
|
+
</span>
|
|
241
251
|
);
|
|
242
252
|
}
|
|
243
253
|
|
|
@@ -16,20 +16,20 @@
|
|
|
16
16
|
- 图文卡片(horizontal 布局)
|
|
17
17
|
- 通知/消息列表
|
|
18
18
|
- 带操作的资源列表
|
|
19
|
-
- 组合结构:ItemGroup [bordered] [divider] > ItemGroupHeader + Item
|
|
19
|
+
- 组合结构:ItemGroup [bordered] [divider] > ItemGroupHeader + Item\* > ItemMedia + ItemContent (> ItemTitle + ItemDescription) + ItemExtra + ItemActions [separated] > ItemGroupFooter
|
|
20
20
|
|
|
21
21
|
## Props
|
|
22
22
|
|
|
23
|
-
| 名称
|
|
24
|
-
|
|
|
25
|
-
| `bordered`
|
|
26
|
-
| `divider`
|
|
27
|
-
| `variant`
|
|
28
|
-
| `size`
|
|
29
|
-
| `layout`
|
|
30
|
-
| `asChild`
|
|
31
|
-
| `variant`
|
|
32
|
-
| `separated` | `boolean`
|
|
23
|
+
| 名称 | 类型 | 默认值 | 必填 | 说明 |
|
|
24
|
+
| ----------- | ------------------------------------------- | ------------ | ---- | ---------------------------- |
|
|
25
|
+
| `bordered` | `"true" \| "false"` | – | – | – |
|
|
26
|
+
| `divider` | `"true" \| "false"` | – | – | – |
|
|
27
|
+
| `variant` | `"default" \| "outline" \| "muted"` | `"default"` | – | – |
|
|
28
|
+
| `size` | `"default" \| "sm" \| "xs"` | `"default"` | – | – |
|
|
29
|
+
| `layout` | `"vertical" \| "horizontal"` | `"vertical"` | – | – |
|
|
30
|
+
| `asChild` | `boolean` | – | – | 使用 Slot 模式渲染子元素 |
|
|
31
|
+
| `variant` | `"default" \| "icon" \| "image" \| "cover"` | `"default"` | – | – |
|
|
32
|
+
| `separated` | `boolean` | – | – | 子元素之间自动插入竖向分隔线 |
|
|
33
33
|
|
|
34
34
|
## 示例
|
|
35
35
|
|
|
@@ -127,18 +127,10 @@
|
|
|
127
127
|
<span className="text-xs text-muted-foreground">3 小时前更新</span>
|
|
128
128
|
</ItemContent>
|
|
129
129
|
<ItemActions>
|
|
130
|
-
<Button
|
|
131
|
-
size="sm"
|
|
132
|
-
variant="ghost"
|
|
133
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
134
|
-
>
|
|
130
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
135
131
|
编辑
|
|
136
132
|
</Button>
|
|
137
|
-
<Button
|
|
138
|
-
size="sm"
|
|
139
|
-
variant="ghost"
|
|
140
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
141
|
-
>
|
|
133
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
142
134
|
删除
|
|
143
135
|
</Button>
|
|
144
136
|
</ItemActions>
|
|
@@ -159,18 +151,10 @@
|
|
|
159
151
|
<span className="text-xs text-muted-foreground">1 天前更新</span>
|
|
160
152
|
</ItemContent>
|
|
161
153
|
<ItemActions>
|
|
162
|
-
<Button
|
|
163
|
-
size="sm"
|
|
164
|
-
variant="ghost"
|
|
165
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
166
|
-
>
|
|
154
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
167
155
|
编辑
|
|
168
156
|
</Button>
|
|
169
|
-
<Button
|
|
170
|
-
size="sm"
|
|
171
|
-
variant="ghost"
|
|
172
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
173
|
-
>
|
|
157
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
174
158
|
删除
|
|
175
159
|
</Button>
|
|
176
160
|
</ItemActions>
|
|
@@ -221,26 +205,18 @@ Actions 自动分隔
|
|
|
221
205
|
<ItemDescription>点击操作按钮管理</ItemDescription>
|
|
222
206
|
</ItemContent>
|
|
223
207
|
<ItemActions separated>
|
|
224
|
-
<Button
|
|
225
|
-
size="sm"
|
|
226
|
-
variant="ghost"
|
|
227
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
228
|
-
>
|
|
208
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
229
209
|
<PencilIcon />
|
|
230
210
|
编辑
|
|
231
211
|
</Button>
|
|
232
|
-
<Button
|
|
233
|
-
size="sm"
|
|
234
|
-
variant="ghost"
|
|
235
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
236
|
-
>
|
|
212
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
237
213
|
<BookmarkIcon />
|
|
238
214
|
收藏
|
|
239
215
|
</Button>
|
|
240
216
|
<Button
|
|
241
217
|
size="sm"
|
|
242
|
-
variant="
|
|
243
|
-
className="text-destructive hover:
|
|
218
|
+
variant="link"
|
|
219
|
+
className="text-destructive hover:text-destructive/80"
|
|
244
220
|
>
|
|
245
221
|
<TrashIcon />
|
|
246
222
|
删除
|
|
@@ -314,11 +290,7 @@ Actions 自动分隔
|
|
|
314
290
|
</Item>
|
|
315
291
|
<ItemGroupFooter>
|
|
316
292
|
<span>共 2 条通知</span>
|
|
317
|
-
<Button
|
|
318
|
-
size="sm"
|
|
319
|
-
variant="ghost"
|
|
320
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
321
|
-
>
|
|
293
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
322
294
|
查看全部
|
|
323
295
|
</Button>
|
|
324
296
|
</ItemGroupFooter>
|
|
@@ -344,11 +316,7 @@ Actions 自动分隔
|
|
|
344
316
|
</ItemContent>
|
|
345
317
|
<ItemFooter>
|
|
346
318
|
<span>截止:2025-01-15</span>
|
|
347
|
-
<Button
|
|
348
|
-
size="sm"
|
|
349
|
-
variant="ghost"
|
|
350
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
351
|
-
>
|
|
319
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
352
320
|
查看
|
|
353
321
|
</Button>
|
|
354
322
|
</ItemFooter>
|
|
@@ -51,7 +51,7 @@ export const Default: Story = {
|
|
|
51
51
|
<Button
|
|
52
52
|
size="icon-sm"
|
|
53
53
|
variant="ghost"
|
|
54
|
-
className="text-muted-foreground
|
|
54
|
+
className="text-muted-foreground"
|
|
55
55
|
>
|
|
56
56
|
<MoreHorizontalIcon />
|
|
57
57
|
</Button>
|
|
@@ -69,7 +69,7 @@ export const Default: Story = {
|
|
|
69
69
|
<Button
|
|
70
70
|
size="icon-sm"
|
|
71
71
|
variant="ghost"
|
|
72
|
-
className="text-muted-foreground
|
|
72
|
+
className="text-muted-foreground"
|
|
73
73
|
>
|
|
74
74
|
<MoreHorizontalIcon />
|
|
75
75
|
</Button>
|
|
@@ -169,18 +169,10 @@ export const Horizontal: Story = {
|
|
|
169
169
|
<span className="text-xs text-muted-foreground">3 小时前更新</span>
|
|
170
170
|
</ItemContent>
|
|
171
171
|
<ItemActions>
|
|
172
|
-
<Button
|
|
173
|
-
size="sm"
|
|
174
|
-
variant="ghost"
|
|
175
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
176
|
-
>
|
|
172
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
177
173
|
编辑
|
|
178
174
|
</Button>
|
|
179
|
-
<Button
|
|
180
|
-
size="sm"
|
|
181
|
-
variant="ghost"
|
|
182
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
183
|
-
>
|
|
175
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
184
176
|
删除
|
|
185
177
|
</Button>
|
|
186
178
|
</ItemActions>
|
|
@@ -201,18 +193,10 @@ export const Horizontal: Story = {
|
|
|
201
193
|
<span className="text-xs text-muted-foreground">1 天前更新</span>
|
|
202
194
|
</ItemContent>
|
|
203
195
|
<ItemActions>
|
|
204
|
-
<Button
|
|
205
|
-
size="sm"
|
|
206
|
-
variant="ghost"
|
|
207
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
208
|
-
>
|
|
196
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
209
197
|
编辑
|
|
210
198
|
</Button>
|
|
211
|
-
<Button
|
|
212
|
-
size="sm"
|
|
213
|
-
variant="ghost"
|
|
214
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
215
|
-
>
|
|
199
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
216
200
|
删除
|
|
217
201
|
</Button>
|
|
218
202
|
</ItemActions>
|
|
@@ -261,26 +245,18 @@ export const ActionsSeparated: Story = {
|
|
|
261
245
|
<ItemDescription>点击操作按钮管理</ItemDescription>
|
|
262
246
|
</ItemContent>
|
|
263
247
|
<ItemActions separated>
|
|
264
|
-
<Button
|
|
265
|
-
size="sm"
|
|
266
|
-
variant="ghost"
|
|
267
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
268
|
-
>
|
|
248
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
269
249
|
<PencilIcon />
|
|
270
250
|
编辑
|
|
271
251
|
</Button>
|
|
272
|
-
<Button
|
|
273
|
-
size="sm"
|
|
274
|
-
variant="ghost"
|
|
275
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
276
|
-
>
|
|
252
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
277
253
|
<BookmarkIcon />
|
|
278
254
|
收藏
|
|
279
255
|
</Button>
|
|
280
256
|
<Button
|
|
281
257
|
size="sm"
|
|
282
|
-
variant="
|
|
283
|
-
className="text-destructive hover:
|
|
258
|
+
variant="link"
|
|
259
|
+
className="text-destructive hover:text-destructive/80"
|
|
284
260
|
>
|
|
285
261
|
<TrashIcon />
|
|
286
262
|
删除
|
|
@@ -352,11 +328,7 @@ export const GroupWithHeaderFooter: Story = {
|
|
|
352
328
|
</Item>
|
|
353
329
|
<ItemGroupFooter>
|
|
354
330
|
<span>共 2 条通知</span>
|
|
355
|
-
<Button
|
|
356
|
-
size="sm"
|
|
357
|
-
variant="ghost"
|
|
358
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
359
|
-
>
|
|
331
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
360
332
|
查看全部
|
|
361
333
|
</Button>
|
|
362
334
|
</ItemGroupFooter>
|
|
@@ -381,11 +353,7 @@ export const WithHeaderFooter: Story = {
|
|
|
381
353
|
</ItemContent>
|
|
382
354
|
<ItemFooter>
|
|
383
355
|
<span>截止:2025-01-15</span>
|
|
384
|
-
<Button
|
|
385
|
-
size="sm"
|
|
386
|
-
variant="ghost"
|
|
387
|
-
className="text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
388
|
-
>
|
|
356
|
+
<Button size="sm" variant="link" className="text-muted-foreground">
|
|
389
357
|
查看
|
|
390
358
|
</Button>
|
|
391
359
|
</ItemFooter>
|
|
@@ -176,11 +176,15 @@ function TableHeader({ className, ...props }: React.ComponentProps<'thead'>) {
|
|
|
176
176
|
// ─── TableBody ──────────────────────────────────────────────────────────────
|
|
177
177
|
|
|
178
178
|
function TableBody({ className, ...props }: React.ComponentProps<'tbody'>) {
|
|
179
|
-
const { striped } = useTableContext();
|
|
179
|
+
const { striped, bordered } = useTableContext();
|
|
180
180
|
return (
|
|
181
181
|
<tbody
|
|
182
182
|
data-slot="table-body"
|
|
183
|
-
className={cn(
|
|
183
|
+
className={cn(
|
|
184
|
+
striped && '[&_tr:nth-child(even)]:bg-muted/30',
|
|
185
|
+
bordered && '[&>tr:last-child]:border-b-0',
|
|
186
|
+
className,
|
|
187
|
+
)}
|
|
184
188
|
{...props}
|
|
185
189
|
/>
|
|
186
190
|
);
|
|
@@ -328,10 +328,7 @@ function TransferPanel({
|
|
|
328
328
|
|
|
329
329
|
{/* Search */}
|
|
330
330
|
{showSearch ? (
|
|
331
|
-
<div
|
|
332
|
-
data-slot="transfer-search"
|
|
333
|
-
className="px-2 pt-1.5 pb-2"
|
|
334
|
-
>
|
|
331
|
+
<div data-slot="transfer-search" className="px-2 pt-1.5 pb-2">
|
|
335
332
|
<Input
|
|
336
333
|
value={search}
|
|
337
334
|
disabled={disabled}
|
|
@@ -404,17 +401,22 @@ function TransferPanel({
|
|
|
404
401
|
) : null}
|
|
405
402
|
<div className="min-w-0 flex-1">{renderItemContent(item)}</div>
|
|
406
403
|
{showRemove ? (
|
|
407
|
-
<
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
404
|
+
<span
|
|
405
|
+
role="button"
|
|
406
|
+
aria-label="移除"
|
|
407
|
+
tabIndex={-1}
|
|
408
|
+
onPointerDown={(e) => {
|
|
409
|
+
e.preventDefault();
|
|
410
|
+
e.stopPropagation();
|
|
411
|
+
}}
|
|
411
412
|
onClick={(e) => {
|
|
412
413
|
e.stopPropagation();
|
|
413
414
|
onItemRemove?.(item.key);
|
|
414
415
|
}}
|
|
416
|
+
className="inline-flex size-4 shrink-0 cursor-pointer items-center justify-center rounded-sm text-muted-foreground opacity-0 transition-colors hover:text-foreground group-hover/transfer-item:opacity-100"
|
|
415
417
|
>
|
|
416
|
-
<X />
|
|
417
|
-
</
|
|
418
|
+
<X className="size-3.5" />
|
|
419
|
+
</span>
|
|
418
420
|
) : null}
|
|
419
421
|
</div>
|
|
420
422
|
);
|