@nebutra/ui 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/dist/components/index.d.ts +380 -0
- package/dist/components/index.js +2398 -0
- package/dist/components/index.js.map +1 -0
- package/dist/hooks/index.d.ts +106 -0
- package/dist/hooks/index.js +182 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/icons/index.d.ts +3 -0
- package/dist/icons/index.js +5 -0
- package/dist/icons/index.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/layout/index.d.ts +296 -0
- package/dist/layout/index.js +1303 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/layouts/index.d.ts +161 -0
- package/dist/layouts/index.js +611 -0
- package/dist/layouts/index.js.map +1 -0
- package/dist/patterns/index.d.ts +363 -0
- package/dist/patterns/index.js +3004 -0
- package/dist/patterns/index.js.map +1 -0
- package/dist/primitives/index.d.ts +9588 -0
- package/dist/primitives/index.js +26779 -0
- package/dist/primitives/index.js.map +1 -0
- package/dist/styles/brand-override.css +61 -0
- package/dist/tailwind.preset.d.ts +251 -0
- package/dist/tailwind.preset.js +273 -0
- package/dist/tailwind.preset.js.map +1 -0
- package/dist/theme/index.d.ts +150 -0
- package/dist/theme/index.js +28 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/typography/fonts.css +110 -0
- package/dist/typography/index.d.ts +425 -0
- package/dist/typography/index.js +374 -0
- package/dist/typography/index.js.map +1 -0
- package/dist/utils/index.d.ts +61 -0
- package/dist/utils/index.js +55 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +16 -6
|
@@ -0,0 +1,1303 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Cross, Warning, External, Menu } from '@nebutra/icons';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { createContext, useState, useEffect, useMemo, useCallback } from 'react';
|
|
5
|
+
import { Dialog } from '@base-ui/react/dialog';
|
|
6
|
+
import { cva } from 'class-variance-authority';
|
|
7
|
+
import { colors } from '@nebutra/brand';
|
|
8
|
+
import { clsx } from 'clsx';
|
|
9
|
+
import { twMerge } from 'tailwind-merge';
|
|
10
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
11
|
+
import Link from 'next/link';
|
|
12
|
+
|
|
13
|
+
// src/layout/app-shell.tsx
|
|
14
|
+
({
|
|
15
|
+
// Nebutra Blue (云毓蓝) — technology & trust — VI: #0033FE
|
|
16
|
+
blue50: colors.primary[50],
|
|
17
|
+
blue100: colors.primary[100],
|
|
18
|
+
blue200: colors.primary[200],
|
|
19
|
+
blue300: colors.primary[300],
|
|
20
|
+
blue400: colors.primary[400],
|
|
21
|
+
blue500: colors.primary[500],
|
|
22
|
+
// brand primary
|
|
23
|
+
blue600: colors.primary[600],
|
|
24
|
+
blue700: colors.primary[700],
|
|
25
|
+
blue800: colors.primary[800],
|
|
26
|
+
blue900: colors.primary[900],
|
|
27
|
+
blue950: colors.primary[950],
|
|
28
|
+
// Nebutra Cyan (云毓青) — data flow & intelligence — VI: #0BF1C3
|
|
29
|
+
cyan50: colors.accent[50],
|
|
30
|
+
cyan100: colors.accent[100],
|
|
31
|
+
cyan200: colors.accent[200],
|
|
32
|
+
cyan300: colors.accent[300],
|
|
33
|
+
cyan400: colors.accent[400],
|
|
34
|
+
cyan500: colors.accent[500],
|
|
35
|
+
// brand secondary
|
|
36
|
+
cyan600: colors.accent[600],
|
|
37
|
+
cyan700: colors.accent[700],
|
|
38
|
+
cyan800: colors.accent[800],
|
|
39
|
+
cyan900: colors.accent[900],
|
|
40
|
+
cyan950: colors.accent[950],
|
|
41
|
+
// Neutral (blue-undertone gray scale)
|
|
42
|
+
neutral50: colors.neutral[50],
|
|
43
|
+
neutral100: colors.neutral[100],
|
|
44
|
+
neutral200: colors.neutral[200],
|
|
45
|
+
neutral300: colors.neutral[300],
|
|
46
|
+
neutral400: colors.neutral[400],
|
|
47
|
+
neutral500: colors.neutral[500],
|
|
48
|
+
neutral600: colors.neutral[600],
|
|
49
|
+
neutral700: colors.neutral[700],
|
|
50
|
+
neutral800: colors.neutral[800],
|
|
51
|
+
neutral900: colors.neutral[900],
|
|
52
|
+
neutral950: colors.neutral[950],
|
|
53
|
+
white: colors.white,
|
|
54
|
+
black: colors.black
|
|
55
|
+
});
|
|
56
|
+
({
|
|
57
|
+
/** Hero sections, primary CTA buttons, logo fills — VI signature gradient */
|
|
58
|
+
primary: colors.gradient.primary,
|
|
59
|
+
/** Hover states, secondary gradient elements */
|
|
60
|
+
reverse: colors.gradient.primaryReverse,
|
|
61
|
+
/** Vertical layout dividers, page section separators */
|
|
62
|
+
vertical: colors.gradient.primaryVertical,
|
|
63
|
+
/** Background halos, focus glow effects, radial emphasis */
|
|
64
|
+
radial: colors.gradient.primaryRadial});
|
|
65
|
+
var primitiveSpacing = {
|
|
66
|
+
1: 4,
|
|
67
|
+
2: 8,
|
|
68
|
+
3: 12,
|
|
69
|
+
4: 16,
|
|
70
|
+
5: 20,
|
|
71
|
+
6: 24,
|
|
72
|
+
8: 32,
|
|
73
|
+
10: 40,
|
|
74
|
+
12: 48,
|
|
75
|
+
14: 56,
|
|
76
|
+
16: 64,
|
|
77
|
+
24: 96
|
|
78
|
+
};
|
|
79
|
+
var primitiveSizing = {
|
|
80
|
+
sm: 32,
|
|
81
|
+
lg: 48,
|
|
82
|
+
"2xl": 80
|
|
83
|
+
};
|
|
84
|
+
var primitiveRadius = {
|
|
85
|
+
md: 6,
|
|
86
|
+
// Geist default — slightly more rounded than 4px
|
|
87
|
+
lg: 8,
|
|
88
|
+
"2xl": 16};
|
|
89
|
+
var primitiveFontSize = {
|
|
90
|
+
xs: 12,
|
|
91
|
+
sm: 14,
|
|
92
|
+
base: 16,
|
|
93
|
+
lg: 18};
|
|
94
|
+
var primitiveFontWeight = {
|
|
95
|
+
semibold: 600};
|
|
96
|
+
var primitiveTransition = {
|
|
97
|
+
duration: {
|
|
98
|
+
// standard state transitions (default)
|
|
99
|
+
reveal: 300},
|
|
100
|
+
easing: {
|
|
101
|
+
inOut: "cubic-bezier(0.4, 0, 0.2, 1)"
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// src/tokens/components/sheet.ts
|
|
106
|
+
var sheetTokens = {
|
|
107
|
+
inset: primitiveSpacing[3],
|
|
108
|
+
sideWidth: primitiveSizing["2xl"] * 6 + primitiveSpacing[8],
|
|
109
|
+
// 512px
|
|
110
|
+
edgeHeight: primitiveSizing["2xl"] * 4,
|
|
111
|
+
// 320px
|
|
112
|
+
paddingX: primitiveSpacing[6],
|
|
113
|
+
paddingY: primitiveSpacing[5],
|
|
114
|
+
bodyPaddingY: primitiveSpacing[4],
|
|
115
|
+
gap: primitiveSpacing[4],
|
|
116
|
+
headerGap: primitiveSpacing[1] + 2,
|
|
117
|
+
footerGap: primitiveSpacing[2],
|
|
118
|
+
radius: primitiveRadius["2xl"],
|
|
119
|
+
close: {
|
|
120
|
+
size: primitiveSizing.sm,
|
|
121
|
+
iconSize: primitiveFontSize.base,
|
|
122
|
+
offset: primitiveSpacing[4],
|
|
123
|
+
radius: primitiveRadius.md
|
|
124
|
+
},
|
|
125
|
+
overlay: {
|
|
126
|
+
background: "hsl(var(--background) / 0.68)",
|
|
127
|
+
blur: "blur(6px)"
|
|
128
|
+
},
|
|
129
|
+
surface: {
|
|
130
|
+
background: "hsl(var(--popover))",
|
|
131
|
+
shadow: "var(--elevation-xl)"
|
|
132
|
+
},
|
|
133
|
+
motion: {
|
|
134
|
+
duration: primitiveTransition.duration.reveal,
|
|
135
|
+
easing: primitiveTransition.easing.inOut
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
function cn(...inputs) {
|
|
139
|
+
return twMerge(clsx(inputs));
|
|
140
|
+
}
|
|
141
|
+
function getSheetStyle(style) {
|
|
142
|
+
return {
|
|
143
|
+
"--sheet-inset": `${sheetTokens.inset}px`,
|
|
144
|
+
"--sheet-side-width": `${sheetTokens.sideWidth}px`,
|
|
145
|
+
"--sheet-edge-height": `${sheetTokens.edgeHeight}px`,
|
|
146
|
+
"--sheet-padding-x": `${sheetTokens.paddingX}px`,
|
|
147
|
+
"--sheet-padding-y": `${sheetTokens.paddingY}px`,
|
|
148
|
+
"--sheet-body-padding-y": `${sheetTokens.bodyPaddingY}px`,
|
|
149
|
+
"--sheet-gap": `${sheetTokens.gap}px`,
|
|
150
|
+
"--sheet-header-gap": `${sheetTokens.headerGap}px`,
|
|
151
|
+
"--sheet-footer-gap": `${sheetTokens.footerGap}px`,
|
|
152
|
+
"--sheet-radius": `${sheetTokens.radius}px`,
|
|
153
|
+
"--sheet-close-size": `${sheetTokens.close.size}px`,
|
|
154
|
+
"--sheet-close-icon-size": `${sheetTokens.close.iconSize}px`,
|
|
155
|
+
"--sheet-close-offset": `${sheetTokens.close.offset}px`,
|
|
156
|
+
"--sheet-close-radius": `${sheetTokens.close.radius}px`,
|
|
157
|
+
"--sheet-overlay-background": sheetTokens.overlay.background,
|
|
158
|
+
"--sheet-overlay-blur": sheetTokens.overlay.blur,
|
|
159
|
+
"--sheet-background": sheetTokens.surface.background,
|
|
160
|
+
"--sheet-shadow": sheetTokens.surface.shadow,
|
|
161
|
+
"--sheet-duration": `${sheetTokens.motion.duration}ms`,
|
|
162
|
+
"--sheet-easing": sheetTokens.motion.easing,
|
|
163
|
+
...style
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function Sheet({ modal = "trap-focus", disablePointerDismissal = true, ...props }) {
|
|
167
|
+
return /* @__PURE__ */ jsx(
|
|
168
|
+
Dialog.Root,
|
|
169
|
+
{
|
|
170
|
+
"data-slot": "sheet",
|
|
171
|
+
modal,
|
|
172
|
+
disablePointerDismissal,
|
|
173
|
+
...props
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
Sheet.displayName = "Sheet";
|
|
178
|
+
var SheetTrigger = React.forwardRef(
|
|
179
|
+
({ asChild, children, ...props }, ref) => {
|
|
180
|
+
if (asChild && React.isValidElement(children)) {
|
|
181
|
+
return /* @__PURE__ */ jsx(
|
|
182
|
+
Dialog.Trigger,
|
|
183
|
+
{
|
|
184
|
+
ref,
|
|
185
|
+
"data-slot": "sheet-trigger",
|
|
186
|
+
...props,
|
|
187
|
+
render: children
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
return /* @__PURE__ */ jsx(Dialog.Trigger, { ref, "data-slot": "sheet-trigger", ...props, children });
|
|
192
|
+
}
|
|
193
|
+
);
|
|
194
|
+
SheetTrigger.displayName = "SheetTrigger";
|
|
195
|
+
var SheetClose = React.forwardRef(
|
|
196
|
+
({ asChild, children, ...props }, ref) => {
|
|
197
|
+
if (asChild && React.isValidElement(children)) {
|
|
198
|
+
return /* @__PURE__ */ jsx(
|
|
199
|
+
Dialog.Close,
|
|
200
|
+
{
|
|
201
|
+
ref,
|
|
202
|
+
"data-slot": "sheet-close",
|
|
203
|
+
...props,
|
|
204
|
+
render: children
|
|
205
|
+
}
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
return /* @__PURE__ */ jsx(Dialog.Close, { ref, "data-slot": "sheet-close", ...props, children });
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
SheetClose.displayName = "SheetClose";
|
|
212
|
+
function SheetPortal(props) {
|
|
213
|
+
return /* @__PURE__ */ jsx(Dialog.Portal, { "data-slot": "sheet-portal", ...props });
|
|
214
|
+
}
|
|
215
|
+
SheetPortal.displayName = "SheetPortal";
|
|
216
|
+
var SheetOverlay = React.forwardRef(
|
|
217
|
+
({ className, style, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
218
|
+
Dialog.Backdrop,
|
|
219
|
+
{
|
|
220
|
+
ref,
|
|
221
|
+
"data-slot": "sheet-overlay",
|
|
222
|
+
className: cn(
|
|
223
|
+
"fixed inset-0 z-50 bg-[var(--sheet-overlay-background)] backdrop-blur-[var(--sheet-overlay-blur)]",
|
|
224
|
+
"transition-[opacity,backdrop-filter,display] duration-[var(--sheet-duration)] ease-[var(--sheet-easing)]",
|
|
225
|
+
"data-ending-style:opacity-0 data-starting-style:opacity-0 motion-reduce:transition-none",
|
|
226
|
+
className
|
|
227
|
+
),
|
|
228
|
+
style: getSheetStyle(style),
|
|
229
|
+
...props
|
|
230
|
+
}
|
|
231
|
+
)
|
|
232
|
+
);
|
|
233
|
+
SheetOverlay.displayName = "SheetOverlay";
|
|
234
|
+
var sheetVariants = cva(
|
|
235
|
+
[
|
|
236
|
+
"fixed z-50 flex flex-col overflow-hidden border border-border bg-[var(--sheet-background)] text-foreground shadow-[var(--sheet-shadow)] outline-none",
|
|
237
|
+
"transition-[opacity,transform,display] duration-[var(--sheet-duration)] ease-[var(--sheet-easing)]",
|
|
238
|
+
"data-ending-style:opacity-0 data-starting-style:opacity-0 motion-reduce:transition-none"
|
|
239
|
+
].join(" "),
|
|
240
|
+
{
|
|
241
|
+
variants: {
|
|
242
|
+
side: {
|
|
243
|
+
top: "inset-x-[var(--sheet-inset)] top-[var(--sheet-inset)] max-h-[min(var(--sheet-edge-height),calc(100dvh_-_var(--sheet-inset)_-_var(--sheet-inset)))] rounded-[var(--sheet-radius)] data-ending-style:-translate-y-full data-starting-style:-translate-y-full",
|
|
244
|
+
bottom: "inset-x-[var(--sheet-inset)] bottom-[var(--sheet-inset)] max-h-[min(var(--sheet-edge-height),calc(100dvh_-_var(--sheet-inset)_-_var(--sheet-inset)))] rounded-[var(--sheet-radius)] data-ending-style:translate-y-full data-starting-style:translate-y-full",
|
|
245
|
+
left: "inset-y-[var(--sheet-inset)] left-[var(--sheet-inset)] h-[calc(100dvh_-_var(--sheet-inset)_-_var(--sheet-inset))] w-[min(var(--sheet-side-width),calc(100vw_-_var(--sheet-inset)_-_var(--sheet-inset)))] rounded-[var(--sheet-radius)] data-ending-style:-translate-x-full data-starting-style:-translate-x-full",
|
|
246
|
+
right: "inset-y-[var(--sheet-inset)] right-[var(--sheet-inset)] h-[calc(100dvh_-_var(--sheet-inset)_-_var(--sheet-inset))] w-[min(var(--sheet-side-width),calc(100vw_-_var(--sheet-inset)_-_var(--sheet-inset)))] rounded-[var(--sheet-radius)] data-ending-style:translate-x-full data-starting-style:translate-x-full"
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
defaultVariants: {
|
|
250
|
+
side: "right"
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
var SheetContent = React.forwardRef(
|
|
255
|
+
({
|
|
256
|
+
side = "right",
|
|
257
|
+
className,
|
|
258
|
+
children,
|
|
259
|
+
overlay = true,
|
|
260
|
+
noOverlay = false,
|
|
261
|
+
showClose,
|
|
262
|
+
close,
|
|
263
|
+
style,
|
|
264
|
+
...props
|
|
265
|
+
}, ref) => {
|
|
266
|
+
const shouldRenderClose = close ?? showClose ?? true;
|
|
267
|
+
const shouldRenderOverlay = overlay && !noOverlay;
|
|
268
|
+
return /* @__PURE__ */ jsxs(SheetPortal, { children: [
|
|
269
|
+
shouldRenderOverlay ? /* @__PURE__ */ jsx(SheetOverlay, {}) : null,
|
|
270
|
+
/* @__PURE__ */ jsxs(
|
|
271
|
+
Dialog.Popup,
|
|
272
|
+
{
|
|
273
|
+
ref,
|
|
274
|
+
"data-slot": "sheet-content",
|
|
275
|
+
className: cn(sheetVariants({ side }), className),
|
|
276
|
+
style: getSheetStyle(style),
|
|
277
|
+
...props,
|
|
278
|
+
children: [
|
|
279
|
+
children,
|
|
280
|
+
shouldRenderClose ? /* @__PURE__ */ jsxs(
|
|
281
|
+
SheetClose,
|
|
282
|
+
{
|
|
283
|
+
"aria-label": "Close",
|
|
284
|
+
className: cn(
|
|
285
|
+
"absolute right-[var(--sheet-close-offset)] top-[var(--sheet-close-offset)] inline-flex size-[var(--sheet-close-size)] items-center justify-center rounded-[var(--sheet-close-radius)] text-muted-foreground",
|
|
286
|
+
"transition-[background-color,color,box-shadow] duration-[var(--sheet-duration)] ease-[var(--sheet-easing)] hover:bg-muted hover:text-foreground",
|
|
287
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none motion-reduce:transition-none"
|
|
288
|
+
),
|
|
289
|
+
children: [
|
|
290
|
+
/* @__PURE__ */ jsx(Cross, { "aria-hidden": "true", className: "size-[var(--sheet-close-icon-size)]" }),
|
|
291
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
292
|
+
]
|
|
293
|
+
}
|
|
294
|
+
) : null
|
|
295
|
+
]
|
|
296
|
+
}
|
|
297
|
+
)
|
|
298
|
+
] });
|
|
299
|
+
}
|
|
300
|
+
);
|
|
301
|
+
SheetContent.displayName = "SheetContent";
|
|
302
|
+
var SheetHeader = React.forwardRef(
|
|
303
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
304
|
+
"div",
|
|
305
|
+
{
|
|
306
|
+
ref,
|
|
307
|
+
"data-slot": "sheet-header",
|
|
308
|
+
className: cn(
|
|
309
|
+
"grid gap-[var(--sheet-header-gap)] border-b border-border px-[var(--sheet-padding-x)] py-[var(--sheet-padding-y)] pr-[calc(var(--sheet-padding-x)_+_var(--sheet-close-size))] text-left",
|
|
310
|
+
className
|
|
311
|
+
),
|
|
312
|
+
...props
|
|
313
|
+
}
|
|
314
|
+
)
|
|
315
|
+
);
|
|
316
|
+
SheetHeader.displayName = "SheetHeader";
|
|
317
|
+
var SheetBody = React.forwardRef(
|
|
318
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
319
|
+
"div",
|
|
320
|
+
{
|
|
321
|
+
ref,
|
|
322
|
+
"data-slot": "sheet-body",
|
|
323
|
+
className: cn(
|
|
324
|
+
"min-h-0 flex-1 overflow-y-auto overscroll-contain px-[var(--sheet-padding-x)] py-[var(--sheet-body-padding-y)]",
|
|
325
|
+
className
|
|
326
|
+
),
|
|
327
|
+
...props
|
|
328
|
+
}
|
|
329
|
+
)
|
|
330
|
+
);
|
|
331
|
+
SheetBody.displayName = "SheetBody";
|
|
332
|
+
var SheetFooter = React.forwardRef(
|
|
333
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
334
|
+
"div",
|
|
335
|
+
{
|
|
336
|
+
ref,
|
|
337
|
+
"data-slot": "sheet-footer",
|
|
338
|
+
className: cn(
|
|
339
|
+
"mt-auto flex flex-col-reverse gap-[var(--sheet-footer-gap)] border-t border-border px-[var(--sheet-padding-x)] py-[var(--sheet-padding-y)] sm:flex-row sm:justify-end",
|
|
340
|
+
className
|
|
341
|
+
),
|
|
342
|
+
...props
|
|
343
|
+
}
|
|
344
|
+
)
|
|
345
|
+
);
|
|
346
|
+
SheetFooter.displayName = "SheetFooter";
|
|
347
|
+
var SheetTitle = React.forwardRef(
|
|
348
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
349
|
+
Dialog.Title,
|
|
350
|
+
{
|
|
351
|
+
ref,
|
|
352
|
+
"data-slot": "sheet-title",
|
|
353
|
+
className: cn("font-semibold text-base leading-6 text-foreground", className),
|
|
354
|
+
...props
|
|
355
|
+
}
|
|
356
|
+
)
|
|
357
|
+
);
|
|
358
|
+
SheetTitle.displayName = "SheetTitle";
|
|
359
|
+
var SheetDescription = React.forwardRef(
|
|
360
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
361
|
+
Dialog.Description,
|
|
362
|
+
{
|
|
363
|
+
ref,
|
|
364
|
+
"data-slot": "sheet-description",
|
|
365
|
+
className: cn("text-muted-foreground text-sm leading-5", className),
|
|
366
|
+
...props
|
|
367
|
+
}
|
|
368
|
+
)
|
|
369
|
+
);
|
|
370
|
+
SheetDescription.displayName = "SheetDescription";
|
|
371
|
+
var DEFAULT_SIDEBAR_WIDTH = 224;
|
|
372
|
+
var DEFAULT_COLLAPSED_WIDTH = 52;
|
|
373
|
+
var DEFAULT_HEADER_HEIGHT = 48;
|
|
374
|
+
function AppShell({
|
|
375
|
+
sidebar,
|
|
376
|
+
header,
|
|
377
|
+
children,
|
|
378
|
+
sidebarWidth = DEFAULT_SIDEBAR_WIDTH,
|
|
379
|
+
sidebarCollapsedWidth = DEFAULT_COLLAPSED_WIDTH,
|
|
380
|
+
collapsed,
|
|
381
|
+
defaultCollapsed = false,
|
|
382
|
+
onCollapsedChange,
|
|
383
|
+
headerHeight = DEFAULT_HEADER_HEIGHT,
|
|
384
|
+
contentClassName,
|
|
385
|
+
className
|
|
386
|
+
}) {
|
|
387
|
+
const isControlled = collapsed !== void 0;
|
|
388
|
+
const [internalCollapsed] = React.useState(defaultCollapsed);
|
|
389
|
+
const isCollapsed = isControlled ? collapsed : internalCollapsed;
|
|
390
|
+
const lastReportedRef = React.useRef(isCollapsed);
|
|
391
|
+
React.useEffect(() => {
|
|
392
|
+
if (lastReportedRef.current !== isCollapsed) {
|
|
393
|
+
lastReportedRef.current = isCollapsed;
|
|
394
|
+
onCollapsedChange?.(isCollapsed);
|
|
395
|
+
}
|
|
396
|
+
}, [isCollapsed, onCollapsedChange]);
|
|
397
|
+
const [mobileOpen, setMobileOpen] = React.useState(false);
|
|
398
|
+
const railWidth = isCollapsed ? sidebarCollapsedWidth : sidebarWidth;
|
|
399
|
+
return /* @__PURE__ */ jsxs(
|
|
400
|
+
"div",
|
|
401
|
+
{
|
|
402
|
+
className: cn("relative flex min-h-screen w-full bg-background text-foreground", className),
|
|
403
|
+
children: [
|
|
404
|
+
/* @__PURE__ */ jsx(
|
|
405
|
+
"aside",
|
|
406
|
+
{
|
|
407
|
+
"aria-label": "Primary",
|
|
408
|
+
className: cn(
|
|
409
|
+
"hidden shrink-0 overflow-hidden border-r border-neutral-4 bg-neutral-2/80 md:block",
|
|
410
|
+
"transition-[width] duration-200 ease-out"
|
|
411
|
+
),
|
|
412
|
+
style: { width: railWidth },
|
|
413
|
+
children: /* @__PURE__ */ jsx(
|
|
414
|
+
"div",
|
|
415
|
+
{
|
|
416
|
+
className: "h-full overflow-y-auto",
|
|
417
|
+
style: { width: isCollapsed ? sidebarCollapsedWidth : sidebarWidth },
|
|
418
|
+
children: sidebar
|
|
419
|
+
}
|
|
420
|
+
)
|
|
421
|
+
}
|
|
422
|
+
),
|
|
423
|
+
/* @__PURE__ */ jsx(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: /* @__PURE__ */ jsx(SheetContent, { side: "left", className: "w-72 border-r border-neutral-4 bg-neutral-2 p-0", children: /* @__PURE__ */ jsx("div", { className: "h-full overflow-y-auto", children: sidebar }) }) }),
|
|
424
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
425
|
+
header !== void 0 && /* @__PURE__ */ jsxs(
|
|
426
|
+
"header",
|
|
427
|
+
{
|
|
428
|
+
className: cn(
|
|
429
|
+
"sticky top-0 z-30 flex items-center gap-2 border-b border-border",
|
|
430
|
+
"bg-background/85 px-3 backdrop-blur supports-[backdrop-filter]:bg-background/70 sm:px-4"
|
|
431
|
+
),
|
|
432
|
+
style: { height: headerHeight },
|
|
433
|
+
children: [
|
|
434
|
+
/* @__PURE__ */ jsx(
|
|
435
|
+
"button",
|
|
436
|
+
{
|
|
437
|
+
type: "button",
|
|
438
|
+
"aria-label": "Open navigation menu",
|
|
439
|
+
onClick: () => setMobileOpen(true),
|
|
440
|
+
className: cn(
|
|
441
|
+
"relative inline-flex size-8 items-center justify-center rounded-md text-foreground/80 after:absolute after:-inset-1.5 after:content-['']",
|
|
442
|
+
"hover:bg-muted hover:text-foreground md:hidden",
|
|
443
|
+
"focus:outline-none focus:ring-2 focus:ring-offset-1"
|
|
444
|
+
),
|
|
445
|
+
children: /* @__PURE__ */ jsx(Menu, { className: "size-4", "aria-hidden": "true" })
|
|
446
|
+
}
|
|
447
|
+
),
|
|
448
|
+
/* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: header })
|
|
449
|
+
]
|
|
450
|
+
}
|
|
451
|
+
),
|
|
452
|
+
header === void 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center border-b border-border bg-background px-4 py-2 md:hidden", children: /* @__PURE__ */ jsx(
|
|
453
|
+
"button",
|
|
454
|
+
{
|
|
455
|
+
type: "button",
|
|
456
|
+
"aria-label": "Open navigation menu",
|
|
457
|
+
onClick: () => setMobileOpen(true),
|
|
458
|
+
className: cn(
|
|
459
|
+
"relative inline-flex size-8 items-center justify-center rounded-md text-foreground/80 after:absolute after:-inset-1.5 after:content-['']",
|
|
460
|
+
"hover:bg-muted hover:text-foreground",
|
|
461
|
+
"focus:outline-none focus:ring-2 focus:ring-offset-1"
|
|
462
|
+
),
|
|
463
|
+
children: /* @__PURE__ */ jsx(Menu, { className: "size-4", "aria-hidden": "true" })
|
|
464
|
+
}
|
|
465
|
+
) }),
|
|
466
|
+
/* @__PURE__ */ jsx(
|
|
467
|
+
"main",
|
|
468
|
+
{
|
|
469
|
+
className: cn("w-full max-w-none px-3 py-4 sm:px-4 md:px-5 2xl:px-6", contentClassName),
|
|
470
|
+
children
|
|
471
|
+
}
|
|
472
|
+
)
|
|
473
|
+
] })
|
|
474
|
+
]
|
|
475
|
+
}
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
function Card({ children, isInteractive = false, className }) {
|
|
479
|
+
return /* @__PURE__ */ jsx(
|
|
480
|
+
"div",
|
|
481
|
+
{
|
|
482
|
+
className: cn(
|
|
483
|
+
"rounded-lg border border-[color:var(--neutral-7)] bg-[color:var(--neutral-1)] p-4 text-[color:var(--neutral-12)] shadow-sm dark:border-white/10 dark:bg-black/40 dark:text-white",
|
|
484
|
+
isInteractive && "cursor-pointer transition-shadow hover:shadow-md",
|
|
485
|
+
className
|
|
486
|
+
),
|
|
487
|
+
children
|
|
488
|
+
}
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
var sizeClasses = {
|
|
492
|
+
sm: "max-w-screen-sm",
|
|
493
|
+
md: "max-w-screen-md",
|
|
494
|
+
lg: "max-w-screen-lg",
|
|
495
|
+
xl: "max-w-screen-xl",
|
|
496
|
+
full: "max-w-full"
|
|
497
|
+
};
|
|
498
|
+
function Container({ children, size = "lg", className }) {
|
|
499
|
+
return /* @__PURE__ */ jsx("div", { className: cn("mx-auto w-full px-4", sizeClasses[size], className), children });
|
|
500
|
+
}
|
|
501
|
+
var DesignSystemContext = createContext(null);
|
|
502
|
+
function DesignSystemProvider({
|
|
503
|
+
children,
|
|
504
|
+
defaultMode = "system",
|
|
505
|
+
storageKey = "nebutra-theme-mode",
|
|
506
|
+
enableSystemPreference = true
|
|
507
|
+
}) {
|
|
508
|
+
const [mode, setModeState] = useState(defaultMode);
|
|
509
|
+
const [systemPreference, setSystemPreference] = useState("light");
|
|
510
|
+
useEffect(() => {
|
|
511
|
+
if (typeof window === "undefined" || !enableSystemPreference) return;
|
|
512
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
513
|
+
setSystemPreference(mediaQuery.matches ? "dark" : "light");
|
|
514
|
+
const handler = (e) => {
|
|
515
|
+
setSystemPreference(e.matches ? "dark" : "light");
|
|
516
|
+
};
|
|
517
|
+
mediaQuery.addEventListener("change", handler);
|
|
518
|
+
return () => mediaQuery.removeEventListener("change", handler);
|
|
519
|
+
}, [enableSystemPreference]);
|
|
520
|
+
useEffect(() => {
|
|
521
|
+
if (typeof window === "undefined") return;
|
|
522
|
+
const stored = localStorage.getItem(storageKey);
|
|
523
|
+
if (stored && ["light", "dark", "system"].includes(stored)) {
|
|
524
|
+
setModeState(stored);
|
|
525
|
+
}
|
|
526
|
+
}, [storageKey]);
|
|
527
|
+
const resolvedMode = useMemo(() => {
|
|
528
|
+
if (mode === "system") {
|
|
529
|
+
return systemPreference;
|
|
530
|
+
}
|
|
531
|
+
return mode;
|
|
532
|
+
}, [mode, systemPreference]);
|
|
533
|
+
const setMode = useCallback(
|
|
534
|
+
(newMode) => {
|
|
535
|
+
setModeState(newMode);
|
|
536
|
+
if (typeof window !== "undefined") {
|
|
537
|
+
localStorage.setItem(storageKey, newMode);
|
|
538
|
+
}
|
|
539
|
+
},
|
|
540
|
+
[storageKey]
|
|
541
|
+
);
|
|
542
|
+
const toggleMode = useCallback(() => {
|
|
543
|
+
setMode(resolvedMode === "light" ? "dark" : "light");
|
|
544
|
+
}, [resolvedMode, setMode]);
|
|
545
|
+
const contextValue = useMemo(
|
|
546
|
+
() => ({
|
|
547
|
+
mode,
|
|
548
|
+
setMode,
|
|
549
|
+
toggleMode,
|
|
550
|
+
resolvedMode
|
|
551
|
+
}),
|
|
552
|
+
[mode, resolvedMode, setMode, toggleMode]
|
|
553
|
+
);
|
|
554
|
+
return /* @__PURE__ */ jsx(DesignSystemContext.Provider, { value: contextValue, children });
|
|
555
|
+
}
|
|
556
|
+
var SIZE_MAP = {
|
|
557
|
+
sm: { box: "h-8 w-8", halo: "h-16 w-16 -inset-4", glyph: "h-3.5 w-3.5" },
|
|
558
|
+
md: { box: "h-10 w-10", halo: "h-20 w-20 -inset-5", glyph: "h-4 w-4" },
|
|
559
|
+
lg: { box: "h-14 w-14", halo: "h-28 w-28 -inset-7", glyph: "h-5 w-5" },
|
|
560
|
+
xl: { box: "h-20 w-20", halo: "h-40 w-40 -inset-10", glyph: "h-7 w-7" }
|
|
561
|
+
};
|
|
562
|
+
function BrandMark({
|
|
563
|
+
children,
|
|
564
|
+
variant = "gradient",
|
|
565
|
+
size = "md",
|
|
566
|
+
className,
|
|
567
|
+
halo = false,
|
|
568
|
+
ariaHidden = true
|
|
569
|
+
}) {
|
|
570
|
+
const sizes = SIZE_MAP[size];
|
|
571
|
+
return /* @__PURE__ */ jsxs(
|
|
572
|
+
"span",
|
|
573
|
+
{
|
|
574
|
+
"aria-hidden": ariaHidden,
|
|
575
|
+
className: cn("relative inline-flex shrink-0 items-center justify-center", className),
|
|
576
|
+
children: [
|
|
577
|
+
halo && /* @__PURE__ */ jsx(
|
|
578
|
+
"span",
|
|
579
|
+
{
|
|
580
|
+
"aria-hidden": "true",
|
|
581
|
+
className: cn(
|
|
582
|
+
"pointer-events-none absolute rounded-full opacity-30 blur-2xl",
|
|
583
|
+
sizes.halo
|
|
584
|
+
),
|
|
585
|
+
style: { background: "var(--brand-gradient)" }
|
|
586
|
+
}
|
|
587
|
+
),
|
|
588
|
+
/* @__PURE__ */ jsx(
|
|
589
|
+
"span",
|
|
590
|
+
{
|
|
591
|
+
className: cn(
|
|
592
|
+
"relative inline-flex items-center justify-center rounded-2xl",
|
|
593
|
+
sizes.box,
|
|
594
|
+
variant === "gradient" && "text-white shadow-sm",
|
|
595
|
+
variant === "soft" && "bg-blue-2 text-blue-11 dark:bg-blue-2/20 dark:text-blue-9",
|
|
596
|
+
variant === "outline" && "border border-neutral-7 bg-neutral-1 text-neutral-12 dark:border-white/10 dark:bg-white/[0.04] dark:text-white"
|
|
597
|
+
),
|
|
598
|
+
style: variant === "gradient" ? { background: "var(--brand-gradient)" } : void 0,
|
|
599
|
+
children: children ?? /* @__PURE__ */ jsx(DefaultGlyph, { className: sizes.glyph })
|
|
600
|
+
}
|
|
601
|
+
)
|
|
602
|
+
]
|
|
603
|
+
}
|
|
604
|
+
);
|
|
605
|
+
}
|
|
606
|
+
function DefaultGlyph({ className }) {
|
|
607
|
+
return /* @__PURE__ */ jsxs(
|
|
608
|
+
"svg",
|
|
609
|
+
{
|
|
610
|
+
viewBox: "0 0 16 16",
|
|
611
|
+
fill: "none",
|
|
612
|
+
"aria-hidden": "true",
|
|
613
|
+
className,
|
|
614
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
615
|
+
children: [
|
|
616
|
+
/* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "3", fill: "currentColor" }),
|
|
617
|
+
/* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "6.5", stroke: "currentColor", strokeOpacity: "0.35" })
|
|
618
|
+
]
|
|
619
|
+
}
|
|
620
|
+
);
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// src/tokens/components/empty-state.ts
|
|
624
|
+
var emptyStateTokens = {
|
|
625
|
+
root: {
|
|
626
|
+
minHeight: {
|
|
627
|
+
sm: primitiveSpacing[16] * 2,
|
|
628
|
+
md: primitiveSpacing[24] * 2,
|
|
629
|
+
lg: primitiveSpacing[16] * 4
|
|
630
|
+
},
|
|
631
|
+
paddingX: {
|
|
632
|
+
sm: primitiveSpacing[4],
|
|
633
|
+
md: primitiveSpacing[6],
|
|
634
|
+
lg: primitiveSpacing[8]
|
|
635
|
+
},
|
|
636
|
+
paddingY: {
|
|
637
|
+
sm: primitiveSpacing[8],
|
|
638
|
+
md: primitiveSpacing[10],
|
|
639
|
+
lg: primitiveSpacing[14]
|
|
640
|
+
},
|
|
641
|
+
radius: primitiveRadius.lg
|
|
642
|
+
},
|
|
643
|
+
content: {
|
|
644
|
+
maxWidth: primitiveSpacing[14] * 8,
|
|
645
|
+
descriptionMaxWidth: primitiveSpacing[12] * 8,
|
|
646
|
+
stackGap: primitiveSpacing[4],
|
|
647
|
+
copyGap: primitiveSpacing[2],
|
|
648
|
+
actionsGap: primitiveSpacing[2]
|
|
649
|
+
},
|
|
650
|
+
icon: {
|
|
651
|
+
size: primitiveSizing.lg,
|
|
652
|
+
radius: primitiveRadius.lg
|
|
653
|
+
},
|
|
654
|
+
typography: {
|
|
655
|
+
title: {
|
|
656
|
+
sm: primitiveFontSize.sm,
|
|
657
|
+
md: primitiveFontSize.base,
|
|
658
|
+
lg: primitiveFontSize.lg
|
|
659
|
+
},
|
|
660
|
+
description: {
|
|
661
|
+
sm: primitiveFontSize.xs,
|
|
662
|
+
md: primitiveFontSize.sm,
|
|
663
|
+
lg: primitiveFontSize.sm
|
|
664
|
+
},
|
|
665
|
+
titleWeight: primitiveFontWeight.semibold,
|
|
666
|
+
titleLineHeight: primitiveSpacing[6],
|
|
667
|
+
descriptionLineHeight: primitiveSpacing[6]
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
var variantClassName = {
|
|
671
|
+
"blank-slate": "border border-dashed border-border bg-background",
|
|
672
|
+
informational: "border border-border bg-card",
|
|
673
|
+
educational: "border border-border bg-card",
|
|
674
|
+
guide: "border border-border bg-muted/30",
|
|
675
|
+
"no-results": "border border-dashed border-border bg-background",
|
|
676
|
+
cleared: "border border-dashed border-border bg-muted/20",
|
|
677
|
+
permission: "border border-border bg-card",
|
|
678
|
+
error: "border border-destructive/25 bg-destructive/5"
|
|
679
|
+
};
|
|
680
|
+
var iconToneClassName = {
|
|
681
|
+
"blank-slate": "text-muted-foreground",
|
|
682
|
+
informational: "text-primary",
|
|
683
|
+
educational: "text-primary",
|
|
684
|
+
guide: "text-primary",
|
|
685
|
+
"no-results": "text-muted-foreground",
|
|
686
|
+
cleared: "text-muted-foreground",
|
|
687
|
+
permission: "text-muted-foreground",
|
|
688
|
+
error: "text-destructive"
|
|
689
|
+
};
|
|
690
|
+
var emptyStateCssVars = (size) => ({
|
|
691
|
+
"--empty-state-min-height": `${emptyStateTokens.root.minHeight[size]}px`,
|
|
692
|
+
"--empty-state-padding-x": `${emptyStateTokens.root.paddingX[size]}px`,
|
|
693
|
+
"--empty-state-padding-y": `${emptyStateTokens.root.paddingY[size]}px`,
|
|
694
|
+
"--empty-state-radius": `${emptyStateTokens.root.radius}px`,
|
|
695
|
+
"--empty-state-content-max-width": `${emptyStateTokens.content.maxWidth}px`,
|
|
696
|
+
"--empty-state-description-max-width": `${emptyStateTokens.content.descriptionMaxWidth}px`,
|
|
697
|
+
"--empty-state-stack-gap": `${emptyStateTokens.content.stackGap}px`,
|
|
698
|
+
"--empty-state-copy-gap": `${emptyStateTokens.content.copyGap}px`,
|
|
699
|
+
"--empty-state-actions-gap": `${emptyStateTokens.content.actionsGap}px`,
|
|
700
|
+
"--empty-state-icon-size": `${emptyStateTokens.icon.size}px`,
|
|
701
|
+
"--empty-state-icon-radius": `${emptyStateTokens.icon.radius}px`,
|
|
702
|
+
"--empty-state-title-size": `${emptyStateTokens.typography.title[size]}px`,
|
|
703
|
+
"--empty-state-description-size": `${emptyStateTokens.typography.description[size]}px`,
|
|
704
|
+
"--empty-state-title-weight": `${emptyStateTokens.typography.titleWeight}`,
|
|
705
|
+
"--empty-state-title-line-height": `${emptyStateTokens.typography.titleLineHeight}px`,
|
|
706
|
+
"--empty-state-description-line-height": `${emptyStateTokens.typography.descriptionLineHeight}px`
|
|
707
|
+
});
|
|
708
|
+
var EmptyStateIcon = React.forwardRef(
|
|
709
|
+
({ className, icon, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
710
|
+
"div",
|
|
711
|
+
{
|
|
712
|
+
ref,
|
|
713
|
+
"aria-hidden": "true",
|
|
714
|
+
className: cn(
|
|
715
|
+
"flex size-[var(--empty-state-icon-size)] shrink-0 items-center justify-center rounded-[var(--empty-state-icon-radius)] bg-muted",
|
|
716
|
+
className
|
|
717
|
+
),
|
|
718
|
+
...props,
|
|
719
|
+
children: icon
|
|
720
|
+
}
|
|
721
|
+
)
|
|
722
|
+
);
|
|
723
|
+
EmptyStateIcon.displayName = "EmptyState.Icon";
|
|
724
|
+
var EmptyStateRoot = React.forwardRef(
|
|
725
|
+
({
|
|
726
|
+
className,
|
|
727
|
+
title,
|
|
728
|
+
description,
|
|
729
|
+
icon,
|
|
730
|
+
children,
|
|
731
|
+
action,
|
|
732
|
+
link,
|
|
733
|
+
style,
|
|
734
|
+
variant = "blank-slate",
|
|
735
|
+
size = "md",
|
|
736
|
+
align = "center",
|
|
737
|
+
live = false,
|
|
738
|
+
...props
|
|
739
|
+
}, ref) => {
|
|
740
|
+
const actions = children ?? [action, link].filter(Boolean);
|
|
741
|
+
const hasActions = React.Children.toArray(actions).length > 0;
|
|
742
|
+
return /* @__PURE__ */ jsx(
|
|
743
|
+
"section",
|
|
744
|
+
{
|
|
745
|
+
ref,
|
|
746
|
+
"aria-live": live ? "polite" : void 0,
|
|
747
|
+
className: cn(
|
|
748
|
+
"flex min-h-[var(--empty-state-min-height)] w-full flex-col justify-center rounded-[var(--empty-state-radius)] px-[var(--empty-state-padding-x)] py-[var(--empty-state-padding-y)]",
|
|
749
|
+
variantClassName[variant],
|
|
750
|
+
align === "center" ? "items-center text-center" : "items-start text-left",
|
|
751
|
+
className
|
|
752
|
+
),
|
|
753
|
+
style: { ...emptyStateCssVars(size), ...style },
|
|
754
|
+
...props,
|
|
755
|
+
children: /* @__PURE__ */ jsxs(
|
|
756
|
+
"div",
|
|
757
|
+
{
|
|
758
|
+
className: cn(
|
|
759
|
+
"flex max-w-[var(--empty-state-content-max-width)] flex-col gap-[var(--empty-state-stack-gap)]",
|
|
760
|
+
align === "center" ? "items-center" : "items-start"
|
|
761
|
+
),
|
|
762
|
+
children: [
|
|
763
|
+
icon ? /* @__PURE__ */ jsx("div", { className: cn("[&>div]:bg-muted", iconToneClassName[variant]), children: icon }) : null,
|
|
764
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-[var(--empty-state-copy-gap)]", children: [
|
|
765
|
+
/* @__PURE__ */ jsx("h3", { className: "font-[var(--empty-state-title-weight)] text-[length:var(--empty-state-title-size)] leading-[var(--empty-state-title-line-height)] text-foreground", children: title }),
|
|
766
|
+
description ? /* @__PURE__ */ jsx("p", { className: "max-w-[var(--empty-state-description-max-width)] text-[length:var(--empty-state-description-size)] leading-[var(--empty-state-description-line-height)] text-muted-foreground", children: description }) : null
|
|
767
|
+
] }),
|
|
768
|
+
hasActions ? /* @__PURE__ */ jsx(
|
|
769
|
+
"div",
|
|
770
|
+
{
|
|
771
|
+
className: cn(
|
|
772
|
+
"flex flex-wrap gap-[var(--empty-state-actions-gap)]",
|
|
773
|
+
align === "center" ? "justify-center" : "justify-start"
|
|
774
|
+
),
|
|
775
|
+
children: actions
|
|
776
|
+
}
|
|
777
|
+
) : null
|
|
778
|
+
]
|
|
779
|
+
}
|
|
780
|
+
)
|
|
781
|
+
}
|
|
782
|
+
);
|
|
783
|
+
}
|
|
784
|
+
);
|
|
785
|
+
EmptyStateRoot.displayName = "EmptyState.Root";
|
|
786
|
+
var EmptyState = {
|
|
787
|
+
Root: EmptyStateRoot,
|
|
788
|
+
Icon: EmptyStateIcon
|
|
789
|
+
};
|
|
790
|
+
var toneVariant = {
|
|
791
|
+
default: "blank-slate",
|
|
792
|
+
branded: "informational",
|
|
793
|
+
subtle: "guide"
|
|
794
|
+
};
|
|
795
|
+
function EmptyState2({
|
|
796
|
+
title,
|
|
797
|
+
description,
|
|
798
|
+
mascot,
|
|
799
|
+
icon,
|
|
800
|
+
action,
|
|
801
|
+
secondaryAction,
|
|
802
|
+
tone = "default",
|
|
803
|
+
size = "md",
|
|
804
|
+
className
|
|
805
|
+
}) {
|
|
806
|
+
const visual = mascot ?? icon ?? (tone === "branded" ? /* @__PURE__ */ jsx(BrandMark, { size: size === "lg" ? "lg" : "md" }) : null);
|
|
807
|
+
return /* @__PURE__ */ jsx(
|
|
808
|
+
EmptyState.Root,
|
|
809
|
+
{
|
|
810
|
+
action,
|
|
811
|
+
className: cn(tone === "subtle" && "border-0 bg-transparent", className),
|
|
812
|
+
description,
|
|
813
|
+
icon: visual ? /* @__PURE__ */ jsx(EmptyState.Icon, { icon: visual }) : void 0,
|
|
814
|
+
link: secondaryAction,
|
|
815
|
+
size,
|
|
816
|
+
title,
|
|
817
|
+
variant: toneVariant[tone]
|
|
818
|
+
}
|
|
819
|
+
);
|
|
820
|
+
}
|
|
821
|
+
var Slot = React.forwardRef(
|
|
822
|
+
({ children, className, style, ...props }, ref) => {
|
|
823
|
+
const childArray = React.Children.toArray(children);
|
|
824
|
+
const child = childArray.length === 1 ? childArray[0] : null;
|
|
825
|
+
if (child == null || !React.isValidElement(child)) {
|
|
826
|
+
return /* @__PURE__ */ jsx("span", { ref, className, style, ...props, children });
|
|
827
|
+
}
|
|
828
|
+
const childProps = child.props;
|
|
829
|
+
const mergedRef = (node) => {
|
|
830
|
+
if (typeof ref === "function") ref(node);
|
|
831
|
+
else if (ref) ref.current = node;
|
|
832
|
+
const childRef = child.ref;
|
|
833
|
+
if (typeof childRef === "function") childRef(node);
|
|
834
|
+
else if (childRef && "current" in childRef) {
|
|
835
|
+
childRef.current = node;
|
|
836
|
+
}
|
|
837
|
+
};
|
|
838
|
+
const mergedClass = [className, childProps.className].filter(Boolean).join(" ");
|
|
839
|
+
const merged = {
|
|
840
|
+
...childProps,
|
|
841
|
+
...props,
|
|
842
|
+
ref: mergedRef,
|
|
843
|
+
className: mergedClass,
|
|
844
|
+
style: { ...childProps.style, ...style }
|
|
845
|
+
};
|
|
846
|
+
return React.cloneElement(
|
|
847
|
+
child,
|
|
848
|
+
merged
|
|
849
|
+
);
|
|
850
|
+
}
|
|
851
|
+
);
|
|
852
|
+
Slot.displayName = "Slot";
|
|
853
|
+
var buttonVariants = cva(
|
|
854
|
+
[
|
|
855
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap",
|
|
856
|
+
"rounded-[var(--radius-md)] text-sm font-medium",
|
|
857
|
+
"transition-colors duration-150 ease-out",
|
|
858
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
859
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
860
|
+
"aria-busy:cursor-wait"
|
|
861
|
+
].join(" "),
|
|
862
|
+
{
|
|
863
|
+
variants: {
|
|
864
|
+
variant: {
|
|
865
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
866
|
+
ink: "bg-[var(--neutral-12)] text-[var(--neutral-1)] ring-1 ring-inset ring-white/[0.04] hover:bg-[var(--neutral-11)] hover:-translate-y-px active:translate-y-0 transition-[transform,background-color] duration-150",
|
|
867
|
+
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
868
|
+
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
|
869
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
870
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
871
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
872
|
+
tertiary: "border border-transparent bg-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground hover:border-input",
|
|
873
|
+
warning: "bg-warning text-warning-foreground hover:bg-warning/90"
|
|
874
|
+
},
|
|
875
|
+
size: {
|
|
876
|
+
tiny: "h-6 rounded-[var(--radius-sm)] px-2 text-[11px]",
|
|
877
|
+
// 24px
|
|
878
|
+
sm: "h-8 rounded-[var(--radius-sm)] px-3 text-xs",
|
|
879
|
+
// 32px
|
|
880
|
+
default: "h-10 px-4 py-2",
|
|
881
|
+
// 40px
|
|
882
|
+
lg: "h-12 rounded-[var(--radius-lg)] px-5 text-base",
|
|
883
|
+
// 48px
|
|
884
|
+
icon: "h-10 w-10"
|
|
885
|
+
// 40×40px (kept for backward compat)
|
|
886
|
+
},
|
|
887
|
+
shape: {
|
|
888
|
+
default: "",
|
|
889
|
+
square: "",
|
|
890
|
+
circle: ""
|
|
891
|
+
}
|
|
892
|
+
},
|
|
893
|
+
compoundVariants: [
|
|
894
|
+
// shape="square" — width = height, no horizontal padding
|
|
895
|
+
{ shape: "square", size: "tiny", className: "w-6 px-0" },
|
|
896
|
+
{ shape: "square", size: "sm", className: "w-8 px-0" },
|
|
897
|
+
{ shape: "square", size: "default", className: "w-10 px-0" },
|
|
898
|
+
{ shape: "square", size: "lg", className: "w-12 px-0" },
|
|
899
|
+
// shape="circle" — width = height + rounded-full
|
|
900
|
+
{ shape: "circle", size: "tiny", className: "w-6 px-0 rounded-full" },
|
|
901
|
+
{ shape: "circle", size: "sm", className: "w-8 px-0 rounded-full" },
|
|
902
|
+
{ shape: "circle", size: "default", className: "w-10 px-0 rounded-full" },
|
|
903
|
+
{ shape: "circle", size: "lg", className: "w-12 px-0 rounded-full" }
|
|
904
|
+
],
|
|
905
|
+
defaultVariants: {
|
|
906
|
+
variant: "default",
|
|
907
|
+
size: "default",
|
|
908
|
+
shape: "default"
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
);
|
|
912
|
+
function Spinner({ className }) {
|
|
913
|
+
return /* @__PURE__ */ jsx(
|
|
914
|
+
"span",
|
|
915
|
+
{
|
|
916
|
+
"aria-hidden": "true",
|
|
917
|
+
className: cn(
|
|
918
|
+
"block rounded-full border-2 border-current border-t-transparent animate-[spinner_0.6s_linear_infinite]",
|
|
919
|
+
className
|
|
920
|
+
)
|
|
921
|
+
}
|
|
922
|
+
);
|
|
923
|
+
}
|
|
924
|
+
function getIconSizeClass(size) {
|
|
925
|
+
switch (size) {
|
|
926
|
+
case "tiny":
|
|
927
|
+
return "[&>svg]:size-3";
|
|
928
|
+
// 12px
|
|
929
|
+
case "sm":
|
|
930
|
+
return "[&>svg]:size-3.5";
|
|
931
|
+
// 14px
|
|
932
|
+
case "lg":
|
|
933
|
+
return "[&>svg]:size-4.5";
|
|
934
|
+
// 18px
|
|
935
|
+
default:
|
|
936
|
+
return "[&>svg]:size-4";
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
function getSpinnerSizeClass(size) {
|
|
940
|
+
switch (size) {
|
|
941
|
+
case "tiny":
|
|
942
|
+
return "size-3";
|
|
943
|
+
// 12px
|
|
944
|
+
case "sm":
|
|
945
|
+
return "size-3.5";
|
|
946
|
+
// 14px
|
|
947
|
+
case "lg":
|
|
948
|
+
return "size-4.5";
|
|
949
|
+
// 18px
|
|
950
|
+
default:
|
|
951
|
+
return "size-4";
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
var SHADOW_CLASSES = {
|
|
955
|
+
sm: "shadow-sm",
|
|
956
|
+
md: "shadow-md",
|
|
957
|
+
lg: "shadow-lg"
|
|
958
|
+
};
|
|
959
|
+
function resolveShadowClass(shadow) {
|
|
960
|
+
if (!shadow) return void 0;
|
|
961
|
+
const level = shadow === true ? "md" : shadow;
|
|
962
|
+
return SHADOW_CLASSES[level];
|
|
963
|
+
}
|
|
964
|
+
function ButtonContent({ loading, prefix, suffix, size, children }) {
|
|
965
|
+
const iconSizeClass = getIconSizeClass(size);
|
|
966
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
967
|
+
loading && /* @__PURE__ */ jsx(Spinner, { className: getSpinnerSizeClass(size) }),
|
|
968
|
+
prefix != null && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("shrink-0", iconSizeClass), children: prefix }),
|
|
969
|
+
children,
|
|
970
|
+
suffix != null && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("shrink-0", iconSizeClass), children: suffix })
|
|
971
|
+
] });
|
|
972
|
+
}
|
|
973
|
+
var Button = React.forwardRef(
|
|
974
|
+
({
|
|
975
|
+
className,
|
|
976
|
+
variant,
|
|
977
|
+
size,
|
|
978
|
+
shape,
|
|
979
|
+
asChild = false,
|
|
980
|
+
loading = false,
|
|
981
|
+
disabled,
|
|
982
|
+
prefix,
|
|
983
|
+
suffix,
|
|
984
|
+
shadow,
|
|
985
|
+
children,
|
|
986
|
+
...props
|
|
987
|
+
}, ref) => {
|
|
988
|
+
const Comp = asChild ? Slot : "button";
|
|
989
|
+
const isDisabled = disabled ?? loading;
|
|
990
|
+
const shadowClass = resolveShadowClass(shadow);
|
|
991
|
+
return /* @__PURE__ */ jsx(
|
|
992
|
+
Comp,
|
|
993
|
+
{
|
|
994
|
+
ref,
|
|
995
|
+
className: cn(buttonVariants({ variant, size, shape }), shadowClass, className),
|
|
996
|
+
disabled: isDisabled,
|
|
997
|
+
"aria-busy": loading || void 0,
|
|
998
|
+
...props,
|
|
999
|
+
children: asChild ? children : /* @__PURE__ */ jsx(ButtonContent, { loading, prefix, suffix, size, children })
|
|
1000
|
+
}
|
|
1001
|
+
);
|
|
1002
|
+
}
|
|
1003
|
+
);
|
|
1004
|
+
Button.displayName = "Button";
|
|
1005
|
+
var ButtonLink = React.forwardRef(
|
|
1006
|
+
({
|
|
1007
|
+
className,
|
|
1008
|
+
variant,
|
|
1009
|
+
size,
|
|
1010
|
+
shape,
|
|
1011
|
+
prefix,
|
|
1012
|
+
suffix,
|
|
1013
|
+
shadow,
|
|
1014
|
+
loading = false,
|
|
1015
|
+
children,
|
|
1016
|
+
...props
|
|
1017
|
+
}, ref) => {
|
|
1018
|
+
const shadowClass = resolveShadowClass(shadow);
|
|
1019
|
+
const loadingProps = loading ? {
|
|
1020
|
+
"aria-busy": "true",
|
|
1021
|
+
"aria-disabled": "true",
|
|
1022
|
+
tabIndex: -1
|
|
1023
|
+
} : {};
|
|
1024
|
+
return /* @__PURE__ */ jsx(
|
|
1025
|
+
"a",
|
|
1026
|
+
{
|
|
1027
|
+
ref,
|
|
1028
|
+
className: cn(
|
|
1029
|
+
buttonVariants({ variant, size, shape }),
|
|
1030
|
+
shadowClass,
|
|
1031
|
+
loading && "pointer-events-none opacity-50",
|
|
1032
|
+
className
|
|
1033
|
+
),
|
|
1034
|
+
...loadingProps,
|
|
1035
|
+
...props,
|
|
1036
|
+
children: /* @__PURE__ */ jsx(ButtonContent, { loading, prefix, suffix, size, children })
|
|
1037
|
+
}
|
|
1038
|
+
);
|
|
1039
|
+
}
|
|
1040
|
+
);
|
|
1041
|
+
ButtonLink.displayName = "ButtonLink";
|
|
1042
|
+
var textSize = {
|
|
1043
|
+
small: "text-xs",
|
|
1044
|
+
medium: "text-sm",
|
|
1045
|
+
large: "text-base"
|
|
1046
|
+
};
|
|
1047
|
+
var iconSize = {
|
|
1048
|
+
small: 12,
|
|
1049
|
+
medium: 14,
|
|
1050
|
+
large: 16
|
|
1051
|
+
};
|
|
1052
|
+
var surfaceSize = {
|
|
1053
|
+
small: "gap-2 rounded-[var(--radius-md)] p-3 text-sm",
|
|
1054
|
+
medium: "gap-3 rounded-[var(--radius-lg)] p-4 text-sm",
|
|
1055
|
+
large: "gap-3 rounded-[var(--radius-lg)] p-5 text-base"
|
|
1056
|
+
};
|
|
1057
|
+
var surfaceIconSize = {
|
|
1058
|
+
small: 14,
|
|
1059
|
+
medium: 16,
|
|
1060
|
+
large: 18
|
|
1061
|
+
};
|
|
1062
|
+
function getActionTarget(link) {
|
|
1063
|
+
if (link?.startsWith("http")) {
|
|
1064
|
+
return { target: "_blank", rel: "noopener noreferrer" };
|
|
1065
|
+
}
|
|
1066
|
+
return {};
|
|
1067
|
+
}
|
|
1068
|
+
var ErrorMessage = React.forwardRef(
|
|
1069
|
+
({ children, label, size = "medium", error, className }, ref) => {
|
|
1070
|
+
const sz = size;
|
|
1071
|
+
const message = error?.message ?? children;
|
|
1072
|
+
return /* @__PURE__ */ jsxs(
|
|
1073
|
+
"span",
|
|
1074
|
+
{
|
|
1075
|
+
ref,
|
|
1076
|
+
role: "alert",
|
|
1077
|
+
className: cn("inline-flex items-center gap-1.5 text-destructive", textSize[sz], className),
|
|
1078
|
+
children: [
|
|
1079
|
+
/* @__PURE__ */ jsx(Warning, { size: iconSize[sz], "aria-hidden": "true", className: "shrink-0" }),
|
|
1080
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1081
|
+
label && /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
|
|
1082
|
+
label,
|
|
1083
|
+
":\xA0"
|
|
1084
|
+
] }),
|
|
1085
|
+
message,
|
|
1086
|
+
error?.action && error.link && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1087
|
+
" ",
|
|
1088
|
+
/* @__PURE__ */ jsxs(
|
|
1089
|
+
"a",
|
|
1090
|
+
{
|
|
1091
|
+
href: error.link,
|
|
1092
|
+
className: "underline underline-offset-2 hover:no-underline",
|
|
1093
|
+
target: "_blank",
|
|
1094
|
+
rel: "noopener noreferrer",
|
|
1095
|
+
children: [
|
|
1096
|
+
error.action,
|
|
1097
|
+
/* @__PURE__ */ jsx(External, { size: 10, "aria-hidden": "true", className: "ml-0.5 inline" })
|
|
1098
|
+
]
|
|
1099
|
+
}
|
|
1100
|
+
)
|
|
1101
|
+
] })
|
|
1102
|
+
] })
|
|
1103
|
+
]
|
|
1104
|
+
}
|
|
1105
|
+
);
|
|
1106
|
+
}
|
|
1107
|
+
);
|
|
1108
|
+
ErrorMessage.displayName = "ErrorMessage";
|
|
1109
|
+
var ErrorSurface = React.forwardRef(
|
|
1110
|
+
({
|
|
1111
|
+
children,
|
|
1112
|
+
label,
|
|
1113
|
+
showLabel = true,
|
|
1114
|
+
title,
|
|
1115
|
+
size = "medium",
|
|
1116
|
+
error,
|
|
1117
|
+
errorId,
|
|
1118
|
+
errorIdLabel = "Request ID",
|
|
1119
|
+
live = "polite",
|
|
1120
|
+
action,
|
|
1121
|
+
link,
|
|
1122
|
+
onAction,
|
|
1123
|
+
actionLoading = false,
|
|
1124
|
+
className,
|
|
1125
|
+
role,
|
|
1126
|
+
...props
|
|
1127
|
+
}, ref) => {
|
|
1128
|
+
const message = error?.message ?? children;
|
|
1129
|
+
const resolvedTitle = title ?? error?.title;
|
|
1130
|
+
const resolvedAction = action ?? error?.action;
|
|
1131
|
+
const resolvedLink = link ?? error?.link;
|
|
1132
|
+
const resolvedErrorId = errorId ?? error?.id;
|
|
1133
|
+
const resolvedRole = role ?? (live === "assertive" ? "alert" : "status");
|
|
1134
|
+
const ariaLive = live === "off" ? void 0 : live;
|
|
1135
|
+
return /* @__PURE__ */ jsxs(
|
|
1136
|
+
"div",
|
|
1137
|
+
{
|
|
1138
|
+
ref,
|
|
1139
|
+
role: resolvedRole,
|
|
1140
|
+
"aria-live": ariaLive,
|
|
1141
|
+
className: cn(
|
|
1142
|
+
"flex w-full border border-destructive/25 bg-destructive/5 text-foreground",
|
|
1143
|
+
surfaceSize[size],
|
|
1144
|
+
className
|
|
1145
|
+
),
|
|
1146
|
+
...props,
|
|
1147
|
+
children: [
|
|
1148
|
+
/* @__PURE__ */ jsx(
|
|
1149
|
+
"span",
|
|
1150
|
+
{
|
|
1151
|
+
"aria-hidden": "true",
|
|
1152
|
+
className: "mt-0.5 flex size-7 shrink-0 items-center justify-center rounded-[var(--radius-sm)] border border-destructive/20 bg-background text-destructive",
|
|
1153
|
+
children: /* @__PURE__ */ jsx(Warning, { size: surfaceIconSize[size] })
|
|
1154
|
+
}
|
|
1155
|
+
),
|
|
1156
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1157
|
+
label && showLabel ? /* @__PURE__ */ jsx("p", { className: "mb-1 text-xs font-medium uppercase tracking-normal text-destructive", children: label }) : null,
|
|
1158
|
+
resolvedTitle ? /* @__PURE__ */ jsx("p", { className: "font-semibold leading-6 text-foreground", children: resolvedTitle }) : null,
|
|
1159
|
+
message ? /* @__PURE__ */ jsx("p", { className: cn("leading-5 text-muted-foreground", resolvedTitle && "mt-1"), children: message }) : null,
|
|
1160
|
+
resolvedErrorId ? /* @__PURE__ */ jsxs("details", { className: "mt-3 text-xs text-muted-foreground", children: [
|
|
1161
|
+
/* @__PURE__ */ jsx("summary", { className: "cursor-pointer select-none text-foreground", children: "Diagnostic details" }),
|
|
1162
|
+
/* @__PURE__ */ jsxs("code", { className: "mt-2 block overflow-x-auto rounded-[var(--radius-sm)] border bg-background px-2 py-1 font-mono text-xs text-muted-foreground", children: [
|
|
1163
|
+
errorIdLabel,
|
|
1164
|
+
": ",
|
|
1165
|
+
resolvedErrorId,
|
|
1166
|
+
error?.code ? ` (${error.code})` : ""
|
|
1167
|
+
] })
|
|
1168
|
+
] }) : null,
|
|
1169
|
+
resolvedAction ? /* @__PURE__ */ jsx("div", { className: "mt-4 flex flex-wrap gap-2", children: resolvedLink ? /* @__PURE__ */ jsx(
|
|
1170
|
+
ButtonLink,
|
|
1171
|
+
{
|
|
1172
|
+
href: resolvedLink,
|
|
1173
|
+
size: "sm",
|
|
1174
|
+
variant: "outline",
|
|
1175
|
+
...getActionTarget(resolvedLink),
|
|
1176
|
+
children: resolvedAction
|
|
1177
|
+
}
|
|
1178
|
+
) : /* @__PURE__ */ jsx(
|
|
1179
|
+
Button,
|
|
1180
|
+
{
|
|
1181
|
+
type: "button",
|
|
1182
|
+
size: "sm",
|
|
1183
|
+
variant: "outline",
|
|
1184
|
+
loading: actionLoading,
|
|
1185
|
+
onClick: onAction,
|
|
1186
|
+
children: resolvedAction
|
|
1187
|
+
}
|
|
1188
|
+
) }) : null
|
|
1189
|
+
] })
|
|
1190
|
+
]
|
|
1191
|
+
}
|
|
1192
|
+
);
|
|
1193
|
+
}
|
|
1194
|
+
);
|
|
1195
|
+
ErrorSurface.displayName = "Error";
|
|
1196
|
+
function ErrorState({
|
|
1197
|
+
title = "Couldn\u2019t Load Resource",
|
|
1198
|
+
message,
|
|
1199
|
+
onRetry,
|
|
1200
|
+
errorId
|
|
1201
|
+
}) {
|
|
1202
|
+
const stableIdProps = errorId === void 0 ? {} : { errorId };
|
|
1203
|
+
return /* @__PURE__ */ jsx("div", { className: "px-4 py-6", children: onRetry ? /* @__PURE__ */ jsx(ErrorSurface, { title, action: "Try Again", onAction: onRetry, ...stableIdProps, children: message }) : /* @__PURE__ */ jsx(ErrorSurface, { title, ...stableIdProps, children: message }) });
|
|
1204
|
+
}
|
|
1205
|
+
function FullPageStatus({
|
|
1206
|
+
code,
|
|
1207
|
+
title,
|
|
1208
|
+
description,
|
|
1209
|
+
primaryAction,
|
|
1210
|
+
secondaryAction,
|
|
1211
|
+
meta,
|
|
1212
|
+
variant = "viewport"
|
|
1213
|
+
}) {
|
|
1214
|
+
const isSection = variant === "section";
|
|
1215
|
+
const Wrapper = isSection ? "section" : "main";
|
|
1216
|
+
const wrapperClass = isSection ? "flex min-h-[60vh] items-center justify-center px-6 py-12 text-neutral-12" : "flex min-h-[100dvh] items-center justify-center bg-neutral-1 px-6 text-neutral-12";
|
|
1217
|
+
return /* @__PURE__ */ jsx(Wrapper, { role: isSection ? "alert" : "main", className: wrapperClass, children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-[480px]", children: [
|
|
1218
|
+
/* @__PURE__ */ jsx("div", { className: "mb-4 font-mono text-xs font-medium uppercase tracking-[0.08em] text-neutral-9", children: code }),
|
|
1219
|
+
/* @__PURE__ */ jsx("h1", { className: "mb-3 text-[clamp(28px,5vw,36px)] font-semibold leading-[1.15] tracking-[-0.02em]", children: title }),
|
|
1220
|
+
/* @__PURE__ */ jsx("p", { className: "mb-8 max-w-[52ch] text-base leading-[1.6] text-neutral-11", children: description }),
|
|
1221
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-3", children: [
|
|
1222
|
+
/* @__PURE__ */ jsx(ActionButton, { action: primaryAction, variant: "primary" }),
|
|
1223
|
+
secondaryAction && /* @__PURE__ */ jsx(ActionButton, { action: secondaryAction, variant: "secondary" })
|
|
1224
|
+
] }),
|
|
1225
|
+
meta && (meta.errorId || meta.statusUrl) && /* @__PURE__ */ jsxs("div", { className: "mt-10 flex flex-wrap justify-between gap-4 border-t border-neutral-6 pt-5 font-mono text-xs text-neutral-10", children: [
|
|
1226
|
+
meta.errorId && /* @__PURE__ */ jsxs("span", { children: [
|
|
1227
|
+
"Error ID: ",
|
|
1228
|
+
meta.errorId
|
|
1229
|
+
] }),
|
|
1230
|
+
meta.statusUrl && /* @__PURE__ */ jsxs(
|
|
1231
|
+
"a",
|
|
1232
|
+
{
|
|
1233
|
+
href: `https://${meta.statusUrl}`,
|
|
1234
|
+
className: "text-neutral-10 hover:text-neutral-12",
|
|
1235
|
+
rel: "noreferrer",
|
|
1236
|
+
children: [
|
|
1237
|
+
meta.statusUrl,
|
|
1238
|
+
" \u2192"
|
|
1239
|
+
]
|
|
1240
|
+
}
|
|
1241
|
+
)
|
|
1242
|
+
] })
|
|
1243
|
+
] }) });
|
|
1244
|
+
}
|
|
1245
|
+
function ActionButton({
|
|
1246
|
+
action,
|
|
1247
|
+
variant
|
|
1248
|
+
}) {
|
|
1249
|
+
const buttonVariant = variant === "primary" ? "ink" : "outline";
|
|
1250
|
+
if (action.href) {
|
|
1251
|
+
return /* @__PURE__ */ jsx(Button, { asChild: true, variant: buttonVariant, children: /* @__PURE__ */ jsx(Link, { href: action.href, children: action.label }) });
|
|
1252
|
+
}
|
|
1253
|
+
return /* @__PURE__ */ jsx(Button, { type: "button", onClick: action.onClick, variant: buttonVariant, children: action.label });
|
|
1254
|
+
}
|
|
1255
|
+
FullPageStatus.Accent = function Accent({ children }) {
|
|
1256
|
+
return /* @__PURE__ */ jsx("span", { className: "text-neutral-12", children });
|
|
1257
|
+
};
|
|
1258
|
+
var spinnerSize = {
|
|
1259
|
+
small: "h-4 w-4 border-2",
|
|
1260
|
+
medium: "h-6 w-6 border-2",
|
|
1261
|
+
large: "h-8 w-8 border-4"
|
|
1262
|
+
};
|
|
1263
|
+
function LoadingState({ message, size = "large" }) {
|
|
1264
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-10", children: [
|
|
1265
|
+
/* @__PURE__ */ jsx(
|
|
1266
|
+
"span",
|
|
1267
|
+
{
|
|
1268
|
+
className: cn(
|
|
1269
|
+
"inline-block animate-spin rounded-full border-solid border-[color:var(--blue-9)] border-r-transparent align-[-0.125em]",
|
|
1270
|
+
spinnerSize[size]
|
|
1271
|
+
),
|
|
1272
|
+
role: "status",
|
|
1273
|
+
"aria-label": message ?? "Loading"
|
|
1274
|
+
}
|
|
1275
|
+
),
|
|
1276
|
+
message && /* @__PURE__ */ jsx("p", { className: "mt-3 text-sm text-[color:var(--neutral-11)] dark:text-white/70", children: message })
|
|
1277
|
+
] });
|
|
1278
|
+
}
|
|
1279
|
+
function PageHeader({ title, description, actions, className }) {
|
|
1280
|
+
return /* @__PURE__ */ jsxs(
|
|
1281
|
+
"div",
|
|
1282
|
+
{
|
|
1283
|
+
className: cn(
|
|
1284
|
+
"flex flex-col gap-1 pb-6 sm:flex-row sm:items-start sm:justify-between",
|
|
1285
|
+
className
|
|
1286
|
+
),
|
|
1287
|
+
children: [
|
|
1288
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
1289
|
+
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold tracking-tight text-[color:var(--neutral-12)] dark:text-white", children: title }),
|
|
1290
|
+
description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-[color:var(--neutral-11)] dark:text-white/70", children: description })
|
|
1291
|
+
] }),
|
|
1292
|
+
actions && /* @__PURE__ */ jsx("div", { className: "mt-2 flex shrink-0 gap-2 sm:mt-0", children: actions })
|
|
1293
|
+
]
|
|
1294
|
+
}
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1297
|
+
function Section({ children, label, className }) {
|
|
1298
|
+
return /* @__PURE__ */ jsx("section", { "aria-label": label, className: cn("py-8", className), children });
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
export { AppShell, Card, Container, DesignSystemProvider, EmptyState2 as EmptyState, ErrorState, FullPageStatus, LoadingState, PageHeader, Section };
|
|
1302
|
+
//# sourceMappingURL=index.js.map
|
|
1303
|
+
//# sourceMappingURL=index.js.map
|