@teamix-evo/ui 0.6.1 → 0.7.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/manifest.json +6 -1
- package/package.json +3 -3
- package/src/components/data-table/index.tsx +0 -6
- package/src/components/date-picker/index.tsx +0 -1
- package/src/components/dialog/index.tsx +10 -1
- package/src/components/page-header/stories.tsx +87 -1
- package/src/components/sheet/index.tsx +10 -1
- package/src/components/table/index.tsx +1 -1
- package/src/components/tabs/index.tsx +1 -1
- package/src/examples/built-in-assets/stories.tsx +572 -0
- package/src/examples/evaluators/stories.tsx +502 -0
- package/src/hooks/use-radix-popper-guard.ts +51 -0
package/manifest.json
CHANGED
|
@@ -1150,6 +1150,11 @@
|
|
|
1150
1150
|
"source": "src/components/tree/index.tsx",
|
|
1151
1151
|
"targetAlias": "components",
|
|
1152
1152
|
"targetName": "tree.tsx"
|
|
1153
|
+
},
|
|
1154
|
+
{
|
|
1155
|
+
"source": "src/components/tree/utils.ts",
|
|
1156
|
+
"targetAlias": "components",
|
|
1157
|
+
"targetName": "utils.ts"
|
|
1153
1158
|
}
|
|
1154
1159
|
],
|
|
1155
1160
|
"meta": "src/components/tree/meta.md",
|
|
@@ -1372,7 +1377,7 @@
|
|
|
1372
1377
|
}
|
|
1373
1378
|
],
|
|
1374
1379
|
"meta": "src/components/tree-select/meta.md",
|
|
1375
|
-
"registryDependencies": ["cn", "popover", "checkbox"],
|
|
1380
|
+
"registryDependencies": ["cn", "popover", "checkbox", "tree"],
|
|
1376
1381
|
"dependencies": {
|
|
1377
1382
|
"lucide-react": "^0.460.0",
|
|
1378
1383
|
"class-variance-authority": "^0.7.1"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamix-evo/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
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.12.0",
|
|
54
55
|
"@teamix-evo/eslint-config": "0.2.3",
|
|
55
|
-
"@teamix-evo/tokens": "^0.
|
|
56
|
-
"@teamix-evo/registry": "0.12.0"
|
|
56
|
+
"@teamix-evo/tokens": "^0.8.0"
|
|
57
57
|
},
|
|
58
58
|
"publishConfig": {
|
|
59
59
|
"access": "public",
|
|
@@ -289,12 +289,6 @@ function alignClass(align?: DataTableColumn<unknown>['align']) {
|
|
|
289
289
|
return undefined;
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
-
function widthStyle(col: DataTableColumn<unknown>): React.CSSProperties {
|
|
293
|
-
const w = col.size ?? col.width;
|
|
294
|
-
if (w === undefined) return {};
|
|
295
|
-
return { width: typeof w === 'number' ? `${w}px` : w };
|
|
296
|
-
}
|
|
297
|
-
|
|
298
292
|
/** 把 DataTableColumn 适配为 TanStack ColumnDef;同时按 fixed 重排(左→中→右)以满足锁列 sticky 计算。 */
|
|
299
293
|
function adaptColumns<T>(
|
|
300
294
|
columns: DataTableColumn<T>[],
|
|
@@ -23,6 +23,7 @@ import * as React from 'react';
|
|
|
23
23
|
import { Dialog as DialogPrimitive } from 'radix-ui';
|
|
24
24
|
|
|
25
25
|
import { cn } from '@/lib/utils';
|
|
26
|
+
import { useRadixPopperGuard } from '@/hooks/use-radix-popper-guard';
|
|
26
27
|
import { XIcon } from 'lucide-react';
|
|
27
28
|
|
|
28
29
|
export interface DialogProps
|
|
@@ -95,6 +96,7 @@ function DialogContent({
|
|
|
95
96
|
children,
|
|
96
97
|
size = 'sm',
|
|
97
98
|
showCloseButton = true,
|
|
99
|
+
onPointerDownOutside,
|
|
98
100
|
...props
|
|
99
101
|
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
|
100
102
|
/** 内容区尺寸。 @default 'sm' */
|
|
@@ -102,12 +104,18 @@ function DialogContent({
|
|
|
102
104
|
/** 是否显示右上角关闭按钮。 @default true */
|
|
103
105
|
showCloseButton?: boolean;
|
|
104
106
|
}) {
|
|
107
|
+
const guard = useRadixPopperGuard();
|
|
108
|
+
|
|
105
109
|
return (
|
|
106
110
|
<DialogPortal>
|
|
107
111
|
<DialogOverlay />
|
|
108
112
|
<DialogPrimitive.Content
|
|
109
113
|
data-slot="dialog-content"
|
|
110
114
|
data-size={size}
|
|
115
|
+
onPointerDownOutside={(e) => {
|
|
116
|
+
guard.onPointerDownOutside(e);
|
|
117
|
+
onPointerDownOutside?.(e);
|
|
118
|
+
}}
|
|
111
119
|
className={cn(
|
|
112
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.
|
|
113
121
|
'fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-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-[size=sm]:sm:max-w-md data-[size=md]:sm:max-w-xl data-[size=lg]:sm:max-w-3xl data-[size=xl]:sm:max-w-6xl data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95',
|
|
@@ -199,7 +207,8 @@ function DialogFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
|
|
199
207
|
<div
|
|
200
208
|
data-slot="dialog-footer"
|
|
201
209
|
className={cn(
|
|
202
|
-
|
|
210
|
+
// eslint-disable-next-line teamix-evo/no-bare-border -- border-footer-separator 是 @theme 声明的语义 token,已加入 lint-core 白名单
|
|
211
|
+
'flex flex-col-reverse gap-2 border-t border-footer-separator px-5 py-4 sm:flex-row sm:justify-end',
|
|
203
212
|
className,
|
|
204
213
|
)}
|
|
205
214
|
{...props}
|
|
@@ -39,8 +39,94 @@ export default meta;
|
|
|
39
39
|
|
|
40
40
|
type Story = StoryObj<typeof meta>;
|
|
41
41
|
|
|
42
|
-
/**
|
|
42
|
+
/** 仅标题:最基础的页头形态,只包含一个标题。 */
|
|
43
43
|
export const Default: Story = {
|
|
44
|
+
render: () => (
|
|
45
|
+
<PageHeader>
|
|
46
|
+
<PageHeaderContent>
|
|
47
|
+
<PageHeaderHeading>
|
|
48
|
+
<PageHeaderTitle>页面标题</PageHeaderTitle>
|
|
49
|
+
</PageHeaderHeading>
|
|
50
|
+
</PageHeaderContent>
|
|
51
|
+
</PageHeader>
|
|
52
|
+
),
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/** 标题 + 描述:标题下方附加一行描述文字。 */
|
|
56
|
+
export const WithDescription: Story = {
|
|
57
|
+
render: () => (
|
|
58
|
+
<PageHeader>
|
|
59
|
+
<PageHeaderContent>
|
|
60
|
+
<div className="flex flex-col">
|
|
61
|
+
<PageHeaderHeading>
|
|
62
|
+
<PageHeaderTitle>页面标题</PageHeaderTitle>
|
|
63
|
+
</PageHeaderHeading>
|
|
64
|
+
<PageHeaderDescription>
|
|
65
|
+
页面描述页面描述页面描述页面描述页面描述页面描述页面描述
|
|
66
|
+
</PageHeaderDescription>
|
|
67
|
+
</div>
|
|
68
|
+
</PageHeaderContent>
|
|
69
|
+
</PageHeader>
|
|
70
|
+
),
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/** 仅面包屑:只有面包屑导航,无标题。 */
|
|
74
|
+
export const OnlyBreadcrumb: Story = {
|
|
75
|
+
render: () => (
|
|
76
|
+
<PageHeader>
|
|
77
|
+
<PageHeaderNav>
|
|
78
|
+
<Breadcrumb>
|
|
79
|
+
<BreadcrumbList>
|
|
80
|
+
<BreadcrumbItem>
|
|
81
|
+
<BreadcrumbLink href="#">首页</BreadcrumbLink>
|
|
82
|
+
</BreadcrumbItem>
|
|
83
|
+
<BreadcrumbSeparator />
|
|
84
|
+
<BreadcrumbItem>
|
|
85
|
+
<BreadcrumbLink href="#">实例列表</BreadcrumbLink>
|
|
86
|
+
</BreadcrumbItem>
|
|
87
|
+
<BreadcrumbSeparator />
|
|
88
|
+
<BreadcrumbItem>
|
|
89
|
+
<BreadcrumbPage>实例详情</BreadcrumbPage>
|
|
90
|
+
</BreadcrumbItem>
|
|
91
|
+
</BreadcrumbList>
|
|
92
|
+
</Breadcrumb>
|
|
93
|
+
</PageHeaderNav>
|
|
94
|
+
</PageHeader>
|
|
95
|
+
),
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/** 面包屑 + 标题:面包屑导航 + 标题,常见于二级页面。 */
|
|
99
|
+
export const WithBreadcrumb: Story = {
|
|
100
|
+
render: () => (
|
|
101
|
+
<PageHeader>
|
|
102
|
+
<PageHeaderNav>
|
|
103
|
+
<Breadcrumb>
|
|
104
|
+
<BreadcrumbList>
|
|
105
|
+
<BreadcrumbItem>
|
|
106
|
+
<BreadcrumbLink href="#">首页</BreadcrumbLink>
|
|
107
|
+
</BreadcrumbItem>
|
|
108
|
+
<BreadcrumbSeparator />
|
|
109
|
+
<BreadcrumbItem>
|
|
110
|
+
<BreadcrumbLink href="#">实例列表</BreadcrumbLink>
|
|
111
|
+
</BreadcrumbItem>
|
|
112
|
+
<BreadcrumbSeparator />
|
|
113
|
+
<BreadcrumbItem>
|
|
114
|
+
<BreadcrumbPage>实例详情</BreadcrumbPage>
|
|
115
|
+
</BreadcrumbItem>
|
|
116
|
+
</BreadcrumbList>
|
|
117
|
+
</Breadcrumb>
|
|
118
|
+
</PageHeaderNav>
|
|
119
|
+
<PageHeaderContent>
|
|
120
|
+
<PageHeaderHeading>
|
|
121
|
+
<PageHeaderTitle>实例详情</PageHeaderTitle>
|
|
122
|
+
</PageHeaderHeading>
|
|
123
|
+
</PageHeaderContent>
|
|
124
|
+
</PageHeader>
|
|
125
|
+
),
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/** 完整版页头:面包屑 + 帮助链接 + 返回 + 主图标 + 标题(含 ⓘ) + 描述 + 多操作。 */
|
|
129
|
+
export const Full: Story = {
|
|
44
130
|
render: () => (
|
|
45
131
|
<PageHeader>
|
|
46
132
|
<PageHeaderNav>
|
|
@@ -25,6 +25,7 @@ import * as React from 'react';
|
|
|
25
25
|
import { Dialog as SheetPrimitive } from 'radix-ui';
|
|
26
26
|
|
|
27
27
|
import { cn } from '@/lib/utils';
|
|
28
|
+
import { useRadixPopperGuard } from '@/hooks/use-radix-popper-guard';
|
|
28
29
|
import { XIcon } from 'lucide-react';
|
|
29
30
|
|
|
30
31
|
export interface SheetProps
|
|
@@ -104,6 +105,7 @@ function SheetContent({
|
|
|
104
105
|
side = 'right',
|
|
105
106
|
size = 'sm',
|
|
106
107
|
showCloseButton = true,
|
|
108
|
+
onPointerDownOutside,
|
|
107
109
|
...props
|
|
108
110
|
}: React.ComponentProps<typeof SheetPrimitive.Content> & {
|
|
109
111
|
/** 弹出方向。 @default 'right' */
|
|
@@ -113,6 +115,8 @@ function SheetContent({
|
|
|
113
115
|
/** 是否显示右上角关闭按钮。 @default true */
|
|
114
116
|
showCloseButton?: boolean;
|
|
115
117
|
}) {
|
|
118
|
+
const guard = useRadixPopperGuard();
|
|
119
|
+
|
|
116
120
|
return (
|
|
117
121
|
<SheetPortal>
|
|
118
122
|
<SheetOverlay />
|
|
@@ -120,6 +124,10 @@ function SheetContent({
|
|
|
120
124
|
data-slot="sheet-content"
|
|
121
125
|
data-side={side}
|
|
122
126
|
data-size={size}
|
|
127
|
+
onPointerDownOutside={(e) => {
|
|
128
|
+
guard.onPointerDownOutside(e);
|
|
129
|
+
onPointerDownOutside?.(e);
|
|
130
|
+
}}
|
|
123
131
|
className={cn(
|
|
124
132
|
// 基础布局:fixed 定位 + flex 列容器 + token 化阴影(抽屉与背景的边界由阴影表达,不画 border)
|
|
125
133
|
// eslint-disable-next-line teamix-evo/no-arbitrary-tw-value -- box-shadow 走 component-level token --drawer-shadow,按 ADR 0026 在源码内显式声明。
|
|
@@ -237,7 +245,8 @@ function SheetFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
|
|
237
245
|
<div
|
|
238
246
|
data-slot="sheet-footer"
|
|
239
247
|
className={cn(
|
|
240
|
-
|
|
248
|
+
// eslint-disable-next-line teamix-evo/no-bare-border -- border-footer-separator 是 @theme 声明的语义 token,已加入 lint-core 白名单
|
|
249
|
+
'flex flex-col gap-2 border-t border-footer-separator px-4 py-2.5 sm:flex-row sm:justify-start',
|
|
241
250
|
className,
|
|
242
251
|
)}
|
|
243
252
|
{...props}
|
|
@@ -154,7 +154,7 @@ function Table({
|
|
|
154
154
|
// ─── TableHeader ────────────────────────────────────────────────────────────
|
|
155
155
|
|
|
156
156
|
function TableHeader({ className, ...props }: React.ComponentProps<'thead'>) {
|
|
157
|
-
const { stickyHeader
|
|
157
|
+
const { stickyHeader } = useTableContext();
|
|
158
158
|
return (
|
|
159
159
|
<thead
|
|
160
160
|
data-slot="table-header"
|
|
@@ -269,7 +269,7 @@ const tabsTriggerVariants = cva(
|
|
|
269
269
|
{
|
|
270
270
|
variants: {
|
|
271
271
|
variant: {
|
|
272
|
-
line: '-mb-px border-b-2 border-transparent text-muted-foreground data-[state=active]:border-
|
|
272
|
+
line: '-mb-px border-b-2 border-transparent text-muted-foreground data-[state=active]:border-tab-indicator data-[state=active]:text-foreground group-data-[orientation=vertical]/tabs:mb-0 group-data-[orientation=vertical]/tabs:-mr-px group-data-[orientation=vertical]/tabs:border-b-0 group-data-[orientation=vertical]/tabs:border-r-2 group-data-[orientation=vertical]/tabs:justify-start',
|
|
273
273
|
capsule:
|
|
274
274
|
'rounded-md text-muted-foreground data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm',
|
|
275
275
|
// text 模式:trigger 间 ::after 竖线分隔(8px 高、1px 宽、垂直居中、border 色)
|