@nebutra/ui 2.0.0 → 3.0.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/dist/{canonical-Bf4czR2u.d.ts → canonical-DEhT4VfS.d.ts} +71 -120
- package/dist/card-DunB1gKE.d.ts +105 -0
- package/dist/components/index.d.ts +33 -4
- package/dist/components/index.js +225 -89
- package/dist/components/index.js.map +1 -1
- package/dist/editorial/index.d.ts +2 -2
- package/dist/editorial/index.js +75 -1
- package/dist/editorial/index.js.map +1 -1
- package/dist/empty-state-bmfHCOuN.d.ts +86 -0
- package/dist/hooks/index.d.ts +18 -1
- package/dist/hooks/index.js +120 -5
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/layout/index.d.ts +17 -58
- package/dist/layout/index.js +366 -126
- package/dist/layout/index.js.map +1 -1
- package/dist/layouts/index.d.ts +1 -1
- package/dist/layouts/index.js +89 -15
- package/dist/layouts/index.js.map +1 -1
- package/dist/patterns/index.d.ts +38 -44
- package/dist/patterns/index.js +470 -278
- package/dist/patterns/index.js.map +1 -1
- package/dist/primitives/canonical.d.ts +3 -1
- package/dist/primitives/canonical.js +495 -231
- package/dist/primitives/canonical.js.map +1 -1
- package/dist/primitives/index.d.ts +90 -62
- package/dist/primitives/index.js +1129 -1185
- package/dist/primitives/index.js.map +1 -1
- package/dist/tailwind.preset.d.ts +32 -32
- package/dist/tailwind.preset.js +24 -20
- package/dist/tailwind.preset.js.map +1 -1
- package/dist/theme/index.d.ts +1 -110
- package/dist/typography/fonts.css +8 -16
- package/dist/typography/index.d.ts +29 -45
- package/dist/typography/index.js +26 -14
- package/dist/typography/index.js.map +1 -1
- package/dist/utils/index.d.ts +18 -12
- package/dist/utils/index.js +94 -18
- package/dist/utils/index.js.map +1 -1
- package/package.json +6 -10
- package/src/typography/fonts.css +8 -16
- package/dist/styles/brand-override.css +0 -61
- package/src/styles/brand-override.css +0 -61
package/dist/patterns/index.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
3
|
+
import { extendTailwindMerge } from 'tailwind-merge';
|
|
4
|
+
import { jsxs, jsx, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
5
|
+
import { cva } from 'class-variance-authority';
|
|
6
|
+
import * as React10 from 'react';
|
|
6
7
|
import { useState, useRef, useCallback, useMemo, Fragment, isValidElement } from 'react';
|
|
7
8
|
import { Check, Copy, Pencil, FileText, TextBold, TextItalic, Code, Hash, ListUnordered, Link, Image, ChevronUp, ChevronDown, Calendar, Eye, Bookmark, StarFill, Share, Flag, ChevronUpDown, Pin, ChevronRight, MoreHorizontal } from '@nebutra/icons';
|
|
8
|
-
import { cva } from 'class-variance-authority';
|
|
9
9
|
import { Menu } from '@base-ui/react/menu';
|
|
10
10
|
import { colors } from '@nebutra/brand';
|
|
11
|
+
import { tokenColor, fontStack } from '@nebutra/tokens/values';
|
|
11
12
|
import { Tabs as Tabs$1 } from '@base-ui/react/tabs';
|
|
12
13
|
import { Tooltip as Tooltip$1 } from '@base-ui/react/tooltip';
|
|
13
14
|
import ReactMarkdown from 'react-markdown';
|
|
@@ -17,6 +18,80 @@ import { Avatar as Avatar$1 } from '@base-ui/react/avatar';
|
|
|
17
18
|
import { useReducedMotion, AnimatePresence, motion } from 'framer-motion';
|
|
18
19
|
|
|
19
20
|
// src/utils/cn.ts
|
|
21
|
+
|
|
22
|
+
// src/utils/tw-merge-theme.generated.ts
|
|
23
|
+
var TW_MERGE_THEME = {
|
|
24
|
+
breakpoint: ["3xl", "shell", "tight", "xs"],
|
|
25
|
+
container: ["content", "text", "wide"],
|
|
26
|
+
ease: ["brand", "in", "in-out", "out", "spring"],
|
|
27
|
+
font: ["cn", "display", "heading", "mono", "sans"],
|
|
28
|
+
leading: ["display", "heading"],
|
|
29
|
+
radius: ["2xl", "3xl", "button", "card", "full", "lg", "md", "none", "panel", "sm", "xl", "xs"],
|
|
30
|
+
shadow: [
|
|
31
|
+
"2xl",
|
|
32
|
+
"ambient-glow",
|
|
33
|
+
"ambient-lg",
|
|
34
|
+
"ambient-md",
|
|
35
|
+
"ambient-sm",
|
|
36
|
+
"brand",
|
|
37
|
+
"brand-lg",
|
|
38
|
+
"glass-lg",
|
|
39
|
+
"glass-md",
|
|
40
|
+
"glass-sm",
|
|
41
|
+
"glow-accent",
|
|
42
|
+
"glow-accent-lg",
|
|
43
|
+
"glow-accent-sm",
|
|
44
|
+
"glow-primary",
|
|
45
|
+
"lg",
|
|
46
|
+
"md",
|
|
47
|
+
"sheen",
|
|
48
|
+
"sm",
|
|
49
|
+
"xl",
|
|
50
|
+
"xs"
|
|
51
|
+
],
|
|
52
|
+
text: [
|
|
53
|
+
"2xl",
|
|
54
|
+
"2xs",
|
|
55
|
+
"3xl",
|
|
56
|
+
"4xl",
|
|
57
|
+
"5xl",
|
|
58
|
+
"6xl",
|
|
59
|
+
"7xl",
|
|
60
|
+
"8xl",
|
|
61
|
+
"9xl",
|
|
62
|
+
"base",
|
|
63
|
+
"body",
|
|
64
|
+
"display",
|
|
65
|
+
"label",
|
|
66
|
+
"lg",
|
|
67
|
+
"meta",
|
|
68
|
+
"sm",
|
|
69
|
+
"ui",
|
|
70
|
+
"xl",
|
|
71
|
+
"xs"
|
|
72
|
+
],
|
|
73
|
+
tracking: ["display", "heading", "label", "tight"]
|
|
74
|
+
};
|
|
75
|
+
var TW_MERGE_CLASS_GROUPS = {
|
|
76
|
+
duration: [{ duration: ["cinematic", "flow", "micro", "reveal"] }]
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// src/utils/cn.ts
|
|
80
|
+
var twMerge = extendTailwindMerge({
|
|
81
|
+
extend: {
|
|
82
|
+
theme: Object.fromEntries(
|
|
83
|
+
Object.entries(TW_MERGE_THEME).map(([key, values]) => [key, [...values]])
|
|
84
|
+
),
|
|
85
|
+
classGroups: Object.fromEntries(
|
|
86
|
+
Object.entries(TW_MERGE_CLASS_GROUPS).map(([key, groups]) => [
|
|
87
|
+
key,
|
|
88
|
+
groups.map(
|
|
89
|
+
(group) => Object.fromEntries(Object.entries(group).map(([k, v]) => [k, [...v]]))
|
|
90
|
+
)
|
|
91
|
+
])
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
});
|
|
20
95
|
function cn(...inputs) {
|
|
21
96
|
return twMerge(clsx(inputs));
|
|
22
97
|
}
|
|
@@ -129,108 +204,120 @@ function ArtifactShiftCardFooter({ className, ...props }) {
|
|
|
129
204
|
}
|
|
130
205
|
);
|
|
131
206
|
}
|
|
132
|
-
var
|
|
133
|
-
var
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
ref,
|
|
152
|
-
className: cn(
|
|
153
|
-
"rounded-[var(--radius-xl)] transition-[background-color,border-color,box-shadow,color] duration-micro",
|
|
154
|
-
variantStyles[variant],
|
|
155
|
-
paddingMap[padding],
|
|
156
|
-
className
|
|
157
|
-
),
|
|
158
|
-
...props,
|
|
159
|
-
children
|
|
207
|
+
var cardVariants = cva(
|
|
208
|
+
"rounded-[var(--radius-card,var(--radius-lg))] text-card-foreground transition-[box-shadow,background-color] duration-micro",
|
|
209
|
+
{
|
|
210
|
+
variants: {
|
|
211
|
+
variant: {
|
|
212
|
+
default: "bg-card shadow-[var(--elevation-card)] ring-1 ring-[var(--edge-soft)]",
|
|
213
|
+
elevated: "bg-card shadow-ambient-md ring-1 ring-[var(--edge-soft)]",
|
|
214
|
+
outline: "bg-transparent ring-1 ring-border",
|
|
215
|
+
ghost: "bg-transparent"
|
|
216
|
+
},
|
|
217
|
+
padding: {
|
|
218
|
+
none: "",
|
|
219
|
+
sm: "p-4",
|
|
220
|
+
md: "p-6",
|
|
221
|
+
lg: "p-8"
|
|
222
|
+
},
|
|
223
|
+
interactive: {
|
|
224
|
+
true: "cursor-pointer hover:shadow-ambient-md",
|
|
225
|
+
false: ""
|
|
160
226
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
);
|
|
164
|
-
CardRoot.displayName = "Card";
|
|
165
|
-
var CardHeader = React.forwardRef(
|
|
166
|
-
({ className, spacing: gap = "md", children, ...props }, ref) => {
|
|
167
|
-
const gapMap = { sm: "gap-2", md: "gap-3", lg: "gap-4" };
|
|
168
|
-
return /* @__PURE__ */ jsx("div", { ref, className: cn("flex items-start", gapMap[gap], className), ...props, children });
|
|
169
|
-
}
|
|
170
|
-
);
|
|
171
|
-
CardHeader.displayName = "Card.Header";
|
|
172
|
-
var CardBody = React.forwardRef(
|
|
173
|
-
({ className, children, ...props }, ref) => {
|
|
174
|
-
return /* @__PURE__ */ jsx("div", { ref, className: cn("mt-4", className), ...props, children });
|
|
175
|
-
}
|
|
176
|
-
);
|
|
177
|
-
CardBody.displayName = "Card.Body";
|
|
178
|
-
var CardFooter = React.forwardRef(
|
|
179
|
-
({ className, children, ...props }, ref) => {
|
|
180
|
-
return /* @__PURE__ */ jsx("div", { ref, className: cn("mt-6 pt-4 border-t border-border/50", className), ...props, children });
|
|
227
|
+
},
|
|
228
|
+
defaultVariants: { variant: "default", padding: "none", interactive: false }
|
|
181
229
|
}
|
|
182
230
|
);
|
|
183
|
-
|
|
184
|
-
var
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
sizeMap[size],
|
|
198
|
-
className
|
|
199
|
-
),
|
|
200
|
-
...props,
|
|
201
|
-
children
|
|
202
|
-
}
|
|
203
|
-
);
|
|
231
|
+
var CardPaddedContext = React10.createContext(false);
|
|
232
|
+
var CardRoot = ({
|
|
233
|
+
className,
|
|
234
|
+
variant,
|
|
235
|
+
padding = "none",
|
|
236
|
+
interactive,
|
|
237
|
+
ref,
|
|
238
|
+
...props
|
|
239
|
+
}) => /* @__PURE__ */ jsx(CardPaddedContext.Provider, { value: padding !== "none", children: /* @__PURE__ */ jsx(
|
|
240
|
+
"div",
|
|
241
|
+
{
|
|
242
|
+
ref,
|
|
243
|
+
className: cn(cardVariants({ variant, padding, interactive }), className),
|
|
244
|
+
...props
|
|
204
245
|
}
|
|
205
|
-
);
|
|
206
|
-
|
|
207
|
-
var
|
|
208
|
-
|
|
209
|
-
|
|
246
|
+
) });
|
|
247
|
+
CardRoot.displayName = "Card";
|
|
248
|
+
var CardHeader = ({ className, ref, ...props }) => {
|
|
249
|
+
const padded = React10.use(CardPaddedContext);
|
|
250
|
+
return /* @__PURE__ */ jsx(
|
|
251
|
+
"div",
|
|
252
|
+
{
|
|
253
|
+
ref,
|
|
254
|
+
className: cn("flex flex-col gap-1.5", !padded && "p-6", className),
|
|
255
|
+
...props
|
|
256
|
+
}
|
|
257
|
+
);
|
|
258
|
+
};
|
|
259
|
+
CardHeader.displayName = "CardHeader";
|
|
260
|
+
var CardTitle = ({ className, as: Tag = "h3", ref, ...props }) => /* @__PURE__ */ jsx(
|
|
261
|
+
Tag,
|
|
262
|
+
{
|
|
263
|
+
ref,
|
|
264
|
+
className: cn("text-lg font-semibold leading-tight tracking-tight text-foreground", className),
|
|
265
|
+
...props
|
|
210
266
|
}
|
|
211
267
|
);
|
|
212
|
-
CardTitle.displayName = "
|
|
213
|
-
var CardDescription =
|
|
214
|
-
|
|
215
|
-
|
|
268
|
+
CardTitle.displayName = "CardTitle";
|
|
269
|
+
var CardDescription = ({ className, as: Tag = "p", ref, ...props }) => React10.createElement(Tag, {
|
|
270
|
+
ref,
|
|
271
|
+
className: cn("text-sm leading-relaxed text-muted-foreground", className),
|
|
272
|
+
...props
|
|
273
|
+
});
|
|
274
|
+
CardDescription.displayName = "CardDescription";
|
|
275
|
+
var CardContent = ({ className, ref, ...props }) => {
|
|
276
|
+
const padded = React10.use(CardPaddedContext);
|
|
277
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn(padded ? "mt-4 first:mt-0" : "p-6 pt-0", className), ...props });
|
|
278
|
+
};
|
|
279
|
+
CardContent.displayName = "CardContent";
|
|
280
|
+
var CardFooter = ({ className, ref, ...props }) => {
|
|
281
|
+
const padded = React10.use(CardPaddedContext);
|
|
282
|
+
return /* @__PURE__ */ jsx(
|
|
283
|
+
"div",
|
|
216
284
|
{
|
|
217
285
|
ref,
|
|
218
|
-
className: cn(
|
|
286
|
+
className: cn(
|
|
287
|
+
"flex items-center",
|
|
288
|
+
padded ? "mt-6 border-t border-border/50 pt-4 first:mt-0" : "p-6 pt-0",
|
|
289
|
+
className
|
|
290
|
+
),
|
|
219
291
|
...props
|
|
220
|
-
}
|
|
221
|
-
children
|
|
292
|
+
}
|
|
222
293
|
);
|
|
223
|
-
}
|
|
224
|
-
|
|
294
|
+
};
|
|
295
|
+
CardFooter.displayName = "CardFooter";
|
|
296
|
+
var iconSize = { sm: "size-8", md: "size-10", lg: "size-12" };
|
|
297
|
+
var CardIcon = ({ className, size = "md", ref, ...props }) => /* @__PURE__ */ jsx(
|
|
298
|
+
"div",
|
|
299
|
+
{
|
|
300
|
+
ref,
|
|
301
|
+
className: cn(
|
|
302
|
+
"flex shrink-0 items-center justify-center rounded-[var(--radius-lg)] bg-muted/50",
|
|
303
|
+
iconSize[size],
|
|
304
|
+
className
|
|
305
|
+
),
|
|
306
|
+
...props
|
|
307
|
+
}
|
|
308
|
+
);
|
|
309
|
+
CardIcon.displayName = "CardIcon";
|
|
225
310
|
var Card = Object.assign(CardRoot, {
|
|
226
311
|
Header: CardHeader,
|
|
227
|
-
Body: CardBody,
|
|
228
|
-
Footer: CardFooter,
|
|
229
|
-
Icon: CardIcon,
|
|
230
312
|
Title: CardTitle,
|
|
231
|
-
Description: CardDescription
|
|
313
|
+
Description: CardDescription,
|
|
314
|
+
Content: CardContent,
|
|
315
|
+
Body: CardContent,
|
|
316
|
+
Footer: CardFooter,
|
|
317
|
+
Icon: CardIcon
|
|
232
318
|
});
|
|
233
|
-
var
|
|
319
|
+
var CardBody = CardContent;
|
|
320
|
+
var CommandBox = React10.forwardRef(
|
|
234
321
|
({
|
|
235
322
|
className,
|
|
236
323
|
command,
|
|
@@ -240,8 +327,8 @@ var CommandBox = React.forwardRef(
|
|
|
240
327
|
onCopy,
|
|
241
328
|
...props
|
|
242
329
|
}, ref) => {
|
|
243
|
-
const [copied, setCopied] =
|
|
244
|
-
const handleCopy =
|
|
330
|
+
const [copied, setCopied] = React10.useState(false);
|
|
331
|
+
const handleCopy = React10.useCallback(async () => {
|
|
245
332
|
try {
|
|
246
333
|
await navigator.clipboard.writeText(command);
|
|
247
334
|
setCopied(true);
|
|
@@ -253,7 +340,7 @@ var CommandBox = React.forwardRef(
|
|
|
253
340
|
}
|
|
254
341
|
}
|
|
255
342
|
}, [command, onCopy]);
|
|
256
|
-
const
|
|
343
|
+
const variantStyles2 = {
|
|
257
344
|
default: "bg-muted border border-border rounded-[var(--radius-lg)]",
|
|
258
345
|
minimal: "bg-background border border-border rounded-[var(--radius-md)]",
|
|
259
346
|
pill: "bg-muted border border-border rounded-full"
|
|
@@ -266,7 +353,7 @@ var CommandBox = React.forwardRef(
|
|
|
266
353
|
ref,
|
|
267
354
|
className: cn(
|
|
268
355
|
"group relative flex items-center gap-3 px-4 py-2.5 font-mono text-sm cursor-pointer transition-colors hover:bg-muted",
|
|
269
|
-
|
|
356
|
+
variantStyles2[variant],
|
|
270
357
|
className
|
|
271
358
|
),
|
|
272
359
|
onClick: handleCopy,
|
|
@@ -281,14 +368,14 @@ var CommandBox = React.forwardRef(
|
|
|
281
368
|
"aria-label": `Copy command: ${command}`,
|
|
282
369
|
...props,
|
|
283
370
|
children: [
|
|
284
|
-
/* @__PURE__ */ jsx("span", { className: "text-
|
|
371
|
+
/* @__PURE__ */ jsx("span", { className: "text-success-strong shrink-0 select-none", children: prefix }),
|
|
285
372
|
/* @__PURE__ */ jsx("span", { className: "flex-1 text-muted-foreground truncate", children: command }),
|
|
286
373
|
showCopyButton && /* @__PURE__ */ jsx(
|
|
287
374
|
"span",
|
|
288
375
|
{
|
|
289
376
|
className: cn(
|
|
290
377
|
"shrink-0 text-xs transition-colors",
|
|
291
|
-
copied ? "text-
|
|
378
|
+
copied ? "text-success-strong" : "text-muted-foreground group-hover:text-muted-foreground"
|
|
292
379
|
),
|
|
293
380
|
children: copied ? /* @__PURE__ */ jsx(CopiedIcon, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx(CopyIcon, { className: "w-4 h-4" })
|
|
294
381
|
}
|
|
@@ -297,7 +384,7 @@ var CommandBox = React.forwardRef(
|
|
|
297
384
|
"span",
|
|
298
385
|
{
|
|
299
386
|
className: cn(
|
|
300
|
-
"absolute -top-8 left-1/2 -translate-x-1/2 px-2 py-1 text-xs rounded bg-
|
|
387
|
+
"absolute -top-8 left-1/2 -translate-x-1/2 px-2 py-1 text-xs rounded bg-popover text-popover-foreground opacity-0 transition-opacity pointer-events-none",
|
|
301
388
|
"group-hover:opacity-100",
|
|
302
389
|
copied && "opacity-100"
|
|
303
390
|
),
|
|
@@ -351,8 +438,8 @@ function CopiedIcon({ className }) {
|
|
|
351
438
|
var metricToneClasses = {
|
|
352
439
|
neutral: "bg-muted/70 text-muted-foreground ring-border",
|
|
353
440
|
blue: "bg-info/10 text-info ring-info/20",
|
|
354
|
-
green: "bg-success/10 text-success ring-success/20",
|
|
355
|
-
amber: "bg-warning/10 text-warning ring-warning/20"
|
|
441
|
+
green: "bg-success/10 text-success-strong ring-success/20",
|
|
442
|
+
amber: "bg-warning/10 text-warning-strong ring-warning/20"
|
|
356
443
|
};
|
|
357
444
|
function DashboardCommandSurface({
|
|
358
445
|
status,
|
|
@@ -367,25 +454,27 @@ function DashboardCommandSurface({
|
|
|
367
454
|
{
|
|
368
455
|
"data-pattern": "nebutra-dashboard-command",
|
|
369
456
|
className: cn(
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
457
|
+
// Same surface rails as Card: --radius-card, --edge-soft hairline and
|
|
458
|
+
// --elevation-card, so a Brand Package retargets a command header and a
|
|
459
|
+
// card together. The gradient hairline + radial wash that used to sit
|
|
460
|
+
// here were decoration no language could retarget.
|
|
461
|
+
"rounded-[var(--radius-card)] bg-card p-4 text-card-foreground shadow-[0_0_0_1px_var(--edge-soft),var(--elevation-card)]",
|
|
373
462
|
"sm:p-5",
|
|
374
463
|
className
|
|
375
464
|
),
|
|
376
465
|
children: [
|
|
377
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
466
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between", children: [
|
|
378
467
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
379
468
|
status ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
380
|
-
/* @__PURE__ */ jsx("span", { className: "size-1.5 rounded-full bg-success
|
|
381
|
-
/* @__PURE__ */ jsx("p", { className: "text-
|
|
469
|
+
/* @__PURE__ */ jsx("span", { className: "size-1.5 rounded-full bg-success" }),
|
|
470
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium uppercase tracking-label text-muted-foreground", children: status })
|
|
382
471
|
] }) : null,
|
|
383
|
-
/* @__PURE__ */ jsx("h1", { className: "mt-2 text-2xl font-semibold tracking-
|
|
384
|
-
description ? /* @__PURE__ */ jsx("p", { className: "mt-2 max-w-2xl text-
|
|
472
|
+
/* @__PURE__ */ jsx("h1", { className: "mt-2 text-2xl font-semibold tracking-heading text-card-foreground sm:text-3xl", children: title }),
|
|
473
|
+
description ? /* @__PURE__ */ jsx("p", { className: "mt-2 max-w-2xl text-sm leading-5 text-muted-foreground", children: description }) : null
|
|
385
474
|
] }),
|
|
386
475
|
actions ? /* @__PURE__ */ jsx("div", { className: "flex shrink-0 flex-wrap items-center gap-1.5", children: actions }) : null
|
|
387
476
|
] }),
|
|
388
|
-
children ? /* @__PURE__ */ jsx("div", { className: "
|
|
477
|
+
children ? /* @__PURE__ */ jsx("div", { className: "mt-4", children }) : null
|
|
389
478
|
]
|
|
390
479
|
}
|
|
391
480
|
);
|
|
@@ -404,7 +493,7 @@ function DashboardPanel({
|
|
|
404
493
|
{
|
|
405
494
|
"data-pattern": "nebutra-dashboard-panel",
|
|
406
495
|
className: cn(
|
|
407
|
-
"rounded-[var(--radius-
|
|
496
|
+
"rounded-[var(--radius-card)] bg-card p-3.5 text-card-foreground shadow-[0_0_0_1px_var(--edge-soft),var(--elevation-card)] sm:p-4",
|
|
408
497
|
className
|
|
409
498
|
),
|
|
410
499
|
children: [
|
|
@@ -417,7 +506,7 @@ function DashboardPanel({
|
|
|
417
506
|
),
|
|
418
507
|
children: [
|
|
419
508
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
420
|
-
/* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold
|
|
509
|
+
/* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-card-foreground", children: title }),
|
|
421
510
|
description ? /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs leading-5 text-muted-foreground", children: description }) : null
|
|
422
511
|
] }),
|
|
423
512
|
(meta || action) && /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2 lg:justify-end", children: [
|
|
@@ -446,8 +535,8 @@ function DashboardMetricTile({
|
|
|
446
535
|
{
|
|
447
536
|
"data-pattern": "nebutra-dashboard-metric",
|
|
448
537
|
className: cn(
|
|
449
|
-
"group h-full rounded-[var(--radius-
|
|
450
|
-
"hover:
|
|
538
|
+
"group h-full rounded-[var(--radius-card)] bg-muted/40 p-3 shadow-[0_0_0_1px_var(--edge-soft)] transition-[background-color,box-shadow] duration-micro",
|
|
539
|
+
"hover:bg-muted/65 hover:shadow-[0_0_0_1px_var(--edge-medium)]",
|
|
451
540
|
className
|
|
452
541
|
),
|
|
453
542
|
children: [
|
|
@@ -464,10 +553,10 @@ function DashboardMetricTile({
|
|
|
464
553
|
}
|
|
465
554
|
) : null
|
|
466
555
|
] }),
|
|
467
|
-
/* @__PURE__ */ jsx("p", { className: "mt-2 text-2xl font-semibold tabular-nums
|
|
556
|
+
/* @__PURE__ */ jsx("p", { className: "mt-2 text-2xl font-semibold tabular-nums text-card-foreground", children: value }),
|
|
468
557
|
(detail || source) && /* @__PURE__ */ jsxs("div", { className: "mt-1.5 space-y-0.5 text-xs leading-5 text-muted-foreground", children: [
|
|
469
558
|
detail ? /* @__PURE__ */ jsx("span", { className: "block", children: detail }) : null,
|
|
470
|
-
source ? /* @__PURE__ */ jsx("span", { className: "block text-
|
|
559
|
+
source ? /* @__PURE__ */ jsx("span", { className: "block text-xs text-muted-foreground/70", children: source }) : null
|
|
471
560
|
] })
|
|
472
561
|
]
|
|
473
562
|
}
|
|
@@ -518,8 +607,14 @@ var badgeVariants = cva(
|
|
|
518
607
|
"teal-subtle": "bg-info/10 text-info fill-current border-transparent",
|
|
519
608
|
inverted: "bg-foreground text-background fill-current",
|
|
520
609
|
// Special visual treatments (intentional product design, not brand hex)
|
|
521
|
-
trial:
|
|
522
|
-
|
|
610
|
+
trial: (
|
|
611
|
+
// allow-palette: the trial gradient is fixed and vivid in both themes, so its ink is fixed white
|
|
612
|
+
"bg-gradient-to-br from-trial-start to-trial-end text-white fill-current"
|
|
613
|
+
),
|
|
614
|
+
turbo: (
|
|
615
|
+
// allow-palette: the turbo gradient is fixed and vivid in both themes, so its ink is fixed white
|
|
616
|
+
"bg-gradient-to-br from-turbo-start to-turbo-end text-white fill-current"
|
|
617
|
+
),
|
|
523
618
|
pill: "bg-background text-foreground fill-foreground border-border hover:bg-muted/50 focus-visible:bg-muted/50",
|
|
524
619
|
beta: "border-transparent bg-muted text-muted-foreground",
|
|
525
620
|
new: "border-transparent bg-primary/10 text-primary",
|
|
@@ -584,11 +679,11 @@ function Badge({
|
|
|
584
679
|
label
|
|
585
680
|
] });
|
|
586
681
|
if (asChild) {
|
|
587
|
-
const childArray =
|
|
682
|
+
const childArray = React10.Children.toArray(children);
|
|
588
683
|
const child = childArray.length === 1 ? childArray[0] : null;
|
|
589
|
-
if (
|
|
684
|
+
if (React10.isValidElement(child)) {
|
|
590
685
|
const childProps = child.props;
|
|
591
|
-
return
|
|
686
|
+
return React10.cloneElement(child, {
|
|
592
687
|
...props,
|
|
593
688
|
...childProps,
|
|
594
689
|
"data-slot": "badge",
|
|
@@ -601,7 +696,7 @@ function Badge({
|
|
|
601
696
|
return /* @__PURE__ */ jsx("span", { "data-slot": "badge", className: badgeClassName, ...props, children: renderContent(children) });
|
|
602
697
|
}
|
|
603
698
|
({
|
|
604
|
-
// Nebutra Blue (云毓蓝) — technology & trust
|
|
699
|
+
// Nebutra Blue (云毓蓝) — technology & trust
|
|
605
700
|
blue50: colors.primary[50],
|
|
606
701
|
blue100: colors.primary[100],
|
|
607
702
|
blue200: colors.primary[200],
|
|
@@ -614,7 +709,7 @@ function Badge({
|
|
|
614
709
|
blue800: colors.primary[800],
|
|
615
710
|
blue900: colors.primary[900],
|
|
616
711
|
blue950: colors.primary[950],
|
|
617
|
-
// Nebutra Cyan (云毓青) — data flow & intelligence
|
|
712
|
+
// Nebutra Cyan (云毓青) — data flow & intelligence
|
|
618
713
|
cyan50: colors.accent[50],
|
|
619
714
|
cyan100: colors.accent[100],
|
|
620
715
|
cyan200: colors.accent[200],
|
|
@@ -639,6 +734,13 @@ function Badge({
|
|
|
639
734
|
neutral800: colors.neutral[800],
|
|
640
735
|
neutral900: colors.neutral[900],
|
|
641
736
|
neutral950: colors.neutral[950],
|
|
737
|
+
// deepest — used as dark background
|
|
738
|
+
// Semantic raw colors — VI §Color Specifications. The 500s are the status
|
|
739
|
+
// tokens; the 600 hover steps have no token of their own.
|
|
740
|
+
// NOTE: info = brand blue, not sky/teal
|
|
741
|
+
red500: tokenColor("--status-danger"),
|
|
742
|
+
green500: tokenColor("--status-success"),
|
|
743
|
+
amber500: tokenColor("--status-warning"),
|
|
642
744
|
white: colors.white,
|
|
643
745
|
black: colors.black
|
|
644
746
|
});
|
|
@@ -677,6 +779,18 @@ var primitiveFontSize = {
|
|
|
677
779
|
sm: 14,
|
|
678
780
|
base: 16,
|
|
679
781
|
lg: 18};
|
|
782
|
+
({
|
|
783
|
+
/** Default body/UI stack — Geist with CJK falling through to MiSans */
|
|
784
|
+
sans: fontStack("--font-sans"),
|
|
785
|
+
/** CJK-locale stack (same order as sans, minus Latin-only system faces) */
|
|
786
|
+
cnSans: fontStack("--font-cn"),
|
|
787
|
+
/** Display / hero headlines */
|
|
788
|
+
display: fontStack("--font-display"),
|
|
789
|
+
/** Headings */
|
|
790
|
+
heading: fontStack("--font-heading"),
|
|
791
|
+
/** Code / monospace */
|
|
792
|
+
mono: fontStack("--font-mono")
|
|
793
|
+
});
|
|
680
794
|
var primitiveTransition = {
|
|
681
795
|
duration: {
|
|
682
796
|
// hover, focus, small state changes
|
|
@@ -704,15 +818,15 @@ var overlayClassNames = {
|
|
|
704
818
|
menuSurface: [
|
|
705
819
|
"min-w-32 origin-[var(--transform-origin)] overflow-hidden rounded-[var(--radius-lg)] border border-border/70 bg-popover/95 p-1 text-popover-foreground backdrop-blur-md",
|
|
706
820
|
shadowClasses.xl,
|
|
707
|
-
"outline-none transition-[opacity,transform
|
|
708
|
-
"data-[starting-style]:scale-[0.97] data-[starting-style]:opacity-0 data-
|
|
821
|
+
"outline-none transition-[opacity,transform] duration-[var(--motion-duration-flow)] ease-[var(--ease-brand)]",
|
|
822
|
+
"data-[starting-style]:scale-[0.97] data-[starting-style]:opacity-0 data-ending-style:scale-[0.97] data-ending-style:opacity-0 data-ending-style:duration-[var(--motion-duration-micro)]",
|
|
709
823
|
"motion-reduce:transition-none motion-reduce:data-[starting-style]:transform-none motion-reduce:data-[ending-style]:transform-none"
|
|
710
824
|
].join(" "),
|
|
711
825
|
tooltipSurface: [
|
|
712
826
|
"origin-[var(--transform-origin)] overflow-hidden rounded-[var(--radius-md)] border border-border/70 bg-popover/95 px-3 py-1.5 text-sm text-popover-foreground backdrop-blur-md",
|
|
713
827
|
shadowClasses.md,
|
|
714
|
-
"transition-[opacity,transform
|
|
715
|
-
"data-starting-style:scale-[0.97] data-starting-style:opacity-0 data-ending-style:scale-[0.97] data-ending-style:opacity-0",
|
|
828
|
+
"transition-[opacity,transform] duration-[var(--motion-duration-flow)] ease-[var(--ease-brand)]",
|
|
829
|
+
"data-starting-style:scale-[0.97] data-starting-style:opacity-0 data-ending-style:scale-[0.97] data-ending-style:opacity-0 data-ending-style:duration-[var(--motion-duration-micro)]",
|
|
716
830
|
"data-[instant]:duration-0",
|
|
717
831
|
"motion-reduce:transition-none motion-reduce:data-starting-style:transform-none motion-reduce:data-ending-style:transform-none"
|
|
718
832
|
].join(" ")};
|
|
@@ -727,7 +841,7 @@ var menuHighlightedClassName = "data-[highlighted]:bg-accent data-[highlighted]:
|
|
|
727
841
|
var overlayPrimitiveClassNames = {
|
|
728
842
|
menuSurface: "rounded-[var(--radius-md)] border-border/70 bg-popover/95 shadow-md",
|
|
729
843
|
menuItem: [menuItemBaseClassName, menuHighlightedClassName].join(" ")};
|
|
730
|
-
var DropdownMenuContext =
|
|
844
|
+
var DropdownMenuContext = React10.createContext(null);
|
|
731
845
|
function DropdownMenu({
|
|
732
846
|
open: controlledOpen,
|
|
733
847
|
defaultOpen = false,
|
|
@@ -735,7 +849,7 @@ function DropdownMenu({
|
|
|
735
849
|
children,
|
|
736
850
|
...props
|
|
737
851
|
}) {
|
|
738
|
-
const [uncontrolledOpen, setUncontrolledOpen] =
|
|
852
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React10.useState(defaultOpen);
|
|
739
853
|
const open = controlledOpen ?? uncontrolledOpen;
|
|
740
854
|
function setOpen(nextOpen, eventDetails) {
|
|
741
855
|
if (controlledOpen === void 0) {
|
|
@@ -754,11 +868,11 @@ var DropdownMenuTrigger = ({
|
|
|
754
868
|
ref,
|
|
755
869
|
...props
|
|
756
870
|
}) => {
|
|
757
|
-
const context =
|
|
871
|
+
const context = React10.use(DropdownMenuContext);
|
|
758
872
|
function openFromTrigger() {
|
|
759
873
|
context?.setOpen(true);
|
|
760
874
|
}
|
|
761
|
-
const childRenderElement = asChild &&
|
|
875
|
+
const childRenderElement = asChild && React10.isValidElement(children) ? React10.cloneElement(children, {
|
|
762
876
|
onMouseDown: (event) => {
|
|
763
877
|
children.props.onMouseDown?.(event);
|
|
764
878
|
if (!event.defaultPrevented) {
|
|
@@ -851,11 +965,13 @@ var DropdownMenuSeparator = ({
|
|
|
851
965
|
DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
|
|
852
966
|
var iconToneStyles = {
|
|
853
967
|
neutral: "bg-muted text-muted-foreground",
|
|
854
|
-
blue: "bg-blue-
|
|
855
|
-
cyan: "bg-cyan-
|
|
968
|
+
blue: "bg-blue-3 text-blue-11",
|
|
969
|
+
cyan: "bg-cyan-3 text-cyan-11",
|
|
970
|
+
// allow-palette: categorical hue with no token equivalent (purple/violet has no semantic slot)
|
|
856
971
|
purple: "bg-purple-50 text-purple-700 dark:bg-purple-950/40 dark:text-purple-300",
|
|
857
|
-
amber: "bg-
|
|
858
|
-
green: "bg-
|
|
972
|
+
amber: "bg-warning/15 text-warning-strong",
|
|
973
|
+
green: "bg-success/15 text-success-strong",
|
|
974
|
+
// allow-palette: categorical hue with no token equivalent (pink has no semantic slot)
|
|
859
975
|
pink: "bg-pink-50 text-pink-700 dark:bg-pink-950/40 dark:text-pink-300"
|
|
860
976
|
};
|
|
861
977
|
var badgeToneToVariant = {
|
|
@@ -903,7 +1019,7 @@ function GalleryCardActionsMenu({ actions, title }) {
|
|
|
903
1019
|
action.onSelect();
|
|
904
1020
|
},
|
|
905
1021
|
className: cn(
|
|
906
|
-
action.destructive && "text-destructive data-[highlighted]:bg-destructive/10 data-[highlighted]:text-destructive"
|
|
1022
|
+
action.destructive && "text-destructive-strong data-[highlighted]:bg-destructive/10 data-[highlighted]:text-destructive-strong"
|
|
907
1023
|
),
|
|
908
1024
|
children: action.label
|
|
909
1025
|
},
|
|
@@ -918,6 +1034,7 @@ function GalleryCardBody({
|
|
|
918
1034
|
iconTone,
|
|
919
1035
|
badge,
|
|
920
1036
|
pinned,
|
|
1037
|
+
pinnedLabel = "Pinned",
|
|
921
1038
|
metadata,
|
|
922
1039
|
actions
|
|
923
1040
|
}) {
|
|
@@ -937,7 +1054,13 @@ function GalleryCardBody({
|
|
|
937
1054
|
}
|
|
938
1055
|
) : /* @__PURE__ */ jsx("span", { className: "h-10 w-10 shrink-0", "aria-hidden": "true" }),
|
|
939
1056
|
(pinned || hasActions) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
940
|
-
pinned && /* @__PURE__ */ jsx(
|
|
1057
|
+
pinned && /* @__PURE__ */ jsx(
|
|
1058
|
+
Pin,
|
|
1059
|
+
{
|
|
1060
|
+
className: "h-3.5 w-3.5 fill-warning-strong text-warning-strong",
|
|
1061
|
+
"aria-label": pinnedLabel
|
|
1062
|
+
}
|
|
1063
|
+
),
|
|
941
1064
|
hasActions && actions ? /* @__PURE__ */ jsx(GalleryCardActionsMenu, { actions, title }) : null
|
|
942
1065
|
] })
|
|
943
1066
|
] }),
|
|
@@ -963,6 +1086,7 @@ function GalleryCard(props) {
|
|
|
963
1086
|
iconTone = "neutral",
|
|
964
1087
|
badge,
|
|
965
1088
|
pinned,
|
|
1089
|
+
pinnedLabel,
|
|
966
1090
|
metadata,
|
|
967
1091
|
actions,
|
|
968
1092
|
onClick,
|
|
@@ -979,6 +1103,7 @@ function GalleryCard(props) {
|
|
|
979
1103
|
iconTone,
|
|
980
1104
|
badge,
|
|
981
1105
|
pinned,
|
|
1106
|
+
...pinnedLabel !== void 0 ? { pinnedLabel } : {},
|
|
982
1107
|
metadata,
|
|
983
1108
|
actions
|
|
984
1109
|
}
|
|
@@ -1010,7 +1135,7 @@ function lineTone(line) {
|
|
|
1010
1135
|
return "text-primary font-medium";
|
|
1011
1136
|
}
|
|
1012
1137
|
if (trimmed.includes(":")) {
|
|
1013
|
-
return "text-
|
|
1138
|
+
return "text-success-strong";
|
|
1014
1139
|
}
|
|
1015
1140
|
return "text-foreground/78";
|
|
1016
1141
|
}
|
|
@@ -1135,9 +1260,9 @@ function KineticConsoleFrame({
|
|
|
1135
1260
|
children: [
|
|
1136
1261
|
/* @__PURE__ */ jsxs("div", { className: "flex h-14 flex-none items-center gap-4 border-b border-border/60 bg-background/70 px-5 backdrop-blur-xl", children: [
|
|
1137
1262
|
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", "aria-hidden": true, children: [
|
|
1138
|
-
/* @__PURE__ */ jsx("span", { className: "size-3 rounded-full border border-border/80 bg-muted shadow-sm transition-colors group-hover/kinetic:bg-
|
|
1139
|
-
/* @__PURE__ */ jsx("span", { className: "size-3 rounded-full border border-border/80 bg-muted shadow-sm transition-colors group-hover/kinetic:bg-
|
|
1140
|
-
/* @__PURE__ */ jsx("span", { className: "size-3 rounded-full border border-border/80 bg-muted shadow-sm transition-colors group-hover/kinetic:bg-
|
|
1263
|
+
/* @__PURE__ */ jsx("span", { className: "size-3 rounded-full border border-border/80 bg-muted shadow-sm transition-colors group-hover/kinetic:bg-destructive/80" }),
|
|
1264
|
+
/* @__PURE__ */ jsx("span", { className: "size-3 rounded-full border border-border/80 bg-muted shadow-sm transition-colors group-hover/kinetic:bg-warning/80" }),
|
|
1265
|
+
/* @__PURE__ */ jsx("span", { className: "size-3 rounded-full border border-border/80 bg-muted shadow-sm transition-colors group-hover/kinetic:bg-success/80" })
|
|
1141
1266
|
] }),
|
|
1142
1267
|
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 text-center", children: /* @__PURE__ */ jsx("span", { className: "inline-flex max-w-full items-center rounded-[var(--radius-md)] border border-border/50 bg-muted/35 px-4 py-1 font-mono text-[10px] font-semibold uppercase tracking-[0.16em] text-muted-foreground", children: /* @__PURE__ */ jsx("span", { className: "truncate", translate: "no", children: title }) }) }),
|
|
1143
1268
|
/* @__PURE__ */ jsx("div", { className: "hidden min-w-20 justify-end sm:flex", children: status && /* @__PURE__ */ jsx("span", { className: "rounded-full border border-border/55 bg-background/65 px-2 py-0.5 font-mono text-[10px] uppercase text-muted-foreground", children: status }) })
|
|
@@ -1360,11 +1485,11 @@ function KineticStep({
|
|
|
1360
1485
|
}
|
|
1361
1486
|
);
|
|
1362
1487
|
}
|
|
1363
|
-
var Slot =
|
|
1488
|
+
var Slot = React10.forwardRef(
|
|
1364
1489
|
({ children, className, style, ...props }, ref) => {
|
|
1365
|
-
const childArray =
|
|
1490
|
+
const childArray = React10.Children.toArray(children);
|
|
1366
1491
|
const child = childArray.length === 1 ? childArray[0] : null;
|
|
1367
|
-
if (child == null || !
|
|
1492
|
+
if (child == null || !React10.isValidElement(child)) {
|
|
1368
1493
|
return /* @__PURE__ */ jsx("span", { ref, className, style, ...props, children });
|
|
1369
1494
|
}
|
|
1370
1495
|
const childProps = child.props;
|
|
@@ -1385,7 +1510,7 @@ var Slot = React.forwardRef(
|
|
|
1385
1510
|
className: mergedClass,
|
|
1386
1511
|
style: { ...childProps.style, ...style }
|
|
1387
1512
|
};
|
|
1388
|
-
return
|
|
1513
|
+
return React10.cloneElement(
|
|
1389
1514
|
child,
|
|
1390
1515
|
merged
|
|
1391
1516
|
);
|
|
@@ -1397,7 +1522,11 @@ var buttonVariants = cva(
|
|
|
1397
1522
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap",
|
|
1398
1523
|
"rounded-[var(--btn-default-radius,var(--radius-md))]",
|
|
1399
1524
|
"text-[length:var(--control-font-size-md,0.875rem)] font-[number:var(--font-weight-medium,500)]",
|
|
1400
|
-
|
|
1525
|
+
// `transform` is in the property list on purpose: without it the
|
|
1526
|
+
// active:scale-[0.97] press snapped instantly and the button felt dead
|
|
1527
|
+
// under the finger. Duration/ease stay on the flow rail — motion
|
|
1528
|
+
// governance pins them (primitives/__tests__/motion-governance.test.ts).
|
|
1529
|
+
"transition-[color,background-color,border-color,box-shadow,transform] duration-flow ease-[var(--ease-brand)]",
|
|
1401
1530
|
"active:scale-[0.97] motion-reduce:active:scale-100 motion-reduce:transition-none",
|
|
1402
1531
|
"disabled:pointer-events-none disabled:opacity-50",
|
|
1403
1532
|
"aria-busy:cursor-wait"
|
|
@@ -1407,7 +1536,7 @@ var buttonVariants = cva(
|
|
|
1407
1536
|
variant: {
|
|
1408
1537
|
// Recipe-driven via packages/design/tokens/recipe.css (.btn-brand-default)
|
|
1409
1538
|
default: "btn-brand-default",
|
|
1410
|
-
ink: "bg-
|
|
1539
|
+
ink: "bg-neutral-12 text-neutral-1 ring-1 ring-inset ring-neutral-1/5 hover:bg-neutral-11 hover:-translate-y-px active:translate-y-0 transition-[transform,background-color] duration-micro",
|
|
1411
1540
|
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
1412
1541
|
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
|
1413
1542
|
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
@@ -1530,10 +1659,10 @@ function Spinner({ className }) {
|
|
|
1530
1659
|
}
|
|
1531
1660
|
);
|
|
1532
1661
|
}
|
|
1533
|
-
function getIconSizeClass(size,
|
|
1534
|
-
if (
|
|
1535
|
-
if (
|
|
1536
|
-
if (
|
|
1662
|
+
function getIconSizeClass(size, iconSize2) {
|
|
1663
|
+
if (iconSize2 === "sm") return "[&>svg]:size-3.5";
|
|
1664
|
+
if (iconSize2 === "md") return "[&>svg]:size-3.5";
|
|
1665
|
+
if (iconSize2 === "lg") return "[&>svg]:size-4";
|
|
1537
1666
|
switch (size) {
|
|
1538
1667
|
case "tiny":
|
|
1539
1668
|
return "[&>svg]:size-3";
|
|
@@ -1548,10 +1677,10 @@ function getIconSizeClass(size, iconSize) {
|
|
|
1548
1677
|
return "[&>svg]:size-4";
|
|
1549
1678
|
}
|
|
1550
1679
|
}
|
|
1551
|
-
function getSpinnerSizeClass(size,
|
|
1552
|
-
if (
|
|
1553
|
-
if (
|
|
1554
|
-
if (
|
|
1680
|
+
function getSpinnerSizeClass(size, iconSize2) {
|
|
1681
|
+
if (iconSize2 === "sm") return "size-3.5";
|
|
1682
|
+
if (iconSize2 === "md") return "size-3.5";
|
|
1683
|
+
if (iconSize2 === "lg") return "size-4";
|
|
1555
1684
|
switch (size) {
|
|
1556
1685
|
case "tiny":
|
|
1557
1686
|
return "size-3";
|
|
@@ -1576,10 +1705,10 @@ function resolveShadowClass(shadow) {
|
|
|
1576
1705
|
const level = shadow === true ? "md" : shadow;
|
|
1577
1706
|
return SHADOW_CLASSES[level];
|
|
1578
1707
|
}
|
|
1579
|
-
function ButtonContent({ loading, prefix, suffix, size, iconSize, children }) {
|
|
1580
|
-
const iconSizeClass = getIconSizeClass(size,
|
|
1708
|
+
function ButtonContent({ loading, prefix, suffix, size, iconSize: iconSize2, children }) {
|
|
1709
|
+
const iconSizeClass = getIconSizeClass(size, iconSize2);
|
|
1581
1710
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1582
|
-
loading && /* @__PURE__ */ jsx(Spinner, { className: getSpinnerSizeClass(size,
|
|
1711
|
+
loading && /* @__PURE__ */ jsx(Spinner, { className: getSpinnerSizeClass(size, iconSize2) }),
|
|
1583
1712
|
prefix != null && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("shrink-0", iconSizeClass), children: prefix }),
|
|
1584
1713
|
children,
|
|
1585
1714
|
suffix != null && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("shrink-0", iconSizeClass), children: suffix })
|
|
@@ -1590,7 +1719,7 @@ var Button = ({
|
|
|
1590
1719
|
variant,
|
|
1591
1720
|
size,
|
|
1592
1721
|
shape,
|
|
1593
|
-
iconSize,
|
|
1722
|
+
iconSize: iconSize2,
|
|
1594
1723
|
asChild = false,
|
|
1595
1724
|
loading = false,
|
|
1596
1725
|
disabled,
|
|
@@ -1608,7 +1737,7 @@ var Button = ({
|
|
|
1608
1737
|
Comp,
|
|
1609
1738
|
{
|
|
1610
1739
|
ref,
|
|
1611
|
-
className: cn(buttonVariants({ variant, size, shape, iconSize }), shadowClass, className),
|
|
1740
|
+
className: cn(buttonVariants({ variant, size, shape, iconSize: iconSize2 }), shadowClass, className),
|
|
1612
1741
|
disabled: isDisabled,
|
|
1613
1742
|
"aria-busy": loading || void 0,
|
|
1614
1743
|
...props,
|
|
@@ -1619,7 +1748,7 @@ var Button = ({
|
|
|
1619
1748
|
prefix,
|
|
1620
1749
|
suffix,
|
|
1621
1750
|
size,
|
|
1622
|
-
iconSize,
|
|
1751
|
+
iconSize: iconSize2,
|
|
1623
1752
|
children
|
|
1624
1753
|
}
|
|
1625
1754
|
)
|
|
@@ -1696,8 +1825,18 @@ function asPlainStyle(style) {
|
|
|
1696
1825
|
function withHtmlProps(Component) {
|
|
1697
1826
|
return Component;
|
|
1698
1827
|
}
|
|
1699
|
-
|
|
1700
|
-
|
|
1828
|
+
|
|
1829
|
+
// src/tokens/components/interaction.ts
|
|
1830
|
+
var interaction = {
|
|
1831
|
+
/**
|
|
1832
|
+
* Tooltips. The first one waits so a sweeping pointer does not strobe;
|
|
1833
|
+
* once one is open, its neighbours open instantly if the pointer arrives
|
|
1834
|
+
* within the skip window. Radix Tooltip defaults: delayDuration 700,
|
|
1835
|
+
* skipDelayDuration 300. Vercel/Kowalski: "delay the first tooltip only".
|
|
1836
|
+
*/
|
|
1837
|
+
tooltip: { delayMs: 700, skipWindowMs: 300 }};
|
|
1838
|
+
var DEFAULT_TOOLTIP_DELAY_MS = interaction.tooltip.delayMs;
|
|
1839
|
+
var SKIP_DELAY_WINDOW_MS = interaction.tooltip.skipWindowMs;
|
|
1701
1840
|
var lastTooltipOpenAt = 0;
|
|
1702
1841
|
var skipDelayListeners = /* @__PURE__ */ new Set();
|
|
1703
1842
|
function markTooltipOpened() {
|
|
@@ -1708,8 +1847,8 @@ function shouldSkipDelay() {
|
|
|
1708
1847
|
return Date.now() - lastTooltipOpenAt < SKIP_DELAY_WINDOW_MS;
|
|
1709
1848
|
}
|
|
1710
1849
|
function useSkipDelay() {
|
|
1711
|
-
const [, tick] =
|
|
1712
|
-
|
|
1850
|
+
const [, tick] = React10.useReducer((count) => count + 1, 0);
|
|
1851
|
+
React10.useEffect(() => {
|
|
1713
1852
|
skipDelayListeners.add(tick);
|
|
1714
1853
|
return () => {
|
|
1715
1854
|
skipDelayListeners.delete(tick);
|
|
@@ -1717,7 +1856,7 @@ function useSkipDelay() {
|
|
|
1717
1856
|
}, []);
|
|
1718
1857
|
return shouldSkipDelay();
|
|
1719
1858
|
}
|
|
1720
|
-
var TooltipInstantContext =
|
|
1859
|
+
var TooltipInstantContext = React10.createContext(false);
|
|
1721
1860
|
var TooltipProvider = ({
|
|
1722
1861
|
children,
|
|
1723
1862
|
delayDuration = DEFAULT_TOOLTIP_DELAY_MS
|
|
@@ -1752,7 +1891,7 @@ var TooltipTrigger = ({
|
|
|
1752
1891
|
ref,
|
|
1753
1892
|
...props
|
|
1754
1893
|
}) => {
|
|
1755
|
-
if (asChild &&
|
|
1894
|
+
if (asChild && React10.isValidElement(children)) {
|
|
1756
1895
|
return /* @__PURE__ */ jsx(
|
|
1757
1896
|
Tooltip$1.Trigger,
|
|
1758
1897
|
{
|
|
@@ -1775,7 +1914,7 @@ var TooltipContent = ({
|
|
|
1775
1914
|
ref,
|
|
1776
1915
|
...props
|
|
1777
1916
|
}) => {
|
|
1778
|
-
const instant =
|
|
1917
|
+
const instant = React10.use(TooltipInstantContext);
|
|
1779
1918
|
return /* @__PURE__ */ jsx(Tooltip$1.Portal, { children: /* @__PURE__ */ jsx(
|
|
1780
1919
|
Tooltip$1.Positioner,
|
|
1781
1920
|
{
|
|
@@ -1891,7 +2030,7 @@ var tabsContentVariants = cva(
|
|
|
1891
2030
|
}
|
|
1892
2031
|
}
|
|
1893
2032
|
);
|
|
1894
|
-
var TabsContext =
|
|
2033
|
+
var TabsContext = React10.createContext({
|
|
1895
2034
|
activationMode: "manual",
|
|
1896
2035
|
disabled: false,
|
|
1897
2036
|
shape: "default",
|
|
@@ -1949,7 +2088,7 @@ function Tabs({
|
|
|
1949
2088
|
}) {
|
|
1950
2089
|
const rootValue = selected ?? value;
|
|
1951
2090
|
const rootDefaultValue = defaultValue ?? getFirstEnabledValue(tabs);
|
|
1952
|
-
const context =
|
|
2091
|
+
const context = React10.useMemo(
|
|
1953
2092
|
() => ({ activationMode, disabled, shape, size, variant }),
|
|
1954
2093
|
[activationMode, disabled, shape, size, variant]
|
|
1955
2094
|
);
|
|
@@ -2035,11 +2174,11 @@ function TabsList({
|
|
|
2035
2174
|
children,
|
|
2036
2175
|
...props
|
|
2037
2176
|
}) {
|
|
2038
|
-
const context =
|
|
2177
|
+
const context = React10.use(TabsContext);
|
|
2039
2178
|
const resolvedVariant = variant ?? context.variant;
|
|
2040
2179
|
const resolvedShape = shape ?? context.shape;
|
|
2041
2180
|
const resolvedActivateOnFocus = activateOnFocus ?? context.activationMode === "automatic";
|
|
2042
|
-
const listContext =
|
|
2181
|
+
const listContext = React10.useMemo(
|
|
2043
2182
|
() => ({ ...context, shape: resolvedShape, variant: resolvedVariant }),
|
|
2044
2183
|
[context, resolvedShape, resolvedVariant]
|
|
2045
2184
|
);
|
|
@@ -2076,7 +2215,7 @@ function TabsList({
|
|
|
2076
2215
|
) });
|
|
2077
2216
|
}
|
|
2078
2217
|
function TabsTrigger({ badge, children, className, disabled, icon, ...props }) {
|
|
2079
|
-
const context =
|
|
2218
|
+
const context = React10.use(TabsContext);
|
|
2080
2219
|
const isDisabled = disabled ?? context.disabled;
|
|
2081
2220
|
return /* @__PURE__ */ jsxs(
|
|
2082
2221
|
BaseTrigger,
|
|
@@ -2140,7 +2279,7 @@ var formControlFocusClassNames = {
|
|
|
2140
2279
|
var formControlInvalidClassNames = {
|
|
2141
2280
|
textarea: "aria-invalid:border-destructive/60 aria-invalid:focus:border-destructive aria-invalid:focus:ring-destructive/20"};
|
|
2142
2281
|
var fieldMessageClassName = "text-xs text-muted-foreground";
|
|
2143
|
-
var fieldErrorClassName = "text-xs font-medium text-destructive";
|
|
2282
|
+
var fieldErrorClassName = "text-xs font-medium text-destructive-strong";
|
|
2144
2283
|
function getTextareaStyle(size, style) {
|
|
2145
2284
|
const token = textareaTokens.sizes[size];
|
|
2146
2285
|
return {
|
|
@@ -2175,6 +2314,7 @@ var Textarea = ({
|
|
|
2175
2314
|
description,
|
|
2176
2315
|
error,
|
|
2177
2316
|
fieldClassName,
|
|
2317
|
+
tone = "bordered",
|
|
2178
2318
|
id,
|
|
2179
2319
|
onChange,
|
|
2180
2320
|
onValueChange,
|
|
@@ -2183,13 +2323,13 @@ var Textarea = ({
|
|
|
2183
2323
|
ref,
|
|
2184
2324
|
...props
|
|
2185
2325
|
}) => {
|
|
2186
|
-
const baseId =
|
|
2326
|
+
const baseId = React10.useId();
|
|
2187
2327
|
const textareaId = id ?? (label || description || typeof error === "string" ? baseId : void 0);
|
|
2188
2328
|
const resolvedInvalid = isInvalid(error, ariaInvalid);
|
|
2189
2329
|
const descriptionId = description && textareaId ? `${textareaId}-description` : void 0;
|
|
2190
2330
|
const errorId = typeof error === "string" && textareaId ? `${textareaId}-error` : void 0;
|
|
2191
2331
|
const describedBy = joinDescriptionIds(ariaDescribedBy, descriptionId, errorId);
|
|
2192
|
-
const handleChange =
|
|
2332
|
+
const handleChange = React10.useCallback(
|
|
2193
2333
|
(event) => {
|
|
2194
2334
|
onValueChange?.(event.currentTarget.value);
|
|
2195
2335
|
onChange?.(event);
|
|
@@ -2200,10 +2340,10 @@ var Textarea = ({
|
|
|
2200
2340
|
"textarea",
|
|
2201
2341
|
{
|
|
2202
2342
|
className: cn(
|
|
2203
|
-
"flex min-h-[var(--textarea-min-height)] w-full resize-y rounded-[var(--textarea-radius)]
|
|
2204
|
-
"px-[var(--textarea-padding-x)] py-[var(--textarea-padding-y)] text-[length:var(--textarea-font-size)] text-foreground
|
|
2343
|
+
"flex min-h-[var(--textarea-min-height)] w-full resize-y rounded-[var(--textarea-radius)]",
|
|
2344
|
+
"px-[var(--textarea-padding-x)] py-[var(--textarea-padding-y)] text-[length:var(--textarea-font-size)] text-foreground",
|
|
2205
2345
|
"transition-[background-color,border-color,box-shadow,color] duration-micro ease-out placeholder:text-muted-foreground",
|
|
2206
|
-
formControlFocusClassNames.textarea,
|
|
2346
|
+
tone === "bordered" ? `border border-input bg-background ${formControlFocusClassNames.textarea}` : "border-0 bg-transparent shadow-none",
|
|
2207
2347
|
"disabled:cursor-not-allowed disabled:opacity-50 read-only:cursor-default read-only:bg-muted/70",
|
|
2208
2348
|
formControlInvalidClassNames.textarea,
|
|
2209
2349
|
className
|
|
@@ -2309,6 +2449,17 @@ function MarkdownRenderer({ content, className }) {
|
|
|
2309
2449
|
}
|
|
2310
2450
|
) });
|
|
2311
2451
|
}
|
|
2452
|
+
var DEFAULT_MARKDOWN_EDITOR_LABELS = {
|
|
2453
|
+
bold: "Bold (Ctrl+B)",
|
|
2454
|
+
italic: "Italic (Ctrl+I)",
|
|
2455
|
+
inlineCode: "Inline code",
|
|
2456
|
+
heading: "Heading",
|
|
2457
|
+
blockQuote: "Block quote",
|
|
2458
|
+
bulletList: "Bullet list",
|
|
2459
|
+
link: "Link",
|
|
2460
|
+
image: "Image",
|
|
2461
|
+
fencedCodeBlock: "Fenced code block"
|
|
2462
|
+
};
|
|
2312
2463
|
function QuoteGlyph(props) {
|
|
2313
2464
|
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 16 16", fill: "currentColor", "aria-hidden": "true", className: props.className, children: [
|
|
2314
2465
|
/* @__PURE__ */ jsx("title", { children: "Block quote" }),
|
|
@@ -2317,11 +2468,15 @@ function QuoteGlyph(props) {
|
|
|
2317
2468
|
}
|
|
2318
2469
|
function MarkdownEditor({
|
|
2319
2470
|
value,
|
|
2320
|
-
|
|
2471
|
+
onValueChange,
|
|
2472
|
+
onChange: legacyOnChange,
|
|
2321
2473
|
placeholder = "Write your answer here\u2026",
|
|
2322
2474
|
minHeight = 250,
|
|
2323
|
-
className
|
|
2475
|
+
className,
|
|
2476
|
+
labels
|
|
2324
2477
|
}) {
|
|
2478
|
+
const onChange = onValueChange ?? legacyOnChange;
|
|
2479
|
+
const mergedLabels = { ...DEFAULT_MARKDOWN_EDITOR_LABELS, ...labels };
|
|
2325
2480
|
const [tab, setTab] = useState("write");
|
|
2326
2481
|
const textareaRef = useRef(null);
|
|
2327
2482
|
const insertMarkdown = useCallback(
|
|
@@ -2361,14 +2516,42 @@ function MarkdownEditor({
|
|
|
2361
2516
|
] })
|
|
2362
2517
|
] }),
|
|
2363
2518
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
2364
|
-
/* @__PURE__ */ jsx(ToolbarButton, { "aria-label": "Bold (Ctrl+B)", onClick: () => insertMarkdown("**", "**"), children: /* @__PURE__ */ jsx(TextBold, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) }),
|
|
2365
|
-
/* @__PURE__ */ jsx(ToolbarButton, { "aria-label": "Italic (Ctrl+I)", onClick: () => insertMarkdown("*", "*"), children: /* @__PURE__ */ jsx(TextItalic, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) }),
|
|
2366
|
-
/* @__PURE__ */ jsx(ToolbarButton, { "aria-label": "Inline code", onClick: () => insertMarkdown("`", "`"), children: /* @__PURE__ */ jsx(Code, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) }),
|
|
2367
|
-
/* @__PURE__ */ jsx(ToolbarButton, { "aria-label": "Heading", onClick: () => insertMarkdown("\n## ", "", true), children: /* @__PURE__ */ jsx(Hash, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) }),
|
|
2368
2519
|
/* @__PURE__ */ jsx(
|
|
2369
2520
|
ToolbarButton,
|
|
2370
2521
|
{
|
|
2371
|
-
"aria-label":
|
|
2522
|
+
"aria-label": mergedLabels.bold,
|
|
2523
|
+
onClick: () => insertMarkdown("**", "**"),
|
|
2524
|
+
children: /* @__PURE__ */ jsx(TextBold, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
|
|
2525
|
+
}
|
|
2526
|
+
),
|
|
2527
|
+
/* @__PURE__ */ jsx(
|
|
2528
|
+
ToolbarButton,
|
|
2529
|
+
{
|
|
2530
|
+
"aria-label": mergedLabels.italic,
|
|
2531
|
+
onClick: () => insertMarkdown("*", "*"),
|
|
2532
|
+
children: /* @__PURE__ */ jsx(TextItalic, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
|
|
2533
|
+
}
|
|
2534
|
+
),
|
|
2535
|
+
/* @__PURE__ */ jsx(
|
|
2536
|
+
ToolbarButton,
|
|
2537
|
+
{
|
|
2538
|
+
"aria-label": mergedLabels.inlineCode,
|
|
2539
|
+
onClick: () => insertMarkdown("`", "`"),
|
|
2540
|
+
children: /* @__PURE__ */ jsx(Code, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
|
|
2541
|
+
}
|
|
2542
|
+
),
|
|
2543
|
+
/* @__PURE__ */ jsx(
|
|
2544
|
+
ToolbarButton,
|
|
2545
|
+
{
|
|
2546
|
+
"aria-label": mergedLabels.heading,
|
|
2547
|
+
onClick: () => insertMarkdown("\n## ", "", true),
|
|
2548
|
+
children: /* @__PURE__ */ jsx(Hash, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
|
|
2549
|
+
}
|
|
2550
|
+
),
|
|
2551
|
+
/* @__PURE__ */ jsx(
|
|
2552
|
+
ToolbarButton,
|
|
2553
|
+
{
|
|
2554
|
+
"aria-label": mergedLabels.blockQuote,
|
|
2372
2555
|
onClick: () => insertMarkdown("\n> ", "", true),
|
|
2373
2556
|
children: /* @__PURE__ */ jsx(QuoteGlyph, { className: "h-3.5 w-3.5" })
|
|
2374
2557
|
}
|
|
@@ -2376,17 +2559,31 @@ function MarkdownEditor({
|
|
|
2376
2559
|
/* @__PURE__ */ jsx(
|
|
2377
2560
|
ToolbarButton,
|
|
2378
2561
|
{
|
|
2379
|
-
"aria-label":
|
|
2562
|
+
"aria-label": mergedLabels.bulletList,
|
|
2380
2563
|
onClick: () => insertMarkdown("\n- ", "", true),
|
|
2381
2564
|
children: /* @__PURE__ */ jsx(ListUnordered, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
|
|
2382
2565
|
}
|
|
2383
2566
|
),
|
|
2384
|
-
/* @__PURE__ */ jsx(ToolbarButton, { "aria-label": "Link", onClick: () => insertMarkdown("[", "](url)"), children: /* @__PURE__ */ jsx(Link, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) }),
|
|
2385
|
-
/* @__PURE__ */ jsx(ToolbarButton, { "aria-label": "Image", onClick: () => insertMarkdown(""), children: /* @__PURE__ */ jsx(Image, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) }),
|
|
2386
2567
|
/* @__PURE__ */ jsx(
|
|
2387
2568
|
ToolbarButton,
|
|
2388
2569
|
{
|
|
2389
|
-
"aria-label":
|
|
2570
|
+
"aria-label": mergedLabels.link,
|
|
2571
|
+
onClick: () => insertMarkdown("[", "](url)"),
|
|
2572
|
+
children: /* @__PURE__ */ jsx(Link, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
|
|
2573
|
+
}
|
|
2574
|
+
),
|
|
2575
|
+
/* @__PURE__ */ jsx(
|
|
2576
|
+
ToolbarButton,
|
|
2577
|
+
{
|
|
2578
|
+
"aria-label": mergedLabels.image,
|
|
2579
|
+
onClick: () => insertMarkdown(""),
|
|
2580
|
+
children: /* @__PURE__ */ jsx(Image, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
|
|
2581
|
+
}
|
|
2582
|
+
),
|
|
2583
|
+
/* @__PURE__ */ jsx(
|
|
2584
|
+
ToolbarButton,
|
|
2585
|
+
{
|
|
2586
|
+
"aria-label": mergedLabels.fencedCodeBlock,
|
|
2390
2587
|
onClick: () => insertMarkdown("\n```javascript\n", "\n```\n", true),
|
|
2391
2588
|
children: /* @__PURE__ */ jsx(FileText, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
|
|
2392
2589
|
}
|
|
@@ -2400,7 +2597,8 @@ function MarkdownEditor({
|
|
|
2400
2597
|
value,
|
|
2401
2598
|
onChange: (e) => onChange(e.target.value),
|
|
2402
2599
|
placeholder,
|
|
2403
|
-
|
|
2600
|
+
tone: "bare",
|
|
2601
|
+
className: "resize-none rounded-none font-mono text-sm",
|
|
2404
2602
|
style: { minHeight }
|
|
2405
2603
|
}
|
|
2406
2604
|
) }),
|
|
@@ -2435,34 +2633,6 @@ function ToolbarButton({
|
|
|
2435
2633
|
}
|
|
2436
2634
|
);
|
|
2437
2635
|
}
|
|
2438
|
-
var Card2 = ({
|
|
2439
|
-
className,
|
|
2440
|
-
ref,
|
|
2441
|
-
...props
|
|
2442
|
-
}) => /* @__PURE__ */ jsx(
|
|
2443
|
-
"div",
|
|
2444
|
-
{
|
|
2445
|
-
ref,
|
|
2446
|
-
className: cn(
|
|
2447
|
-
"rounded-[var(--radius-lg)] border border-border bg-card text-card-foreground shadow-sm",
|
|
2448
|
-
className
|
|
2449
|
-
),
|
|
2450
|
-
...props
|
|
2451
|
-
}
|
|
2452
|
-
);
|
|
2453
|
-
Card2.displayName = "Card";
|
|
2454
|
-
var CardHeader2 = ({
|
|
2455
|
-
className,
|
|
2456
|
-
ref,
|
|
2457
|
-
...props
|
|
2458
|
-
}) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex flex-col space-y-1.5 p-6", className), ...props });
|
|
2459
|
-
CardHeader2.displayName = "CardHeader";
|
|
2460
|
-
var CardContent = ({
|
|
2461
|
-
className,
|
|
2462
|
-
ref,
|
|
2463
|
-
...props
|
|
2464
|
-
}) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props });
|
|
2465
|
-
CardContent.displayName = "CardContent";
|
|
2466
2636
|
var Separator = ({
|
|
2467
2637
|
className,
|
|
2468
2638
|
orientation = "horizontal",
|
|
@@ -2491,7 +2661,7 @@ var sizeClasses = {
|
|
|
2491
2661
|
xl: { root: "h-20 w-20", fallback: "text-2xl" }
|
|
2492
2662
|
};
|
|
2493
2663
|
var numericAvatarClass = "h-[var(--avatar-size)] w-[var(--avatar-size)]";
|
|
2494
|
-
var AvatarContext =
|
|
2664
|
+
var AvatarContext = React10.createContext(null);
|
|
2495
2665
|
function isPresetSize(size) {
|
|
2496
2666
|
return typeof size === "string";
|
|
2497
2667
|
}
|
|
@@ -2593,7 +2763,7 @@ var AvatarFallback = ({
|
|
|
2593
2763
|
ref,
|
|
2594
2764
|
...props
|
|
2595
2765
|
}) => {
|
|
2596
|
-
const context =
|
|
2766
|
+
const context = React10.use(AvatarContext);
|
|
2597
2767
|
const resolvedSize = size ?? context?.size ?? "md";
|
|
2598
2768
|
const fallbackLabel = ariaLabel ?? (typeof children === "string" && children.trim().length > 0 ? `Avatar with initials: ${children}` : context?.title);
|
|
2599
2769
|
return /* @__PURE__ */ jsx(
|
|
@@ -2635,9 +2805,10 @@ function UserInfo({ author, timestamp, verb = "asked", className }) {
|
|
|
2635
2805
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
2636
2806
|
/* @__PURE__ */ jsx("span", { className: "font-medium text-foreground text-sm", children: author.name }),
|
|
2637
2807
|
/* @__PURE__ */ jsx("span", { className: "font-bold text-muted-foreground text-xs tabular-nums", children: author.reputation.toLocaleString() }),
|
|
2638
|
-
author.badges.gold > 0 && /* @__PURE__ */ jsx(Badge2, { color: "bg-
|
|
2639
|
-
author.badges.silver > 0 && /* @__PURE__ */ jsx(Badge2, { color: "bg-
|
|
2640
|
-
author.badges.bronze > 0 &&
|
|
2808
|
+
author.badges.gold > 0 && /* @__PURE__ */ jsx(Badge2, { color: "bg-warning", count: author.badges.gold, label: "gold" }),
|
|
2809
|
+
author.badges.silver > 0 && /* @__PURE__ */ jsx(Badge2, { color: "bg-neutral-9", count: author.badges.silver, label: "silver" }),
|
|
2810
|
+
author.badges.bronze > 0 && // allow-palette: bronze medal tier has no design-system equivalent; amber-600 is the closest fixed hue and is distinct from the gold (warning) dot above
|
|
2811
|
+
/* @__PURE__ */ jsx(Badge2, { color: "bg-amber-600", count: author.badges.bronze, label: "bronze" })
|
|
2641
2812
|
] })
|
|
2642
2813
|
] })
|
|
2643
2814
|
]
|
|
@@ -2668,7 +2839,7 @@ function VoteButtons({
|
|
|
2668
2839
|
size = "default",
|
|
2669
2840
|
label = "post"
|
|
2670
2841
|
}) {
|
|
2671
|
-
const
|
|
2842
|
+
const iconSize2 = size === "large" ? "h-5 w-5" : "h-4 w-4";
|
|
2672
2843
|
const scoreSize = size === "large" ? "text-lg" : "text-base";
|
|
2673
2844
|
const score = votes + voteDelta(userVote);
|
|
2674
2845
|
return /* @__PURE__ */ jsxs("fieldset", { className: "flex flex-col items-center gap-2", children: [
|
|
@@ -2686,7 +2857,7 @@ function VoteButtons({
|
|
|
2686
2857
|
"aria-pressed": userVote === "up",
|
|
2687
2858
|
onClick: () => onVote("up"),
|
|
2688
2859
|
className: cn("p-2", userVote === "up" && "bg-primary/10 text-primary hover:bg-primary/15"),
|
|
2689
|
-
children: /* @__PURE__ */ jsx(ChevronUp, { className:
|
|
2860
|
+
children: /* @__PURE__ */ jsx(ChevronUp, { className: iconSize2, "aria-hidden": "true" })
|
|
2690
2861
|
}
|
|
2691
2862
|
),
|
|
2692
2863
|
/* @__PURE__ */ jsx(
|
|
@@ -2716,7 +2887,7 @@ function VoteButtons({
|
|
|
2716
2887
|
"p-2",
|
|
2717
2888
|
userVote === "down" && "bg-muted text-muted-foreground hover:bg-muted"
|
|
2718
2889
|
),
|
|
2719
|
-
children: /* @__PURE__ */ jsx(ChevronDown, { className:
|
|
2890
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { className: iconSize2, "aria-hidden": "true" })
|
|
2720
2891
|
}
|
|
2721
2892
|
)
|
|
2722
2893
|
] });
|
|
@@ -2807,7 +2978,7 @@ function QAPage({
|
|
|
2807
2978
|
] }),
|
|
2808
2979
|
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: question.tags.map((tag) => /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs", children: tag }, tag)) })
|
|
2809
2980
|
] }),
|
|
2810
|
-
/* @__PURE__ */ jsx(
|
|
2981
|
+
/* @__PURE__ */ jsx(Card, { className: "mb-8", children: /* @__PURE__ */ jsxs(CardContent, { className: "flex gap-6 p-6", children: [
|
|
2811
2982
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-4", children: [
|
|
2812
2983
|
/* @__PURE__ */ jsx(
|
|
2813
2984
|
VoteButtons,
|
|
@@ -2828,7 +2999,7 @@ function QAPage({
|
|
|
2828
2999
|
"aria-label": question.bookmarked ? "Remove bookmark" : "Bookmark question",
|
|
2829
3000
|
"aria-pressed": question.bookmarked,
|
|
2830
3001
|
onClick: handleBookmarkToggle,
|
|
2831
|
-
className: cn("p-2", question.bookmarked && "bg-warning/10 text-warning"),
|
|
3002
|
+
className: cn("p-2", question.bookmarked && "bg-warning/10 text-warning-strong"),
|
|
2832
3003
|
children: /* @__PURE__ */ jsx(Bookmark, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
2833
3004
|
}
|
|
2834
3005
|
)
|
|
@@ -2855,7 +3026,7 @@ function QAPage({
|
|
|
2855
3026
|
answers.length === 1 ? "Answer" : "Answers"
|
|
2856
3027
|
] }) }),
|
|
2857
3028
|
/* @__PURE__ */ jsx("div", { className: "mb-8", children: sortedAnswers.map((answer, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2858
|
-
/* @__PURE__ */ jsx(
|
|
3029
|
+
/* @__PURE__ */ jsx(Card, { className: cn("mb-6", answer.isAccepted && "ring-2 ring-success/40"), children: /* @__PURE__ */ jsxs(CardContent, { className: "flex gap-6 p-6", children: [
|
|
2859
3030
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-4", children: [
|
|
2860
3031
|
/* @__PURE__ */ jsx(
|
|
2861
3032
|
VoteButtons,
|
|
@@ -2876,13 +3047,19 @@ function QAPage({
|
|
|
2876
3047
|
"aria-label": answer.isAccepted ? "Unaccept this answer" : "Accept this answer",
|
|
2877
3048
|
"aria-pressed": answer.isAccepted,
|
|
2878
3049
|
onClick: () => handleAccept(answer.id),
|
|
2879
|
-
className: cn("p-2", answer.isAccepted && "bg-success/10 text-success"),
|
|
3050
|
+
className: cn("p-2", answer.isAccepted && "bg-success/10 text-success-strong"),
|
|
2880
3051
|
children: /* @__PURE__ */ jsx(Check, { className: "h-5 w-5", "aria-hidden": "true" })
|
|
2881
3052
|
}
|
|
2882
3053
|
),
|
|
2883
3054
|
answer.isAccepted && /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
2884
|
-
/* @__PURE__ */ jsx(
|
|
2885
|
-
|
|
3055
|
+
/* @__PURE__ */ jsx(
|
|
3056
|
+
StarFill,
|
|
3057
|
+
{
|
|
3058
|
+
"aria-hidden": "true",
|
|
3059
|
+
className: "mx-auto mb-1 h-4 w-4 text-success-strong"
|
|
3060
|
+
}
|
|
3061
|
+
),
|
|
3062
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-success-strong text-xs", children: "Accepted" })
|
|
2886
3063
|
] })
|
|
2887
3064
|
] }),
|
|
2888
3065
|
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
@@ -2903,10 +3080,17 @@ function QAPage({
|
|
|
2903
3080
|
] }) }),
|
|
2904
3081
|
index < sortedAnswers.length - 1 && /* @__PURE__ */ jsx(Separator, { className: "mb-6" })
|
|
2905
3082
|
] }, answer.id)) }),
|
|
2906
|
-
/* @__PURE__ */ jsxs(
|
|
2907
|
-
/* @__PURE__ */ jsx(
|
|
3083
|
+
/* @__PURE__ */ jsxs(Card, { children: [
|
|
3084
|
+
/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx("h3", { className: "font-semibold text-foreground text-lg", children: "Your Answer" }) }),
|
|
2908
3085
|
/* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
|
|
2909
|
-
/* @__PURE__ */ jsx(
|
|
3086
|
+
/* @__PURE__ */ jsx(
|
|
3087
|
+
MarkdownEditor,
|
|
3088
|
+
{
|
|
3089
|
+
value: draft,
|
|
3090
|
+
onValueChange: setDraft,
|
|
3091
|
+
placeholder: "Write your answer here\u2026"
|
|
3092
|
+
}
|
|
3093
|
+
),
|
|
2910
3094
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2911
3095
|
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-xs", children: "Thanks for contributing an answer!" }),
|
|
2912
3096
|
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
@@ -2954,7 +3138,7 @@ function PostActions({
|
|
|
2954
3138
|
/* @__PURE__ */ jsx(UserInfo, { author, timestamp, verb })
|
|
2955
3139
|
] });
|
|
2956
3140
|
}
|
|
2957
|
-
var CollapsibleContext =
|
|
3141
|
+
var CollapsibleContext = React10.createContext({});
|
|
2958
3142
|
var Collapsible = ({
|
|
2959
3143
|
className,
|
|
2960
3144
|
open: openProp,
|
|
@@ -2965,10 +3149,10 @@ var Collapsible = ({
|
|
|
2965
3149
|
ref,
|
|
2966
3150
|
...props
|
|
2967
3151
|
}) => {
|
|
2968
|
-
const [uncontrolledOpen, setUncontrolledOpen] =
|
|
3152
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React10.useState(defaultOpen || false);
|
|
2969
3153
|
const isControlled = openProp !== void 0;
|
|
2970
3154
|
const open = isControlled ? openProp : uncontrolledOpen;
|
|
2971
|
-
const handleOpenChange =
|
|
3155
|
+
const handleOpenChange = React10.useCallback(
|
|
2972
3156
|
(nextOpen) => {
|
|
2973
3157
|
if (!isControlled) {
|
|
2974
3158
|
setUncontrolledOpen(nextOpen);
|
|
@@ -2997,8 +3181,8 @@ var CollapsibleTrigger = ({
|
|
|
2997
3181
|
ref,
|
|
2998
3182
|
...props
|
|
2999
3183
|
}) => {
|
|
3000
|
-
const { open, onOpenChange, disabled } =
|
|
3001
|
-
const handleClick =
|
|
3184
|
+
const { open, onOpenChange, disabled } = React10.use(CollapsibleContext);
|
|
3185
|
+
const handleClick = React10.useCallback(
|
|
3002
3186
|
(e) => {
|
|
3003
3187
|
if (disabled) return;
|
|
3004
3188
|
onOpenChange?.(!open);
|
|
@@ -3006,8 +3190,8 @@ var CollapsibleTrigger = ({
|
|
|
3006
3190
|
},
|
|
3007
3191
|
[disabled, open, onOpenChange, props.onClick]
|
|
3008
3192
|
);
|
|
3009
|
-
if (asChild &&
|
|
3010
|
-
return
|
|
3193
|
+
if (asChild && React10.isValidElement(children)) {
|
|
3194
|
+
return React10.cloneElement(children, {
|
|
3011
3195
|
ref,
|
|
3012
3196
|
onClick: handleClick,
|
|
3013
3197
|
"data-state": open ? "open" : "closed",
|
|
@@ -3041,7 +3225,7 @@ var CollapsibleContent = ({
|
|
|
3041
3225
|
ref,
|
|
3042
3226
|
...props
|
|
3043
3227
|
}) => {
|
|
3044
|
-
const { open } =
|
|
3228
|
+
const { open } = React10.use(CollapsibleContext);
|
|
3045
3229
|
const shouldReduceMotion = useReducedMotion();
|
|
3046
3230
|
return /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: open && /* @__PURE__ */ jsx(
|
|
3047
3231
|
motion.div,
|
|
@@ -3061,9 +3245,9 @@ var CollapsibleContent = ({
|
|
|
3061
3245
|
) });
|
|
3062
3246
|
};
|
|
3063
3247
|
CollapsibleContent.displayName = "CollapsibleContent";
|
|
3064
|
-
var ITEM_BASE_CLASSES = "group flex min-h-8 items-center gap-2 rounded-[var(--radius-md)] px-2.5 py-1.5 text-[13px] leading-5 transition-[background-color,color,box-shadow,transform]";
|
|
3065
|
-
var ITEM_DEFAULT_CLASSES = "text-sidebar-foreground/72 hover:bg-sidebar-accent hover:text-sidebar-
|
|
3066
|
-
var ITEM_ACTIVE_CLASSES = "bg-sidebar-
|
|
3248
|
+
var ITEM_BASE_CLASSES = "group flex min-h-8 items-center gap-2 rounded-[var(--radius-md)] px-2.5 py-1.5 text-[13px] leading-5 transition-[background-color,color,box-shadow,transform] duration-micro ease-brand";
|
|
3249
|
+
var ITEM_DEFAULT_CLASSES = "text-sidebar-foreground/72 hover:bg-sidebar-accent/55 hover:text-sidebar-foreground";
|
|
3250
|
+
var ITEM_ACTIVE_CLASSES = "bg-sidebar-accent text-sidebar-foreground font-medium shadow-[inset_0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent";
|
|
3067
3251
|
var ITEM_DISABLED_CLASSES = "opacity-50 pointer-events-none";
|
|
3068
3252
|
var ITEM_COLLAPSED_CLASSES = "justify-center px-0 size-8 mx-auto";
|
|
3069
3253
|
var ICON_CLASSES = "size-4 shrink-0";
|
|
@@ -3096,19 +3280,19 @@ function ItemContent({
|
|
|
3096
3280
|
const Icon = item.icon;
|
|
3097
3281
|
if (collapsed) {
|
|
3098
3282
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
3099
|
-
Icon ? /* @__PURE__ */ jsx(Icon, { className: ICON_CLASSES }) : null,
|
|
3283
|
+
Icon ? /* @__PURE__ */ jsx(Icon, { className: cn(ICON_CLASSES, item.isActive && "text-sidebar-primary") }) : null,
|
|
3100
3284
|
/* @__PURE__ */ jsx("span", { className: "sr-only", children: item.label })
|
|
3101
3285
|
] });
|
|
3102
3286
|
}
|
|
3103
3287
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
3104
|
-
Icon ? /* @__PURE__ */ jsx(Icon, { className: ICON_CLASSES }) : null,
|
|
3288
|
+
Icon ? /* @__PURE__ */ jsx(Icon, { className: cn(ICON_CLASSES, item.isActive && "text-sidebar-primary") }) : null,
|
|
3105
3289
|
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: item.label }),
|
|
3106
3290
|
item.badge ? /* @__PURE__ */ jsx(Badge, { variant: item.badge.tone, size: "sm", children: item.badge.label }) : null,
|
|
3107
3291
|
showChevron ? /* @__PURE__ */ jsx(
|
|
3108
3292
|
ChevronRight,
|
|
3109
3293
|
{
|
|
3110
3294
|
className: cn(
|
|
3111
|
-
"size-3.5 shrink-0 text-
|
|
3295
|
+
"size-3.5 shrink-0 text-sidebar-foreground/50 transition-transform duration-micro ease-brand",
|
|
3112
3296
|
chevronOpen && "rotate-90"
|
|
3113
3297
|
),
|
|
3114
3298
|
"aria-hidden": "true"
|
|
@@ -3192,12 +3376,12 @@ function ParentItem({
|
|
|
3192
3376
|
renderLink
|
|
3193
3377
|
}) {
|
|
3194
3378
|
const hasActiveChild = item.children?.some((c) => c.isActive === true) ?? false;
|
|
3195
|
-
const [uncontrolledOpen, setUncontrolledOpen] =
|
|
3379
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React10.useState(
|
|
3196
3380
|
item.isActive === true || hasActiveChild
|
|
3197
3381
|
);
|
|
3198
3382
|
const isControlled = item.expanded !== void 0 && item.onExpandedChange !== void 0;
|
|
3199
3383
|
const open = isControlled ? item.expanded : uncontrolledOpen;
|
|
3200
|
-
const setOpen =
|
|
3384
|
+
const setOpen = React10.useCallback(
|
|
3201
3385
|
(next) => {
|
|
3202
3386
|
if (isControlled) {
|
|
3203
3387
|
item.onExpandedChange?.(next);
|
|
@@ -3256,12 +3440,13 @@ function SidebarNav({
|
|
|
3256
3440
|
itemClassName,
|
|
3257
3441
|
header,
|
|
3258
3442
|
footer,
|
|
3259
|
-
renderLink = defaultRenderLink
|
|
3443
|
+
renderLink = defaultRenderLink,
|
|
3444
|
+
navLabel = "Sidebar"
|
|
3260
3445
|
}) {
|
|
3261
3446
|
return /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxs(
|
|
3262
3447
|
"nav",
|
|
3263
3448
|
{
|
|
3264
|
-
"aria-label":
|
|
3449
|
+
"aria-label": navLabel,
|
|
3265
3450
|
"data-ui": "nebutra-sidebar-nav",
|
|
3266
3451
|
className: cn(
|
|
3267
3452
|
"flex h-full flex-col",
|
|
@@ -3318,13 +3503,13 @@ function SidebarNav({
|
|
|
3318
3503
|
}
|
|
3319
3504
|
) });
|
|
3320
3505
|
}
|
|
3321
|
-
var TerminalContext =
|
|
3322
|
-
var
|
|
3506
|
+
var TerminalContext = React10.createContext(null);
|
|
3507
|
+
var variantStyles = {
|
|
3323
3508
|
default: "bg-muted border border-border",
|
|
3324
3509
|
minimal: "bg-background border border-border",
|
|
3325
3510
|
glass: "bg-muted backdrop-blur-md border border-border"
|
|
3326
3511
|
};
|
|
3327
|
-
var TerminalRoot =
|
|
3512
|
+
var TerminalRoot = React10.forwardRef(
|
|
3328
3513
|
({ className, variant = "default", children, ...props }, ref) => {
|
|
3329
3514
|
return /* @__PURE__ */ jsx(TerminalContext.Provider, { value: { variant }, children: /* @__PURE__ */ jsx(
|
|
3330
3515
|
"div",
|
|
@@ -3332,7 +3517,7 @@ var TerminalRoot = React.forwardRef(
|
|
|
3332
3517
|
ref,
|
|
3333
3518
|
className: cn(
|
|
3334
3519
|
"rounded-[var(--radius-xl)] overflow-hidden font-mono text-sm",
|
|
3335
|
-
|
|
3520
|
+
variantStyles[variant],
|
|
3336
3521
|
className
|
|
3337
3522
|
),
|
|
3338
3523
|
...props,
|
|
@@ -3342,7 +3527,7 @@ var TerminalRoot = React.forwardRef(
|
|
|
3342
3527
|
}
|
|
3343
3528
|
);
|
|
3344
3529
|
TerminalRoot.displayName = "Terminal";
|
|
3345
|
-
var TerminalHeader =
|
|
3530
|
+
var TerminalHeader = React10.forwardRef(
|
|
3346
3531
|
({ className, title, showControls = true, children, ...props }, ref) => {
|
|
3347
3532
|
return /* @__PURE__ */ jsxs(
|
|
3348
3533
|
"div",
|
|
@@ -3367,13 +3552,13 @@ var TerminalHeader = React.forwardRef(
|
|
|
3367
3552
|
}
|
|
3368
3553
|
);
|
|
3369
3554
|
TerminalHeader.displayName = "Terminal.Header";
|
|
3370
|
-
var TerminalBody =
|
|
3555
|
+
var TerminalBody = React10.forwardRef(
|
|
3371
3556
|
({ className, children, ...props }, ref) => {
|
|
3372
3557
|
return /* @__PURE__ */ jsx("div", { ref, className: cn("p-4 space-y-1", className), ...props, children });
|
|
3373
3558
|
}
|
|
3374
3559
|
);
|
|
3375
3560
|
TerminalBody.displayName = "Terminal.Body";
|
|
3376
|
-
var TerminalLine =
|
|
3561
|
+
var TerminalLine = React10.forwardRef(
|
|
3377
3562
|
({ className, prompt = "$", output = false, highlight = false, children, ...props }, ref) => {
|
|
3378
3563
|
return /* @__PURE__ */ jsxs(
|
|
3379
3564
|
"div",
|
|
@@ -3386,7 +3571,7 @@ var TerminalLine = React.forwardRef(
|
|
|
3386
3571
|
),
|
|
3387
3572
|
...props,
|
|
3388
3573
|
children: [
|
|
3389
|
-
!output && /* @__PURE__ */ jsx("span", { className: "text-
|
|
3574
|
+
!output && /* @__PURE__ */ jsx("span", { className: "text-success-strong shrink-0 select-none", children: prompt }),
|
|
3390
3575
|
/* @__PURE__ */ jsx("span", { className: cn("flex-1", output ? "text-muted-foreground" : "text-muted-foreground"), children })
|
|
3391
3576
|
]
|
|
3392
3577
|
}
|
|
@@ -3428,7 +3613,7 @@ function subscribePlatform() {
|
|
|
3428
3613
|
return () => void 0;
|
|
3429
3614
|
}
|
|
3430
3615
|
function usePlatform() {
|
|
3431
|
-
return
|
|
3616
|
+
return React10.useSyncExternalStore(subscribePlatform, getClientPlatform, () => "apple");
|
|
3432
3617
|
}
|
|
3433
3618
|
function normalizeKey(children) {
|
|
3434
3619
|
if (typeof children !== "string") {
|
|
@@ -3502,13 +3687,16 @@ function computeInitials(user) {
|
|
|
3502
3687
|
}
|
|
3503
3688
|
return source.slice(0, 2).toUpperCase();
|
|
3504
3689
|
}
|
|
3505
|
-
function DefaultTrigger({
|
|
3690
|
+
function DefaultTrigger({
|
|
3691
|
+
user,
|
|
3692
|
+
triggerLabel = "Open user menu"
|
|
3693
|
+
}) {
|
|
3506
3694
|
const initials2 = computeInitials(user);
|
|
3507
3695
|
return /* @__PURE__ */ jsx(
|
|
3508
3696
|
"button",
|
|
3509
3697
|
{
|
|
3510
3698
|
type: "button",
|
|
3511
|
-
"aria-label":
|
|
3699
|
+
"aria-label": triggerLabel,
|
|
3512
3700
|
className: cn(
|
|
3513
3701
|
"inline-flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-full",
|
|
3514
3702
|
"outline-none transition-[box-shadow,opacity] hover:opacity-90",
|
|
@@ -3517,7 +3705,7 @@ function DefaultTrigger({ user }) {
|
|
|
3517
3705
|
),
|
|
3518
3706
|
children: /* @__PURE__ */ jsxs(Avatar, { size: "sm", children: [
|
|
3519
3707
|
user.avatarUrl ? /* @__PURE__ */ jsx(AvatarImage, { src: user.avatarUrl, alt: user.name }) : null,
|
|
3520
|
-
/* @__PURE__ */ jsx(AvatarFallback, { size: "sm", className: "bg-primary text-
|
|
3708
|
+
/* @__PURE__ */ jsx(AvatarFallback, { size: "sm", className: "bg-primary text-primary-foreground", children: initials2 })
|
|
3521
3709
|
] })
|
|
3522
3710
|
}
|
|
3523
3711
|
);
|
|
@@ -3538,16 +3726,17 @@ function UserMenu(props) {
|
|
|
3538
3726
|
renderTrigger,
|
|
3539
3727
|
renderLink,
|
|
3540
3728
|
className,
|
|
3541
|
-
align = "end"
|
|
3729
|
+
align = "end",
|
|
3730
|
+
triggerLabel
|
|
3542
3731
|
} = props;
|
|
3543
3732
|
const initials2 = computeInitials(user);
|
|
3544
3733
|
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
3545
|
-
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: renderTrigger ? renderTrigger(user) : /* @__PURE__ */ jsx(DefaultTrigger, { user }) }),
|
|
3734
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: renderTrigger ? renderTrigger(user) : /* @__PURE__ */ jsx(DefaultTrigger, { user, ...triggerLabel !== void 0 ? { triggerLabel } : {} }) }),
|
|
3546
3735
|
/* @__PURE__ */ jsxs(DropdownMenuContent, { align, sideOffset: 8, className: cn("w-[280px] p-1", className), children: [
|
|
3547
3736
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 p-3", children: [
|
|
3548
3737
|
/* @__PURE__ */ jsxs(Avatar, { size: "md", children: [
|
|
3549
3738
|
user.avatarUrl ? /* @__PURE__ */ jsx(AvatarImage, { src: user.avatarUrl, alt: user.name }) : null,
|
|
3550
|
-
/* @__PURE__ */ jsx(AvatarFallback, { size: "md", className: "bg-primary text-
|
|
3739
|
+
/* @__PURE__ */ jsx(AvatarFallback, { size: "md", className: "bg-primary text-primary-foreground", children: initials2 })
|
|
3551
3740
|
] }),
|
|
3552
3741
|
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
3553
3742
|
/* @__PURE__ */ jsx("span", { className: "truncate text-sm font-medium text-foreground", children: user.name }),
|
|
@@ -3561,12 +3750,12 @@ function UserMenu(props) {
|
|
|
3561
3750
|
] }) : null,
|
|
3562
3751
|
groups.map((group, groupIndex) => {
|
|
3563
3752
|
const isLastGroup = groupIndex === groups.length - 1;
|
|
3564
|
-
return /* @__PURE__ */ jsxs(
|
|
3753
|
+
return /* @__PURE__ */ jsxs(React10.Fragment, { children: [
|
|
3565
3754
|
group.label ? /* @__PURE__ */ jsx("div", { className: "px-2 py-1 text-xs font-medium uppercase tracking-wider text-muted-foreground", children: group.label }) : null,
|
|
3566
3755
|
group.items.map((item) => {
|
|
3567
3756
|
const itemClassName = cn(
|
|
3568
3757
|
"flex w-full cursor-pointer items-center",
|
|
3569
|
-
item.destructive && "text-destructive focus:bg-destructive focus:text-destructive-foreground data-[highlighted]:bg-destructive data-[highlighted]:text-destructive-foreground"
|
|
3758
|
+
item.destructive && "text-destructive-strong focus:bg-destructive focus:text-destructive-foreground data-[highlighted]:bg-destructive data-[highlighted]:text-destructive-foreground"
|
|
3570
3759
|
);
|
|
3571
3760
|
if (item.href && !item.disabled) {
|
|
3572
3761
|
const linkContent = /* @__PURE__ */ jsx(UserMenuItemContent, { item });
|
|
@@ -3638,7 +3827,7 @@ function WorkspaceAvatar({ workspace, size = "sm", className }) {
|
|
|
3638
3827
|
AvatarFallback,
|
|
3639
3828
|
{
|
|
3640
3829
|
size,
|
|
3641
|
-
className: "rounded-[var(--radius-md)] bg-primary text-
|
|
3830
|
+
className: "rounded-[var(--radius-md)] bg-primary text-primary-foreground font-semibold",
|
|
3642
3831
|
children: initials2
|
|
3643
3832
|
}
|
|
3644
3833
|
)
|
|
@@ -3650,6 +3839,7 @@ function TriggerButton({
|
|
|
3650
3839
|
showRoleBadge,
|
|
3651
3840
|
disabled,
|
|
3652
3841
|
className,
|
|
3842
|
+
switchLabel = "Switch workspace",
|
|
3653
3843
|
ref
|
|
3654
3844
|
}) {
|
|
3655
3845
|
const isOwner = activeWorkspace.role === "owner";
|
|
@@ -3659,7 +3849,7 @@ function TriggerButton({
|
|
|
3659
3849
|
{
|
|
3660
3850
|
ref,
|
|
3661
3851
|
type: "button",
|
|
3662
|
-
"aria-label":
|
|
3852
|
+
"aria-label": switchLabel,
|
|
3663
3853
|
disabled,
|
|
3664
3854
|
className: cn(
|
|
3665
3855
|
"inline-flex items-center gap-1 rounded-[var(--radius-md)] p-1 outline-none transition-colors",
|
|
@@ -3680,7 +3870,7 @@ function TriggerButton({
|
|
|
3680
3870
|
{
|
|
3681
3871
|
ref,
|
|
3682
3872
|
type: "button",
|
|
3683
|
-
"aria-label":
|
|
3873
|
+
"aria-label": switchLabel,
|
|
3684
3874
|
disabled,
|
|
3685
3875
|
className: cn(
|
|
3686
3876
|
"inline-flex w-full items-center gap-2 rounded-[var(--radius-md)] border border-border bg-background px-2 py-1 text-left outline-none transition-colors",
|
|
@@ -3715,8 +3905,8 @@ function WorkspaceItem({ workspace, isActive, onSelect }) {
|
|
|
3715
3905
|
"span",
|
|
3716
3906
|
{
|
|
3717
3907
|
className: cn(
|
|
3718
|
-
"truncate
|
|
3719
|
-
isActive ? "
|
|
3908
|
+
"truncate font-medium text-sm",
|
|
3909
|
+
isActive ? "text-foreground" : "text-foreground/80"
|
|
3720
3910
|
),
|
|
3721
3911
|
children: workspace.name
|
|
3722
3912
|
}
|
|
@@ -3741,7 +3931,8 @@ function WorkspaceSwitcher({
|
|
|
3741
3931
|
headerSlot,
|
|
3742
3932
|
className,
|
|
3743
3933
|
showRoleBadge = true,
|
|
3744
|
-
disabled = false
|
|
3934
|
+
disabled = false,
|
|
3935
|
+
switchLabel
|
|
3745
3936
|
}) {
|
|
3746
3937
|
const activeWorkspace = workspaces.find((ws) => ws.id === activeWorkspaceId) ?? workspaces[0];
|
|
3747
3938
|
const handleSelect = (id) => {
|
|
@@ -3772,7 +3963,8 @@ function WorkspaceSwitcher({
|
|
|
3772
3963
|
variant,
|
|
3773
3964
|
showRoleBadge,
|
|
3774
3965
|
disabled,
|
|
3775
|
-
className
|
|
3966
|
+
className,
|
|
3967
|
+
...switchLabel !== void 0 ? { switchLabel } : {}
|
|
3776
3968
|
}
|
|
3777
3969
|
) }),
|
|
3778
3970
|
/* @__PURE__ */ jsxs(
|