@cut-workbench/workbench 0.1.0 → 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 +153 -9
- package/dist/CutWorkbench.d.ts +26 -1
- package/dist/auto.cjs +4 -0
- package/dist/auto.d.ts +19 -0
- package/dist/auto.js +8 -0
- package/dist/components/common/UnsupportedBrowser.d.ts +6 -1
- package/dist/components/layout/AppShell.d.ts +17 -3
- package/dist/components/layout/WorkbenchToolbar.d.ts +39 -2
- package/dist/cut-workbench.css +47 -6
- package/dist/features/lab/index.d.ts +5 -1
- package/dist/format--DhqHMgX.cjs +208 -0
- package/dist/format--DhqHMgX.cjs.map +1 -0
- package/dist/format-CV2aoZZC.js +109 -0
- package/dist/format-CV2aoZZC.js.map +1 -0
- package/dist/index.cjs +500 -1620
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +419 -1518
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +3 -0
- package/dist/lab-disabled.cjs +6 -0
- package/dist/lab-disabled.cjs.map +1 -0
- package/dist/lab-disabled.d.ts +13 -0
- package/dist/lab-disabled.js +5 -0
- package/dist/lab-disabled.js.map +1 -0
- package/dist/lab.cjs +1178 -0
- package/dist/lab.cjs.map +1 -0
- package/dist/lab.d.ts +32 -0
- package/dist/lab.js +1177 -0
- package/dist/lab.js.map +1 -0
- package/dist/umd/cut-workbench.umd.js +1 -1
- package/package.json +84 -67
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
// \0rolldown/runtime.js
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
let react = require("react");
|
|
23
|
+
react = __toESM(react, 1);
|
|
24
|
+
let _cut_workbench_core = require("@cut-workbench/core");
|
|
25
|
+
let clsx = require("clsx");
|
|
26
|
+
let tailwind_merge = require("tailwind-merge");
|
|
27
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
28
|
+
let class_variance_authority = require("class-variance-authority");
|
|
29
|
+
let radix_ui = require("radix-ui");
|
|
30
|
+
// src/lib/cn.ts
|
|
31
|
+
/**
|
|
32
|
+
* 合并 className:tailwind-merge 负责消解冲突,clsx 负责条件拼接。
|
|
33
|
+
*/
|
|
34
|
+
function cn(...inputs) {
|
|
35
|
+
return (0, tailwind_merge.twMerge)((0, clsx.clsx)(inputs));
|
|
36
|
+
}
|
|
37
|
+
// src/components/ui/badge.tsx
|
|
38
|
+
var badgeVariants = (0, class_variance_authority.cva)("inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3", {
|
|
39
|
+
variants: { variant: {
|
|
40
|
+
default: "bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
|
41
|
+
secondary: "bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
|
42
|
+
destructive: "bg-destructive text-destructive-foreground focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90",
|
|
43
|
+
outline: "border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
|
44
|
+
ghost: "[a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
|
45
|
+
link: "text-primary underline-offset-4 [a&]:hover:underline"
|
|
46
|
+
} },
|
|
47
|
+
defaultVariants: { variant: "default" }
|
|
48
|
+
});
|
|
49
|
+
function Badge({ className, variant = "default", asChild = false, ...props }) {
|
|
50
|
+
const Comp = asChild ? radix_ui.Slot.Root : "span";
|
|
51
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Comp, {
|
|
52
|
+
"data-slot": "badge",
|
|
53
|
+
"data-variant": variant,
|
|
54
|
+
className: cn(badgeVariants({ variant }), className),
|
|
55
|
+
...props
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
// src/components/ui/card.tsx
|
|
59
|
+
function Card({ className, ...props }) {
|
|
60
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
61
|
+
"data-slot": "card",
|
|
62
|
+
className: cn("flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm", className),
|
|
63
|
+
...props
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function CardHeader({ className, ...props }) {
|
|
67
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
68
|
+
"data-slot": "card-header",
|
|
69
|
+
className: cn("@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6", className),
|
|
70
|
+
...props
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function CardTitle({ className, ...props }) {
|
|
74
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
75
|
+
"data-slot": "card-title",
|
|
76
|
+
className: cn("leading-none font-semibold", className),
|
|
77
|
+
...props
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function CardDescription({ className, ...props }) {
|
|
81
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
82
|
+
"data-slot": "card-description",
|
|
83
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
84
|
+
...props
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function CardContent({ className, ...props }) {
|
|
88
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
89
|
+
"data-slot": "card-content",
|
|
90
|
+
className: cn("px-6", className),
|
|
91
|
+
...props
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
// src/lib/format.ts
|
|
95
|
+
/** 字节数 → 人类可读 */
|
|
96
|
+
function formatBytes(bytes) {
|
|
97
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
98
|
+
const units = [
|
|
99
|
+
"KB",
|
|
100
|
+
"MB",
|
|
101
|
+
"GB"
|
|
102
|
+
];
|
|
103
|
+
let value = bytes / 1024;
|
|
104
|
+
let i = 0;
|
|
105
|
+
while (value >= 1024 && i < units.length - 1) {
|
|
106
|
+
value /= 1024;
|
|
107
|
+
i += 1;
|
|
108
|
+
}
|
|
109
|
+
return `${value.toFixed(value >= 100 ? 0 : 1)} ${units[i]}`;
|
|
110
|
+
}
|
|
111
|
+
/** 像素尺寸 → `1920×1080` */
|
|
112
|
+
function formatResolution(width, height) {
|
|
113
|
+
if (!width || !height) return "—";
|
|
114
|
+
return `${width}×${height}`;
|
|
115
|
+
}
|
|
116
|
+
/** 秒数 → `12.3s` */
|
|
117
|
+
function formatElapsed(seconds) {
|
|
118
|
+
if (seconds < 60) return `${seconds.toFixed(1)}s`;
|
|
119
|
+
return `${Math.floor(seconds / 60)}m ${Math.round(seconds % 60)}s`;
|
|
120
|
+
}
|
|
121
|
+
/** 微秒 → 秒(保留一位小数,用于表单展示) */
|
|
122
|
+
function formatSeconds(us) {
|
|
123
|
+
return (0, _cut_workbench_core.usToSec)(us).toFixed(2);
|
|
124
|
+
}
|
|
125
|
+
/** 百分比 0~1 → `42%` */
|
|
126
|
+
function formatPercent(ratio) {
|
|
127
|
+
return `${Math.round(ratio * 100)}%`;
|
|
128
|
+
}
|
|
129
|
+
Object.defineProperty(exports, "Badge", {
|
|
130
|
+
enumerable: true,
|
|
131
|
+
get: function() {
|
|
132
|
+
return Badge;
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
Object.defineProperty(exports, "Card", {
|
|
136
|
+
enumerable: true,
|
|
137
|
+
get: function() {
|
|
138
|
+
return Card;
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
Object.defineProperty(exports, "CardContent", {
|
|
142
|
+
enumerable: true,
|
|
143
|
+
get: function() {
|
|
144
|
+
return CardContent;
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
Object.defineProperty(exports, "CardDescription", {
|
|
148
|
+
enumerable: true,
|
|
149
|
+
get: function() {
|
|
150
|
+
return CardDescription;
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
Object.defineProperty(exports, "CardHeader", {
|
|
154
|
+
enumerable: true,
|
|
155
|
+
get: function() {
|
|
156
|
+
return CardHeader;
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
Object.defineProperty(exports, "CardTitle", {
|
|
160
|
+
enumerable: true,
|
|
161
|
+
get: function() {
|
|
162
|
+
return CardTitle;
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
Object.defineProperty(exports, "__toESM", {
|
|
166
|
+
enumerable: true,
|
|
167
|
+
get: function() {
|
|
168
|
+
return __toESM;
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
Object.defineProperty(exports, "cn", {
|
|
172
|
+
enumerable: true,
|
|
173
|
+
get: function() {
|
|
174
|
+
return cn;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
Object.defineProperty(exports, "formatBytes", {
|
|
178
|
+
enumerable: true,
|
|
179
|
+
get: function() {
|
|
180
|
+
return formatBytes;
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
Object.defineProperty(exports, "formatElapsed", {
|
|
184
|
+
enumerable: true,
|
|
185
|
+
get: function() {
|
|
186
|
+
return formatElapsed;
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
Object.defineProperty(exports, "formatPercent", {
|
|
190
|
+
enumerable: true,
|
|
191
|
+
get: function() {
|
|
192
|
+
return formatPercent;
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
Object.defineProperty(exports, "formatResolution", {
|
|
196
|
+
enumerable: true,
|
|
197
|
+
get: function() {
|
|
198
|
+
return formatResolution;
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
Object.defineProperty(exports, "formatSeconds", {
|
|
202
|
+
enumerable: true,
|
|
203
|
+
get: function() {
|
|
204
|
+
return formatSeconds;
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
//# sourceMappingURL=format--DhqHMgX.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format--DhqHMgX.cjs","names":["twMerge","cva","Slot","usToSec"],"sources":["../src/lib/cn.ts","../src/components/ui/badge.tsx","../src/components/ui/card.tsx","../src/lib/format.ts"],"sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\n/**\n * 合并 className:tailwind-merge 负责消解冲突,clsx 负责条件拼接。\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"@/lib/cn\"\nimport { Slot } from \"radix-ui\"\n\nconst badgeVariants = cva(\n \"inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a&]:hover:bg-primary/90\",\n secondary:\n \"bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90\",\n destructive:\n \"bg-destructive text-destructive-foreground focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90\",\n outline:\n \"border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n ghost: \"[a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 [a&]:hover:underline\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Badge({\n className,\n variant = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"span\"> &\n VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot.Root : \"span\"\n\n return (\n <Comp\n data-slot=\"badge\"\n data-variant={variant}\n className={cn(badgeVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nexport { Badge, badgeVariants }\n","import * as React from \"react\"\nimport { cn } from \"@/lib/cn\"\n\nfunction Card({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card\"\n className={cn(\n \"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-6\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\"flex items-center px-6 [.border-t]:pt-6\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n","import { formatDuration, formatTimecode, usToSec } from '@cut-workbench/core'\n\nexport { formatDuration, formatTimecode }\n\n/** 字节数 → 人类可读 */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n const units = ['KB', 'MB', 'GB']\n let value = bytes / 1024\n let i = 0\n while (value >= 1024 && i < units.length - 1) {\n value /= 1024\n i += 1\n }\n return `${value.toFixed(value >= 100 ? 0 : 1)} ${units[i]}`\n}\n\n/** 像素尺寸 → `1920×1080` */\nexport function formatResolution(width: number, height: number): string {\n if (!width || !height) return '—'\n return `${width}×${height}`\n}\n\n/** 秒数 → `12.3s` */\nexport function formatElapsed(seconds: number): string {\n if (seconds < 60) return `${seconds.toFixed(1)}s`\n const m = Math.floor(seconds / 60)\n const s = Math.round(seconds % 60)\n return `${m}m ${s}s`\n}\n\n/** 微秒 → 秒(保留一位小数,用于表单展示) */\nexport function formatSeconds(us: number): string {\n return usToSec(us).toFixed(2)\n}\n\n/** 百分比 0~1 → `42%` */\nexport function formatPercent(ratio: number): string {\n return `${Math.round(ratio * 100)}%`\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,SAAgB,GAAG,GAAG,QAAsB;CAC1C,QAAA,GAAOA,eAAAA,QAAAA,EAAAA,GAAQ,KAAA,KAAA,CAAK,MAAM,CAAC;AAC7B;;ACHA,IAAM,iBAAA,GAAgBC,yBAAAA,IAAAA,CACpB,uaACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,WACE;EACF,aACE;EACF,SACE;EACF,OAAO;EACP,MAAM;CACR,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CACF;AAEA,SAAS,MAAM,EACb,WACA,UAAU,WACV,UAAU,OACV,GAAG,SAEyD;CAC5D,MAAM,OAAO,UAAUC,SAAAA,KAAK,OAAO;CAEnC,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;EACE,aAAU;EACV,gBAAc;EACd,WAAW,GAAG,cAAc,EAAE,QAAQ,CAAC,GAAG,SAAS;EACnD,GAAI;CACL,CAAA;AAEL;;ACzCA,SAAS,KAAK,EAAE,WAAW,GAAG,SAAsC;CAClE,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,qFACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,GAAG,SAAsC;CACxE,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,4JACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,UAAU,EAAE,WAAW,GAAG,SAAsC;CACvE,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,8BAA8B,SAAS;EACrD,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,gBAAgB,EAAE,WAAW,GAAG,SAAsC;CAC7E,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,iCAAiC,SAAS;EACxD,GAAI;CACL,CAAA;AAEL;AAeA,SAAS,YAAY,EAAE,WAAW,GAAG,SAAsC;CACzE,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,QAAQ,SAAS;EAC/B,GAAI;CACL,CAAA;AAEL;;;ACjEA,SAAgB,YAAY,OAAuB;CACjD,IAAI,QAAQ,MAAM,OAAO,GAAG,MAAM;CAClC,MAAM,QAAQ;EAAC;EAAM;EAAM;CAAI;CAC/B,IAAI,QAAQ,QAAQ;CACpB,IAAI,IAAI;CACR,OAAO,SAAS,QAAQ,IAAI,MAAM,SAAS,GAAG;EAC5C,SAAS;EACT,KAAK;CACP;CACA,OAAO,GAAG,MAAM,QAAQ,SAAS,MAAM,IAAI,CAAC,EAAE,GAAG,MAAM;AACzD;;AAGA,SAAgB,iBAAiB,OAAe,QAAwB;CACtE,IAAI,CAAC,SAAS,CAAC,QAAQ,OAAO;CAC9B,OAAO,GAAG,MAAM,GAAG;AACrB;;AAGA,SAAgB,cAAc,SAAyB;CACrD,IAAI,UAAU,IAAI,OAAO,GAAG,QAAQ,QAAQ,CAAC,EAAE;CAG/C,OAAO,GAFG,KAAK,MAAM,UAAU,EAErB,EAAE,IADF,KAAK,MAAM,UAAU,EACf,EAAE;AACpB;;AAGA,SAAgB,cAAc,IAAoB;CAChD,QAAA,GAAOC,oBAAAA,QAAAA,CAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC;AAC9B;;AAGA,SAAgB,cAAc,OAAuB;CACnD,OAAO,GAAG,KAAK,MAAM,QAAQ,GAAG,EAAE;AACpC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import "react";
|
|
2
|
+
import { formatDuration, usToSec } from "@cut-workbench/core";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
import { twMerge } from "tailwind-merge";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
import { cva } from "class-variance-authority";
|
|
7
|
+
import { Slot } from "radix-ui";
|
|
8
|
+
// src/lib/cn.ts
|
|
9
|
+
/**
|
|
10
|
+
* 合并 className:tailwind-merge 负责消解冲突,clsx 负责条件拼接。
|
|
11
|
+
*/
|
|
12
|
+
function cn(...inputs) {
|
|
13
|
+
return twMerge(clsx(inputs));
|
|
14
|
+
}
|
|
15
|
+
// src/components/ui/badge.tsx
|
|
16
|
+
var badgeVariants = cva("inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3", {
|
|
17
|
+
variants: { variant: {
|
|
18
|
+
default: "bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
|
19
|
+
secondary: "bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
|
20
|
+
destructive: "bg-destructive text-destructive-foreground focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90",
|
|
21
|
+
outline: "border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
|
22
|
+
ghost: "[a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
|
23
|
+
link: "text-primary underline-offset-4 [a&]:hover:underline"
|
|
24
|
+
} },
|
|
25
|
+
defaultVariants: { variant: "default" }
|
|
26
|
+
});
|
|
27
|
+
function Badge({ className, variant = "default", asChild = false, ...props }) {
|
|
28
|
+
const Comp = asChild ? Slot.Root : "span";
|
|
29
|
+
return /* @__PURE__ */ jsx(Comp, {
|
|
30
|
+
"data-slot": "badge",
|
|
31
|
+
"data-variant": variant,
|
|
32
|
+
className: cn(badgeVariants({ variant }), className),
|
|
33
|
+
...props
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
// src/components/ui/card.tsx
|
|
37
|
+
function Card({ className, ...props }) {
|
|
38
|
+
return /* @__PURE__ */ jsx("div", {
|
|
39
|
+
"data-slot": "card",
|
|
40
|
+
className: cn("flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm", className),
|
|
41
|
+
...props
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function CardHeader({ className, ...props }) {
|
|
45
|
+
return /* @__PURE__ */ jsx("div", {
|
|
46
|
+
"data-slot": "card-header",
|
|
47
|
+
className: cn("@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6", className),
|
|
48
|
+
...props
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function CardTitle({ className, ...props }) {
|
|
52
|
+
return /* @__PURE__ */ jsx("div", {
|
|
53
|
+
"data-slot": "card-title",
|
|
54
|
+
className: cn("leading-none font-semibold", className),
|
|
55
|
+
...props
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function CardDescription({ className, ...props }) {
|
|
59
|
+
return /* @__PURE__ */ jsx("div", {
|
|
60
|
+
"data-slot": "card-description",
|
|
61
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
62
|
+
...props
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function CardContent({ className, ...props }) {
|
|
66
|
+
return /* @__PURE__ */ jsx("div", {
|
|
67
|
+
"data-slot": "card-content",
|
|
68
|
+
className: cn("px-6", className),
|
|
69
|
+
...props
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
// src/lib/format.ts
|
|
73
|
+
/** 字节数 → 人类可读 */
|
|
74
|
+
function formatBytes(bytes) {
|
|
75
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
76
|
+
const units = [
|
|
77
|
+
"KB",
|
|
78
|
+
"MB",
|
|
79
|
+
"GB"
|
|
80
|
+
];
|
|
81
|
+
let value = bytes / 1024;
|
|
82
|
+
let i = 0;
|
|
83
|
+
while (value >= 1024 && i < units.length - 1) {
|
|
84
|
+
value /= 1024;
|
|
85
|
+
i += 1;
|
|
86
|
+
}
|
|
87
|
+
return `${value.toFixed(value >= 100 ? 0 : 1)} ${units[i]}`;
|
|
88
|
+
}
|
|
89
|
+
/** 像素尺寸 → `1920×1080` */
|
|
90
|
+
function formatResolution(width, height) {
|
|
91
|
+
if (!width || !height) return "—";
|
|
92
|
+
return `${width}×${height}`;
|
|
93
|
+
}
|
|
94
|
+
/** 秒数 → `12.3s` */
|
|
95
|
+
function formatElapsed(seconds) {
|
|
96
|
+
if (seconds < 60) return `${seconds.toFixed(1)}s`;
|
|
97
|
+
return `${Math.floor(seconds / 60)}m ${Math.round(seconds % 60)}s`;
|
|
98
|
+
}
|
|
99
|
+
/** 微秒 → 秒(保留一位小数,用于表单展示) */
|
|
100
|
+
function formatSeconds(us) {
|
|
101
|
+
return usToSec(us).toFixed(2);
|
|
102
|
+
}
|
|
103
|
+
/** 百分比 0~1 → `42%` */
|
|
104
|
+
function formatPercent(ratio) {
|
|
105
|
+
return `${Math.round(ratio * 100)}%`;
|
|
106
|
+
}
|
|
107
|
+
export { formatResolution as a, CardContent as c, CardTitle as d, Badge as f, formatPercent as i, CardDescription as l, formatDuration as n, formatSeconds as o, cn as p, formatElapsed as r, Card as s, formatBytes as t, CardHeader as u };
|
|
108
|
+
|
|
109
|
+
//# sourceMappingURL=format-CV2aoZZC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-CV2aoZZC.js","names":[],"sources":["../src/lib/cn.ts","../src/components/ui/badge.tsx","../src/components/ui/card.tsx","../src/lib/format.ts"],"sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\n/**\n * 合并 className:tailwind-merge 负责消解冲突,clsx 负责条件拼接。\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"@/lib/cn\"\nimport { Slot } from \"radix-ui\"\n\nconst badgeVariants = cva(\n \"inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a&]:hover:bg-primary/90\",\n secondary:\n \"bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90\",\n destructive:\n \"bg-destructive text-destructive-foreground focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90\",\n outline:\n \"border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n ghost: \"[a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 [a&]:hover:underline\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Badge({\n className,\n variant = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"span\"> &\n VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot.Root : \"span\"\n\n return (\n <Comp\n data-slot=\"badge\"\n data-variant={variant}\n className={cn(badgeVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nexport { Badge, badgeVariants }\n","import * as React from \"react\"\nimport { cn } from \"@/lib/cn\"\n\nfunction Card({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card\"\n className={cn(\n \"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-6\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\"flex items-center px-6 [.border-t]:pt-6\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n","import { formatDuration, formatTimecode, usToSec } from '@cut-workbench/core'\n\nexport { formatDuration, formatTimecode }\n\n/** 字节数 → 人类可读 */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n const units = ['KB', 'MB', 'GB']\n let value = bytes / 1024\n let i = 0\n while (value >= 1024 && i < units.length - 1) {\n value /= 1024\n i += 1\n }\n return `${value.toFixed(value >= 100 ? 0 : 1)} ${units[i]}`\n}\n\n/** 像素尺寸 → `1920×1080` */\nexport function formatResolution(width: number, height: number): string {\n if (!width || !height) return '—'\n return `${width}×${height}`\n}\n\n/** 秒数 → `12.3s` */\nexport function formatElapsed(seconds: number): string {\n if (seconds < 60) return `${seconds.toFixed(1)}s`\n const m = Math.floor(seconds / 60)\n const s = Math.round(seconds % 60)\n return `${m}m ${s}s`\n}\n\n/** 微秒 → 秒(保留一位小数,用于表单展示) */\nexport function formatSeconds(us: number): string {\n return usToSec(us).toFixed(2)\n}\n\n/** 百分比 0~1 → `42%` */\nexport function formatPercent(ratio: number): string {\n return `${Math.round(ratio * 100)}%`\n}\n"],"mappings":";;;;;;;;;;;AAMA,SAAgB,GAAG,GAAG,QAAsB;CAC1C,OAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;;ACHA,IAAM,gBAAgB,IACpB,uaACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,WACE;EACF,aACE;EACF,SACE;EACF,OAAO;EACP,MAAM;CACR,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CACF;AAEA,SAAS,MAAM,EACb,WACA,UAAU,WACV,UAAU,OACV,GAAG,SAEyD;CAC5D,MAAM,OAAO,UAAU,KAAK,OAAO;CAEnC,OACE,oBAAC,MAAD;EACE,aAAU;EACV,gBAAc;EACd,WAAW,GAAG,cAAc,EAAE,QAAQ,CAAC,GAAG,SAAS;EACnD,GAAI;CACL,CAAA;AAEL;;ACzCA,SAAS,KAAK,EAAE,WAAW,GAAG,SAAsC;CAClE,OACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,qFACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,GAAG,SAAsC;CACxE,OACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,4JACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,UAAU,EAAE,WAAW,GAAG,SAAsC;CACvE,OACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,8BAA8B,SAAS;EACrD,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,gBAAgB,EAAE,WAAW,GAAG,SAAsC;CAC7E,OACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,iCAAiC,SAAS;EACxD,GAAI;CACL,CAAA;AAEL;AAeA,SAAS,YAAY,EAAE,WAAW,GAAG,SAAsC;CACzE,OACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,QAAQ,SAAS;EAC/B,GAAI;CACL,CAAA;AAEL;;;ACjEA,SAAgB,YAAY,OAAuB;CACjD,IAAI,QAAQ,MAAM,OAAO,GAAG,MAAM;CAClC,MAAM,QAAQ;EAAC;EAAM;EAAM;CAAI;CAC/B,IAAI,QAAQ,QAAQ;CACpB,IAAI,IAAI;CACR,OAAO,SAAS,QAAQ,IAAI,MAAM,SAAS,GAAG;EAC5C,SAAS;EACT,KAAK;CACP;CACA,OAAO,GAAG,MAAM,QAAQ,SAAS,MAAM,IAAI,CAAC,EAAE,GAAG,MAAM;AACzD;;AAGA,SAAgB,iBAAiB,OAAe,QAAwB;CACtE,IAAI,CAAC,SAAS,CAAC,QAAQ,OAAO;CAC9B,OAAO,GAAG,MAAM,GAAG;AACrB;;AAGA,SAAgB,cAAc,SAAyB;CACrD,IAAI,UAAU,IAAI,OAAO,GAAG,QAAQ,QAAQ,CAAC,EAAE;CAG/C,OAAO,GAFG,KAAK,MAAM,UAAU,EAErB,EAAE,IADF,KAAK,MAAM,UAAU,EACf,EAAE;AACpB;;AAGA,SAAgB,cAAc,IAAoB;CAChD,OAAO,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC;AAC9B;;AAGA,SAAgB,cAAc,OAAuB;CACnD,OAAO,GAAG,KAAK,MAAM,QAAQ,GAAG,EAAE;AACpC"}
|