@classic-homes/theme-react 0.1.52 → 0.1.53
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/index.css +12 -10
- package/dist/index.d.mts +750 -53
- package/dist/index.d.ts +750 -53
- package/dist/index.js +1451 -217
- package/dist/index.mjs +1447 -233
- package/package.json +13 -3
package/dist/index.js
CHANGED
|
@@ -58,9 +58,18 @@ __export(index_exports, {
|
|
|
58
58
|
DialogTrigger: () => DialogTrigger,
|
|
59
59
|
Input: () => Input,
|
|
60
60
|
Label: () => Label,
|
|
61
|
+
LiveRegion: () => LiveRegion,
|
|
62
|
+
LoadingLogo: () => LoadingLogo,
|
|
63
|
+
LoadingOverlay: () => LoadingOverlay,
|
|
64
|
+
LoadingPage: () => LoadingPage,
|
|
65
|
+
LoadingSection: () => LoadingSection,
|
|
61
66
|
PageHeader: () => PageHeader,
|
|
62
67
|
PasswordInput: () => PasswordInput,
|
|
68
|
+
ProgressBar: () => ProgressBar,
|
|
63
69
|
Separator: () => Separator,
|
|
70
|
+
Skeleton: () => Skeleton,
|
|
71
|
+
SkipLink: () => SkipLink,
|
|
72
|
+
Spinner: () => Spinner,
|
|
64
73
|
Switch: () => Switch,
|
|
65
74
|
badgeVariants: () => badgeVariants,
|
|
66
75
|
buttonVariants: () => buttonVariants,
|
|
@@ -69,7 +78,18 @@ __export(index_exports, {
|
|
|
69
78
|
pageHeaderContainerVariants: () => pageHeaderContainerVariants,
|
|
70
79
|
pageHeaderSubtitleVariants: () => pageHeaderSubtitleVariants,
|
|
71
80
|
pageHeaderTitleVariants: () => pageHeaderTitleVariants,
|
|
72
|
-
|
|
81
|
+
progressBarVariants: () => progressBarVariants,
|
|
82
|
+
skeletonVariants: () => skeletonVariants,
|
|
83
|
+
spinnerVariants: () => spinnerVariants,
|
|
84
|
+
useAnnounce: () => useAnnounce,
|
|
85
|
+
useArrowNavigation: () => useArrowNavigation,
|
|
86
|
+
useClickOutside: () => useClickOutside,
|
|
87
|
+
useDataPanel: () => useDataPanel,
|
|
88
|
+
useEscapeKey: () => useEscapeKey,
|
|
89
|
+
useFocusRef: () => useFocusRef,
|
|
90
|
+
useFocusTrap: () => useFocusTrap,
|
|
91
|
+
useReducedMotion: () => useReducedMotion,
|
|
92
|
+
useRovingTabindex: () => useRovingTabindex
|
|
73
93
|
});
|
|
74
94
|
module.exports = __toCommonJS(index_exports);
|
|
75
95
|
|
|
@@ -114,9 +134,9 @@ var buttonVariants = (0, import_class_variance_authority.cva)(
|
|
|
114
134
|
}
|
|
115
135
|
);
|
|
116
136
|
var Button = React.forwardRef(
|
|
117
|
-
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
137
|
+
({ className, variant, size, asChild = false, children, ...props }, ref) => {
|
|
118
138
|
const Comp = asChild ? import_react_slot.Slot : "button";
|
|
119
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Comp, { className: cn(buttonVariants({ variant, size, className })), ref, ...props });
|
|
139
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Comp, { className: cn(buttonVariants({ variant, size, className })), ref, ...props, children });
|
|
120
140
|
}
|
|
121
141
|
);
|
|
122
142
|
Button.displayName = "Button";
|
|
@@ -125,8 +145,8 @@ Button.displayName = "Button";
|
|
|
125
145
|
var React2 = __toESM(require("react"));
|
|
126
146
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
127
147
|
var Card = React2.forwardRef(
|
|
128
|
-
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
129
|
-
|
|
148
|
+
({ className, as: Component = "div", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
149
|
+
Component,
|
|
130
150
|
{
|
|
131
151
|
ref,
|
|
132
152
|
className: cn(
|
|
@@ -143,8 +163,8 @@ var CardHeader = React2.forwardRef(
|
|
|
143
163
|
);
|
|
144
164
|
CardHeader.displayName = "CardHeader";
|
|
145
165
|
var CardTitle = React2.forwardRef(
|
|
146
|
-
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
147
|
-
|
|
166
|
+
({ className, as: Component = "h3", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
167
|
+
Component,
|
|
148
168
|
{
|
|
149
169
|
ref,
|
|
150
170
|
className: cn("text-2xl font-semibold leading-none tracking-tight", className),
|
|
@@ -168,13 +188,32 @@ CardFooter.displayName = "CardFooter";
|
|
|
168
188
|
var React3 = __toESM(require("react"));
|
|
169
189
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
170
190
|
var Input = React3.forwardRef(
|
|
171
|
-
({
|
|
191
|
+
({
|
|
192
|
+
className,
|
|
193
|
+
type,
|
|
194
|
+
"aria-invalid": ariaInvalid,
|
|
195
|
+
required,
|
|
196
|
+
"aria-describedby": ariaDescribedBy,
|
|
197
|
+
...props
|
|
198
|
+
}, ref) => {
|
|
199
|
+
if (process.env.NODE_ENV !== "production") {
|
|
200
|
+
if (!props["aria-label"] && !props["aria-labelledby"] && !props.id) {
|
|
201
|
+
console.warn(
|
|
202
|
+
"Input: Missing accessible label. Provide aria-label, aria-labelledby, or associate with a Label using id/htmlFor for WCAG compliance."
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
172
206
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
173
207
|
"input",
|
|
174
208
|
{
|
|
175
209
|
type,
|
|
210
|
+
"aria-invalid": ariaInvalid,
|
|
211
|
+
"aria-required": required,
|
|
212
|
+
"aria-describedby": ariaDescribedBy,
|
|
213
|
+
required,
|
|
176
214
|
className: cn(
|
|
177
215
|
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
216
|
+
ariaInvalid === true || ariaInvalid === "true" ? "border-destructive focus-visible:ring-destructive" : "",
|
|
178
217
|
className
|
|
179
218
|
),
|
|
180
219
|
ref,
|
|
@@ -186,7 +225,57 @@ var Input = React3.forwardRef(
|
|
|
186
225
|
Input.displayName = "Input";
|
|
187
226
|
|
|
188
227
|
// src/components/PasswordInput.tsx
|
|
228
|
+
var React5 = __toESM(require("react"));
|
|
229
|
+
|
|
230
|
+
// src/hooks/useAnnounce.ts
|
|
189
231
|
var React4 = __toESM(require("react"));
|
|
232
|
+
function useAnnounce(defaultOptions) {
|
|
233
|
+
const [message, setMessage] = React4.useState("");
|
|
234
|
+
const [politeness, setPoliteness] = React4.useState(
|
|
235
|
+
defaultOptions?.politeness ?? "polite"
|
|
236
|
+
);
|
|
237
|
+
const clearTimeoutRef = React4.useRef(null);
|
|
238
|
+
const clear = React4.useCallback(() => {
|
|
239
|
+
setMessage("");
|
|
240
|
+
if (clearTimeoutRef.current) {
|
|
241
|
+
clearTimeout(clearTimeoutRef.current);
|
|
242
|
+
clearTimeoutRef.current = null;
|
|
243
|
+
}
|
|
244
|
+
}, []);
|
|
245
|
+
const announce = React4.useCallback(
|
|
246
|
+
(newMessage, options) => {
|
|
247
|
+
if (clearTimeoutRef.current) {
|
|
248
|
+
clearTimeout(clearTimeoutRef.current);
|
|
249
|
+
}
|
|
250
|
+
if (options?.politeness) {
|
|
251
|
+
setPoliteness(options.politeness);
|
|
252
|
+
}
|
|
253
|
+
setMessage(newMessage);
|
|
254
|
+
const delay = options?.clearDelay ?? defaultOptions?.clearDelay ?? 1e3;
|
|
255
|
+
if (delay > 0) {
|
|
256
|
+
clearTimeoutRef.current = setTimeout(() => {
|
|
257
|
+
setMessage("");
|
|
258
|
+
}, delay);
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
[defaultOptions?.clearDelay]
|
|
262
|
+
);
|
|
263
|
+
React4.useEffect(() => {
|
|
264
|
+
return () => {
|
|
265
|
+
if (clearTimeoutRef.current) {
|
|
266
|
+
clearTimeout(clearTimeoutRef.current);
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
}, []);
|
|
270
|
+
return {
|
|
271
|
+
announce,
|
|
272
|
+
message,
|
|
273
|
+
politeness,
|
|
274
|
+
clear
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// src/components/PasswordInput.tsx
|
|
190
279
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
191
280
|
var EyeIcon = () => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
192
281
|
"svg",
|
|
@@ -199,6 +288,8 @@ var EyeIcon = () => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
|
199
288
|
strokeWidth: 2,
|
|
200
289
|
strokeLinecap: "round",
|
|
201
290
|
strokeLinejoin: "round",
|
|
291
|
+
"aria-hidden": "true",
|
|
292
|
+
focusable: "false",
|
|
202
293
|
children: [
|
|
203
294
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }),
|
|
204
295
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "12", r: "3" })
|
|
@@ -216,20 +307,48 @@ var EyeOffIcon = () => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
|
216
307
|
strokeWidth: 2,
|
|
217
308
|
strokeLinecap: "round",
|
|
218
309
|
strokeLinejoin: "round",
|
|
310
|
+
"aria-hidden": "true",
|
|
311
|
+
focusable: "false",
|
|
219
312
|
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24M1 1l22 22" })
|
|
220
313
|
}
|
|
221
314
|
);
|
|
222
|
-
var PasswordInput =
|
|
223
|
-
({
|
|
224
|
-
|
|
315
|
+
var PasswordInput = React5.forwardRef(
|
|
316
|
+
({
|
|
317
|
+
className,
|
|
318
|
+
disabled,
|
|
319
|
+
showLabel = "Show password",
|
|
320
|
+
hideLabel = "Hide password",
|
|
321
|
+
visibleAnnouncement = "Password is now visible",
|
|
322
|
+
hiddenAnnouncement = "Password is now hidden",
|
|
323
|
+
id,
|
|
324
|
+
"aria-label": ariaLabel,
|
|
325
|
+
"aria-labelledby": ariaLabelledBy,
|
|
326
|
+
...props
|
|
327
|
+
}, ref) => {
|
|
328
|
+
const [showPassword, setShowPassword] = React5.useState(false);
|
|
329
|
+
const { announce, message, politeness } = useAnnounce();
|
|
330
|
+
if (process.env.NODE_ENV !== "production") {
|
|
331
|
+
if (!ariaLabel && !ariaLabelledBy && !id) {
|
|
332
|
+
console.warn(
|
|
333
|
+
"PasswordInput: Missing accessible label. Provide aria-label, aria-labelledby, or an id to associate with a Label element for WCAG compliance."
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
225
337
|
const toggleVisibility = () => {
|
|
226
|
-
setShowPassword((prev) =>
|
|
338
|
+
setShowPassword((prev) => {
|
|
339
|
+
const newState = !prev;
|
|
340
|
+
announce(newState ? visibleAnnouncement : hiddenAnnouncement);
|
|
341
|
+
return newState;
|
|
342
|
+
});
|
|
227
343
|
};
|
|
228
344
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "relative", children: [
|
|
229
345
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
230
346
|
"input",
|
|
231
347
|
{
|
|
232
348
|
type: showPassword ? "text" : "password",
|
|
349
|
+
id,
|
|
350
|
+
"aria-label": ariaLabel,
|
|
351
|
+
"aria-labelledby": ariaLabelledBy,
|
|
233
352
|
className: cn(
|
|
234
353
|
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 pr-10 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
235
354
|
className
|
|
@@ -243,35 +362,37 @@ var PasswordInput = React4.forwardRef(
|
|
|
243
362
|
"button",
|
|
244
363
|
{
|
|
245
364
|
type: "button",
|
|
246
|
-
className: "absolute right-0 top-0 h-
|
|
365
|
+
className: "absolute right-0 top-0 h-11 w-11 -mr-0.5 -mt-0.5 flex items-center justify-center text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded-r-md disabled:pointer-events-none disabled:opacity-50",
|
|
247
366
|
onClick: toggleVisibility,
|
|
248
367
|
disabled,
|
|
249
368
|
"aria-label": showPassword ? hideLabel : showLabel,
|
|
369
|
+
"aria-pressed": showPassword,
|
|
250
370
|
children: showPassword ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(EyeOffIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(EyeIcon, {})
|
|
251
371
|
}
|
|
252
|
-
)
|
|
372
|
+
),
|
|
373
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { role: "status", "aria-live": politeness, "aria-atomic": "true", className: "sr-only", children: message })
|
|
253
374
|
] });
|
|
254
375
|
}
|
|
255
376
|
);
|
|
256
377
|
PasswordInput.displayName = "PasswordInput";
|
|
257
378
|
|
|
258
379
|
// src/components/Label.tsx
|
|
259
|
-
var
|
|
380
|
+
var React6 = __toESM(require("react"));
|
|
260
381
|
var LabelPrimitive = __toESM(require("@radix-ui/react-label"));
|
|
261
382
|
var import_class_variance_authority2 = require("class-variance-authority");
|
|
262
383
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
263
384
|
var labelVariants = (0, import_class_variance_authority2.cva)(
|
|
264
385
|
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
265
386
|
);
|
|
266
|
-
var Label =
|
|
387
|
+
var Label = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(LabelPrimitive.Root, { ref, className: cn(labelVariants(), className), ...props }));
|
|
267
388
|
Label.displayName = LabelPrimitive.Root.displayName;
|
|
268
389
|
|
|
269
390
|
// src/components/Badge.tsx
|
|
270
|
-
var
|
|
391
|
+
var React7 = __toESM(require("react"));
|
|
271
392
|
var import_class_variance_authority3 = require("class-variance-authority");
|
|
272
393
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
273
394
|
var badgeVariants = (0, import_class_variance_authority3.cva)(
|
|
274
|
-
"inline-flex items-center rounded-full border border-border px-2.5 py-0.5 text-xs font-semibold transition-colors
|
|
395
|
+
"inline-flex items-center rounded-full border border-border px-2.5 py-0.5 text-xs font-semibold transition-colors",
|
|
275
396
|
{
|
|
276
397
|
variants: {
|
|
277
398
|
variant: {
|
|
@@ -286,15 +407,28 @@ var badgeVariants = (0, import_class_variance_authority3.cva)(
|
|
|
286
407
|
}
|
|
287
408
|
}
|
|
288
409
|
);
|
|
289
|
-
var Badge =
|
|
290
|
-
({ className, variant, ...props }, ref) => {
|
|
291
|
-
|
|
410
|
+
var Badge = React7.forwardRef(
|
|
411
|
+
({ className, variant, live, label, children, ...props }, ref) => {
|
|
412
|
+
if (process.env.NODE_ENV !== "production") {
|
|
413
|
+
if (live && !label) {
|
|
414
|
+
console.warn(
|
|
415
|
+
'Badge: When using live={true} for dynamic content, consider providing a label prop for better screen reader context (e.g., label="unread notifications" for a count badge).'
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
292
420
|
"div",
|
|
293
421
|
{
|
|
294
422
|
ref,
|
|
295
|
-
role: "status",
|
|
423
|
+
role: live ? "status" : void 0,
|
|
424
|
+
"aria-live": live ? "polite" : void 0,
|
|
425
|
+
"aria-atomic": live ? "true" : void 0,
|
|
296
426
|
className: cn(badgeVariants({ variant }), className),
|
|
297
|
-
...props
|
|
427
|
+
...props,
|
|
428
|
+
children: [
|
|
429
|
+
children,
|
|
430
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "sr-only", children: label })
|
|
431
|
+
]
|
|
298
432
|
}
|
|
299
433
|
);
|
|
300
434
|
}
|
|
@@ -302,81 +436,123 @@ var Badge = React6.forwardRef(
|
|
|
302
436
|
Badge.displayName = "Badge";
|
|
303
437
|
|
|
304
438
|
// src/components/Separator.tsx
|
|
305
|
-
var
|
|
439
|
+
var React8 = __toESM(require("react"));
|
|
306
440
|
var SeparatorPrimitive = __toESM(require("@radix-ui/react-separator"));
|
|
307
441
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
308
|
-
var Separator =
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
"shrink-0 bg-border",
|
|
316
|
-
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
|
317
|
-
className
|
|
318
|
-
),
|
|
319
|
-
...props
|
|
442
|
+
var Separator = React8.forwardRef(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => {
|
|
443
|
+
if (process.env.NODE_ENV !== "production") {
|
|
444
|
+
if (!decorative && !props["aria-label"]) {
|
|
445
|
+
console.warn(
|
|
446
|
+
"Separator: Non-decorative separators (decorative={false}) should have an aria-label to describe the content they separate."
|
|
447
|
+
);
|
|
448
|
+
}
|
|
320
449
|
}
|
|
321
|
-
)
|
|
450
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
451
|
+
SeparatorPrimitive.Root,
|
|
452
|
+
{
|
|
453
|
+
ref,
|
|
454
|
+
decorative,
|
|
455
|
+
orientation,
|
|
456
|
+
className: cn(
|
|
457
|
+
"shrink-0 bg-border",
|
|
458
|
+
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
|
459
|
+
className
|
|
460
|
+
),
|
|
461
|
+
...props
|
|
462
|
+
}
|
|
463
|
+
);
|
|
464
|
+
});
|
|
322
465
|
Separator.displayName = SeparatorPrimitive.Root.displayName;
|
|
323
466
|
|
|
324
467
|
// src/components/Switch.tsx
|
|
325
|
-
var
|
|
468
|
+
var React9 = __toESM(require("react"));
|
|
326
469
|
var SwitchPrimitives = __toESM(require("@radix-ui/react-switch"));
|
|
327
470
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
328
471
|
var SwitchRoot = SwitchPrimitives.Root;
|
|
329
472
|
var SwitchThumb = SwitchPrimitives.Thumb;
|
|
330
|
-
var Switch =
|
|
331
|
-
({
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
className: cn(
|
|
346
|
-
"pointer-events-none block rounded-full bg-background shadow-lg ring-0 transition-transform",
|
|
347
|
-
size === "default" && "h-5 w-5 data-[state=checked]:translate-x-[22px] data-[state=unchecked]:translate-x-0.5",
|
|
348
|
-
size === "sm" && "h-4 w-4 data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0"
|
|
349
|
-
)
|
|
350
|
-
}
|
|
351
|
-
)
|
|
473
|
+
var Switch = React9.forwardRef(
|
|
474
|
+
({
|
|
475
|
+
className,
|
|
476
|
+
size = "default",
|
|
477
|
+
"aria-label": ariaLabel,
|
|
478
|
+
"aria-labelledby": ariaLabelledBy,
|
|
479
|
+
"aria-describedby": ariaDescribedBy,
|
|
480
|
+
...props
|
|
481
|
+
}, ref) => {
|
|
482
|
+
if (process.env.NODE_ENV !== "production") {
|
|
483
|
+
if (!ariaLabel && !ariaLabelledBy && !props.id) {
|
|
484
|
+
console.warn(
|
|
485
|
+
"Switch: Missing accessible label. Provide aria-label, aria-labelledby, or associate with a Label using id/htmlFor for WCAG compliance."
|
|
486
|
+
);
|
|
487
|
+
}
|
|
352
488
|
}
|
|
353
|
-
|
|
489
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
490
|
+
SwitchRoot,
|
|
491
|
+
{
|
|
492
|
+
className: cn(
|
|
493
|
+
"peer inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
|
|
494
|
+
size === "default" && "h-7 w-12",
|
|
495
|
+
size === "sm" && "h-5 w-9",
|
|
496
|
+
className
|
|
497
|
+
),
|
|
498
|
+
ref,
|
|
499
|
+
"aria-label": ariaLabel,
|
|
500
|
+
"aria-labelledby": ariaLabelledBy,
|
|
501
|
+
"aria-describedby": ariaDescribedBy,
|
|
502
|
+
...props,
|
|
503
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
504
|
+
SwitchThumb,
|
|
505
|
+
{
|
|
506
|
+
className: cn(
|
|
507
|
+
"pointer-events-none block rounded-full bg-background shadow-lg ring-0 transition-transform",
|
|
508
|
+
size === "default" && "h-5 w-5 data-[state=checked]:translate-x-[22px] data-[state=unchecked]:translate-x-0.5",
|
|
509
|
+
size === "sm" && "h-4 w-4 data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0"
|
|
510
|
+
)
|
|
511
|
+
}
|
|
512
|
+
)
|
|
513
|
+
}
|
|
514
|
+
);
|
|
515
|
+
}
|
|
354
516
|
);
|
|
355
517
|
Switch.displayName = SwitchPrimitives.Root.displayName;
|
|
356
518
|
|
|
357
519
|
// src/components/Avatar.tsx
|
|
358
|
-
var
|
|
520
|
+
var React10 = __toESM(require("react"));
|
|
359
521
|
var AvatarPrimitive = __toESM(require("@radix-ui/react-avatar"));
|
|
360
522
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
361
|
-
var Avatar =
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
523
|
+
var Avatar = React10.forwardRef(
|
|
524
|
+
({ className, name, "aria-label": ariaLabel, ...props }, ref) => {
|
|
525
|
+
if (process.env.NODE_ENV !== "production") {
|
|
526
|
+
if (!ariaLabel && !name) {
|
|
527
|
+
console.warn(
|
|
528
|
+
'Avatar: Missing accessible text. Provide either a "name" prop or "aria-label" for screen reader users.'
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
const computedAriaLabel = ariaLabel ?? (name ? `Avatar for ${name}` : void 0);
|
|
533
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
534
|
+
AvatarPrimitive.Root,
|
|
535
|
+
{
|
|
536
|
+
ref,
|
|
537
|
+
"aria-label": computedAriaLabel,
|
|
538
|
+
className: cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className),
|
|
539
|
+
...props
|
|
540
|
+
}
|
|
541
|
+
);
|
|
367
542
|
}
|
|
368
|
-
)
|
|
543
|
+
);
|
|
369
544
|
Avatar.displayName = AvatarPrimitive.Root.displayName;
|
|
370
|
-
var AvatarImage =
|
|
545
|
+
var AvatarImage = React10.forwardRef(({ className, alt, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
371
546
|
AvatarPrimitive.Image,
|
|
372
547
|
{
|
|
373
548
|
ref,
|
|
549
|
+
alt,
|
|
374
550
|
className: cn("aspect-square h-full w-full object-cover", className),
|
|
375
551
|
...props
|
|
376
552
|
}
|
|
377
553
|
));
|
|
378
554
|
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
|
|
379
|
-
var AvatarFallback =
|
|
555
|
+
var AvatarFallback = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
380
556
|
AvatarPrimitive.Fallback,
|
|
381
557
|
{
|
|
382
558
|
ref,
|
|
@@ -390,7 +566,7 @@ var AvatarFallback = React9.forwardRef(({ className, ...props }, ref) => /* @__P
|
|
|
390
566
|
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
|
|
391
567
|
|
|
392
568
|
// src/components/Dialog.tsx
|
|
393
|
-
var
|
|
569
|
+
var React11 = __toESM(require("react"));
|
|
394
570
|
var DialogPrimitive = __toESM(require("@radix-ui/react-dialog"));
|
|
395
571
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
396
572
|
var PrimitiveOverlay = DialogPrimitive.Overlay;
|
|
@@ -401,7 +577,7 @@ var Dialog = DialogPrimitive.Root;
|
|
|
401
577
|
var DialogTrigger = DialogPrimitive.Trigger;
|
|
402
578
|
var DialogPortal = DialogPrimitive.Portal;
|
|
403
579
|
var DialogClose = DialogPrimitive.Close;
|
|
404
|
-
var DialogOverlay =
|
|
580
|
+
var DialogOverlay = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
405
581
|
PrimitiveOverlay,
|
|
406
582
|
{
|
|
407
583
|
ref,
|
|
@@ -413,7 +589,7 @@ var DialogOverlay = React10.forwardRef(({ className, ...props }, ref) => /* @__P
|
|
|
413
589
|
}
|
|
414
590
|
));
|
|
415
591
|
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
416
|
-
var DialogContent =
|
|
592
|
+
var DialogContent = React11.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(DialogPortal, { children: [
|
|
417
593
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DialogOverlay, {}),
|
|
418
594
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
419
595
|
PrimitiveContent,
|
|
@@ -439,7 +615,7 @@ var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_r
|
|
|
439
615
|
}
|
|
440
616
|
);
|
|
441
617
|
DialogFooter.displayName = "DialogFooter";
|
|
442
|
-
var DialogTitle =
|
|
618
|
+
var DialogTitle = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
443
619
|
PrimitiveTitle,
|
|
444
620
|
{
|
|
445
621
|
ref,
|
|
@@ -448,7 +624,7 @@ var DialogTitle = React10.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
448
624
|
}
|
|
449
625
|
));
|
|
450
626
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
451
|
-
var DialogDescription =
|
|
627
|
+
var DialogDescription = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
452
628
|
PrimitiveDescription,
|
|
453
629
|
{
|
|
454
630
|
ref,
|
|
@@ -459,7 +635,7 @@ var DialogDescription = React10.forwardRef(({ className, ...props }, ref) => /*
|
|
|
459
635
|
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
460
636
|
|
|
461
637
|
// src/components/PageHeader.tsx
|
|
462
|
-
var
|
|
638
|
+
var React12 = __toESM(require("react"));
|
|
463
639
|
var import_class_variance_authority4 = require("class-variance-authority");
|
|
464
640
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
465
641
|
var pageHeaderContainerVariants = (0, import_class_variance_authority4.cva)("", {
|
|
@@ -510,25 +686,34 @@ var pageHeaderActionsVariants = (0, import_class_variance_authority4.cva)("flex
|
|
|
510
686
|
variant: "default"
|
|
511
687
|
}
|
|
512
688
|
});
|
|
513
|
-
var PageHeader =
|
|
514
|
-
({ className, variant, title, subtitle, actions, ...props }, ref) =>
|
|
515
|
-
"
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { className: pageHeaderTitleVariants({ variant }), children: title }),
|
|
522
|
-
subtitle && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: pageHeaderSubtitleVariants({ variant }), children: subtitle }),
|
|
523
|
-
actions && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: pageHeaderActionsVariants({ variant }), children: actions })
|
|
524
|
-
]
|
|
689
|
+
var PageHeader = React12.forwardRef(
|
|
690
|
+
({ className, variant, title, subtitle, actions, as: Heading = "h1", ...props }, ref) => {
|
|
691
|
+
if (process.env.NODE_ENV !== "production") {
|
|
692
|
+
if (Heading === "h1") {
|
|
693
|
+
console.warn(
|
|
694
|
+
'PageHeader: Using as="h1" (the default). Ensure there is only one h1 per page for proper document structure. Consider as="h2" for secondary headers.'
|
|
695
|
+
);
|
|
696
|
+
}
|
|
525
697
|
}
|
|
526
|
-
|
|
698
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
699
|
+
"header",
|
|
700
|
+
{
|
|
701
|
+
ref,
|
|
702
|
+
className: cn(pageHeaderContainerVariants({ variant }), className),
|
|
703
|
+
...props,
|
|
704
|
+
children: [
|
|
705
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Heading, { className: pageHeaderTitleVariants({ variant }), children: title }),
|
|
706
|
+
subtitle && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: pageHeaderSubtitleVariants({ variant }), children: subtitle }),
|
|
707
|
+
actions && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: pageHeaderActionsVariants({ variant }), children: actions })
|
|
708
|
+
]
|
|
709
|
+
}
|
|
710
|
+
);
|
|
711
|
+
}
|
|
527
712
|
);
|
|
528
713
|
PageHeader.displayName = "PageHeader";
|
|
529
714
|
|
|
530
715
|
// src/components/DataPanel.tsx
|
|
531
|
-
var
|
|
716
|
+
var React13 = __toESM(require("react"));
|
|
532
717
|
var DropdownMenuPrimitive = __toESM(require("@radix-ui/react-dropdown-menu"));
|
|
533
718
|
var import_data_panel_core = require("@classic-homes/data-panel-core");
|
|
534
719
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
@@ -546,28 +731,28 @@ function useDataPanel(options = {}) {
|
|
|
546
731
|
constraints = {}
|
|
547
732
|
} = options;
|
|
548
733
|
const resolvedConstraints = { ...import_data_panel_core.DEFAULT_CONSTRAINTS, ...constraints };
|
|
549
|
-
const [persistedState] =
|
|
734
|
+
const [persistedState] = React13.useState(() => {
|
|
550
735
|
if (persistKey && typeof window !== "undefined") {
|
|
551
736
|
return (0, import_data_panel_core.loadPanelState)(persistKey);
|
|
552
737
|
}
|
|
553
738
|
return null;
|
|
554
739
|
});
|
|
555
|
-
const [mode, setMode] =
|
|
556
|
-
const [edge, setEdge] =
|
|
557
|
-
const [isExpanded, setIsExpanded] =
|
|
740
|
+
const [mode, setMode] = React13.useState(persistedState?.mode ?? initialMode);
|
|
741
|
+
const [edge, setEdge] = React13.useState(persistedState?.edge ?? initialEdge);
|
|
742
|
+
const [isExpanded, setIsExpanded] = React13.useState(
|
|
558
743
|
persistedState?.isExpanded ?? initialExpanded
|
|
559
744
|
);
|
|
560
|
-
const [detachedPosition, setDetachedPosition] =
|
|
745
|
+
const [detachedPosition, setDetachedPosition] = React13.useState(
|
|
561
746
|
persistedState?.detachedPosition ?? import_data_panel_core.DEFAULT_PANEL_STATE.detachedPosition
|
|
562
747
|
);
|
|
563
|
-
const [detachedSize, setDetachedSize] =
|
|
748
|
+
const [detachedSize, setDetachedSize] = React13.useState(
|
|
564
749
|
persistedState?.detachedSize ?? import_data_panel_core.DEFAULT_PANEL_STATE.detachedSize
|
|
565
750
|
);
|
|
566
|
-
const [pinnedSize, setPinnedSize] =
|
|
751
|
+
const [pinnedSize, setPinnedSize] = React13.useState(
|
|
567
752
|
persistedState?.pinnedSize ?? import_data_panel_core.DEFAULT_PANEL_STATE.pinnedSize
|
|
568
753
|
);
|
|
569
|
-
const saveTimeoutRef =
|
|
570
|
-
const debouncedSave =
|
|
754
|
+
const saveTimeoutRef = React13.useRef(null);
|
|
755
|
+
const debouncedSave = React13.useCallback(() => {
|
|
571
756
|
if (!persistKey) return;
|
|
572
757
|
if (saveTimeoutRef.current) {
|
|
573
758
|
clearTimeout(saveTimeoutRef.current);
|
|
@@ -585,7 +770,7 @@ function useDataPanel(options = {}) {
|
|
|
585
770
|
});
|
|
586
771
|
}, 300);
|
|
587
772
|
}, [persistKey, mode, edge, isExpanded, detachedPosition, detachedSize, pinnedSize]);
|
|
588
|
-
const handleSetMode =
|
|
773
|
+
const handleSetMode = React13.useCallback(
|
|
589
774
|
(newMode) => {
|
|
590
775
|
setMode(newMode);
|
|
591
776
|
if (newMode === "detached" && typeof window !== "undefined" && detachedPosition.x === import_data_panel_core.DEFAULT_PANEL_STATE.detachedPosition.x && detachedPosition.y === import_data_panel_core.DEFAULT_PANEL_STATE.detachedPosition.y) {
|
|
@@ -596,7 +781,7 @@ function useDataPanel(options = {}) {
|
|
|
596
781
|
},
|
|
597
782
|
[detachedPosition, detachedSize]
|
|
598
783
|
);
|
|
599
|
-
const handleSetDetachedPosition =
|
|
784
|
+
const handleSetDetachedPosition = React13.useCallback(
|
|
600
785
|
(position) => {
|
|
601
786
|
if (typeof window === "undefined") {
|
|
602
787
|
setDetachedPosition(position);
|
|
@@ -608,13 +793,13 @@ function useDataPanel(options = {}) {
|
|
|
608
793
|
},
|
|
609
794
|
[detachedSize]
|
|
610
795
|
);
|
|
611
|
-
const handleSetDetachedSize =
|
|
796
|
+
const handleSetDetachedSize = React13.useCallback(
|
|
612
797
|
(size) => {
|
|
613
798
|
setDetachedSize((0, import_data_panel_core.constrainSize)(size, resolvedConstraints));
|
|
614
799
|
},
|
|
615
800
|
[resolvedConstraints]
|
|
616
801
|
);
|
|
617
|
-
const handleSetPinnedSize =
|
|
802
|
+
const handleSetPinnedSize = React13.useCallback(
|
|
618
803
|
(size) => {
|
|
619
804
|
if (typeof window === "undefined") {
|
|
620
805
|
setPinnedSize(size);
|
|
@@ -628,7 +813,7 @@ function useDataPanel(options = {}) {
|
|
|
628
813
|
},
|
|
629
814
|
[edge, resolvedConstraints]
|
|
630
815
|
);
|
|
631
|
-
|
|
816
|
+
React13.useEffect(() => {
|
|
632
817
|
debouncedSave();
|
|
633
818
|
}, [debouncedSave]);
|
|
634
819
|
return {
|
|
@@ -704,10 +889,11 @@ var edgeLabels = {
|
|
|
704
889
|
top: "Pin to top",
|
|
705
890
|
bottom: "Pin to bottom"
|
|
706
891
|
};
|
|
707
|
-
var DataPanelHeader =
|
|
892
|
+
var DataPanelHeader = React13.forwardRef(
|
|
708
893
|
({
|
|
709
894
|
title,
|
|
710
895
|
subtitle,
|
|
896
|
+
titleId,
|
|
711
897
|
mode,
|
|
712
898
|
edge,
|
|
713
899
|
isExpanded,
|
|
@@ -734,7 +920,7 @@ var DataPanelHeader = React12.forwardRef(
|
|
|
734
920
|
"data-panel-header": true,
|
|
735
921
|
children: [
|
|
736
922
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex flex-col min-w-0 flex-1", children: headerContent ? headerContent : /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
737
|
-
title && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { className: "text-sm font-semibold leading-none truncate", children: title }),
|
|
923
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { id: titleId, className: "text-sm font-semibold leading-none truncate", children: title }),
|
|
738
924
|
subtitle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-xs text-muted-foreground mt-1 truncate", children: subtitle })
|
|
739
925
|
] }) }),
|
|
740
926
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center gap-1 shrink-0", children: [
|
|
@@ -816,13 +1002,22 @@ var DataPanelHeader = React12.forwardRef(
|
|
|
816
1002
|
}
|
|
817
1003
|
);
|
|
818
1004
|
DataPanelHeader.displayName = "DataPanelHeader";
|
|
819
|
-
var DataPanelContent =
|
|
820
|
-
({ children, className }, ref) => {
|
|
821
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1005
|
+
var DataPanelContent = React13.forwardRef(
|
|
1006
|
+
({ children, className, "aria-label": ariaLabel = "Panel content" }, ref) => {
|
|
1007
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1008
|
+
"div",
|
|
1009
|
+
{
|
|
1010
|
+
ref,
|
|
1011
|
+
role: "region",
|
|
1012
|
+
"aria-label": ariaLabel,
|
|
1013
|
+
className: cn("flex-1 overflow-auto p-4", className),
|
|
1014
|
+
children
|
|
1015
|
+
}
|
|
1016
|
+
);
|
|
822
1017
|
}
|
|
823
1018
|
);
|
|
824
1019
|
DataPanelContent.displayName = "DataPanelContent";
|
|
825
|
-
var DataPanelFooter =
|
|
1020
|
+
var DataPanelFooter = React13.forwardRef(
|
|
826
1021
|
({ actions = [], footerContent, footerActions, className }, ref) => {
|
|
827
1022
|
if (!footerContent && actions.length === 0 && !footerActions) {
|
|
828
1023
|
return null;
|
|
@@ -858,7 +1053,7 @@ var DataPanelFooter = React12.forwardRef(
|
|
|
858
1053
|
}
|
|
859
1054
|
);
|
|
860
1055
|
DataPanelFooter.displayName = "DataPanelFooter";
|
|
861
|
-
var DataPanelTab =
|
|
1056
|
+
var DataPanelTab = React13.forwardRef(
|
|
862
1057
|
({ title = "Panel", edge, onClick, className }, ref) => {
|
|
863
1058
|
const positionClasses = {
|
|
864
1059
|
left: "left-0 top-1/2 -translate-y-1/2 rounded-r-md border-l-0",
|
|
@@ -895,7 +1090,186 @@ var DataPanelTab = React12.forwardRef(
|
|
|
895
1090
|
}
|
|
896
1091
|
);
|
|
897
1092
|
DataPanelTab.displayName = "DataPanelTab";
|
|
898
|
-
var
|
|
1093
|
+
var KEYBOARD_RESIZE_STEP = 10;
|
|
1094
|
+
var KEYBOARD_RESIZE_STEP_LARGE = 50;
|
|
1095
|
+
function ResizeHandles({
|
|
1096
|
+
mode,
|
|
1097
|
+
edge,
|
|
1098
|
+
detachedSize,
|
|
1099
|
+
pinnedSize,
|
|
1100
|
+
onResizeStart,
|
|
1101
|
+
onSizeChange,
|
|
1102
|
+
onPinnedSizeChange,
|
|
1103
|
+
constraints
|
|
1104
|
+
}) {
|
|
1105
|
+
const handleDetachedKeyDown = React13.useCallback(
|
|
1106
|
+
(e, handle) => {
|
|
1107
|
+
const step = e.shiftKey ? KEYBOARD_RESIZE_STEP_LARGE : KEYBOARD_RESIZE_STEP;
|
|
1108
|
+
let newSize = { ...detachedSize };
|
|
1109
|
+
let handled = false;
|
|
1110
|
+
switch (e.key) {
|
|
1111
|
+
case "ArrowUp":
|
|
1112
|
+
if (handle.includes("top")) {
|
|
1113
|
+
newSize.height = Math.max(constraints.minHeight || 200, detachedSize.height + step);
|
|
1114
|
+
handled = true;
|
|
1115
|
+
} else if (handle.includes("bottom")) {
|
|
1116
|
+
newSize.height = Math.max(constraints.minHeight || 200, detachedSize.height - step);
|
|
1117
|
+
handled = true;
|
|
1118
|
+
}
|
|
1119
|
+
break;
|
|
1120
|
+
case "ArrowDown":
|
|
1121
|
+
if (handle.includes("top")) {
|
|
1122
|
+
newSize.height = Math.max(constraints.minHeight || 200, detachedSize.height - step);
|
|
1123
|
+
handled = true;
|
|
1124
|
+
} else if (handle.includes("bottom")) {
|
|
1125
|
+
newSize.height = Math.min(constraints.maxHeight || 800, detachedSize.height + step);
|
|
1126
|
+
handled = true;
|
|
1127
|
+
}
|
|
1128
|
+
break;
|
|
1129
|
+
case "ArrowLeft":
|
|
1130
|
+
if (handle.includes("left")) {
|
|
1131
|
+
newSize.width = Math.max(constraints.minWidth || 280, detachedSize.width + step);
|
|
1132
|
+
handled = true;
|
|
1133
|
+
} else if (handle.includes("right")) {
|
|
1134
|
+
newSize.width = Math.max(constraints.minWidth || 280, detachedSize.width - step);
|
|
1135
|
+
handled = true;
|
|
1136
|
+
}
|
|
1137
|
+
break;
|
|
1138
|
+
case "ArrowRight":
|
|
1139
|
+
if (handle.includes("left")) {
|
|
1140
|
+
newSize.width = Math.max(constraints.minWidth || 280, detachedSize.width - step);
|
|
1141
|
+
handled = true;
|
|
1142
|
+
} else if (handle.includes("right")) {
|
|
1143
|
+
newSize.width = Math.min(constraints.maxWidth || 600, detachedSize.width + step);
|
|
1144
|
+
handled = true;
|
|
1145
|
+
}
|
|
1146
|
+
break;
|
|
1147
|
+
}
|
|
1148
|
+
if (handled) {
|
|
1149
|
+
e.preventDefault();
|
|
1150
|
+
onSizeChange(newSize);
|
|
1151
|
+
}
|
|
1152
|
+
},
|
|
1153
|
+
[detachedSize, constraints, onSizeChange]
|
|
1154
|
+
);
|
|
1155
|
+
const handlePinnedKeyDown = React13.useCallback(
|
|
1156
|
+
(e) => {
|
|
1157
|
+
const step = e.shiftKey ? KEYBOARD_RESIZE_STEP_LARGE : KEYBOARD_RESIZE_STEP;
|
|
1158
|
+
let newSize = pinnedSize;
|
|
1159
|
+
let handled = false;
|
|
1160
|
+
const isHorizontal2 = edge === "left" || edge === "right";
|
|
1161
|
+
if (isHorizontal2) {
|
|
1162
|
+
if (e.key === "ArrowLeft" && edge === "right" || e.key === "ArrowRight" && edge === "left") {
|
|
1163
|
+
newSize = Math.min(constraints.maxWidth || 600, pinnedSize + step);
|
|
1164
|
+
handled = true;
|
|
1165
|
+
} else if (e.key === "ArrowRight" && edge === "right" || e.key === "ArrowLeft" && edge === "left") {
|
|
1166
|
+
newSize = Math.max(constraints.minWidth || 280, pinnedSize - step);
|
|
1167
|
+
handled = true;
|
|
1168
|
+
}
|
|
1169
|
+
} else {
|
|
1170
|
+
if (e.key === "ArrowUp" && edge === "bottom" || e.key === "ArrowDown" && edge === "top") {
|
|
1171
|
+
newSize = Math.min(constraints.maxHeight || 800, pinnedSize + step);
|
|
1172
|
+
handled = true;
|
|
1173
|
+
} else if (e.key === "ArrowDown" && edge === "bottom" || e.key === "ArrowUp" && edge === "top") {
|
|
1174
|
+
newSize = Math.max(constraints.minHeight || 200, pinnedSize - step);
|
|
1175
|
+
handled = true;
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
if (handled) {
|
|
1179
|
+
e.preventDefault();
|
|
1180
|
+
onPinnedSizeChange(newSize);
|
|
1181
|
+
}
|
|
1182
|
+
},
|
|
1183
|
+
[edge, pinnedSize, constraints, onPinnedSizeChange]
|
|
1184
|
+
);
|
|
1185
|
+
const getAriaValueNow = (handle) => {
|
|
1186
|
+
if (handle.includes("left") || handle.includes("right")) {
|
|
1187
|
+
return mode === "detached" ? detachedSize.width : pinnedSize;
|
|
1188
|
+
}
|
|
1189
|
+
return mode === "detached" ? detachedSize.height : pinnedSize;
|
|
1190
|
+
};
|
|
1191
|
+
const getAriaValueMinMax = (handle) => {
|
|
1192
|
+
const isWidth = handle.includes("left") || handle.includes("right");
|
|
1193
|
+
if (isWidth) {
|
|
1194
|
+
return {
|
|
1195
|
+
min: constraints.minWidth || 280,
|
|
1196
|
+
max: constraints.maxWidth || 600
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
return {
|
|
1200
|
+
min: constraints.minHeight || 200,
|
|
1201
|
+
max: constraints.maxHeight || 800
|
|
1202
|
+
};
|
|
1203
|
+
};
|
|
1204
|
+
if (mode === "detached") {
|
|
1205
|
+
const handles = [
|
|
1206
|
+
"top",
|
|
1207
|
+
"bottom",
|
|
1208
|
+
"left",
|
|
1209
|
+
"right",
|
|
1210
|
+
"top-left",
|
|
1211
|
+
"top-right",
|
|
1212
|
+
"bottom-left",
|
|
1213
|
+
"bottom-right"
|
|
1214
|
+
];
|
|
1215
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_jsx_runtime12.Fragment, { children: handles.map((handle) => {
|
|
1216
|
+
const isCorner = handle.includes("-");
|
|
1217
|
+
const isHorizontal2 = handle === "top" || handle === "bottom";
|
|
1218
|
+
const isVertical = handle === "left" || handle === "right";
|
|
1219
|
+
const { min: min2, max: max2 } = getAriaValueMinMax(handle);
|
|
1220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1221
|
+
"div",
|
|
1222
|
+
{
|
|
1223
|
+
className: cn(
|
|
1224
|
+
"resize-handle",
|
|
1225
|
+
isHorizontal2 && "resize-handle--horizontal",
|
|
1226
|
+
isVertical && "resize-handle--vertical",
|
|
1227
|
+
isCorner && "resize-handle--corner",
|
|
1228
|
+
`resize-handle--${handle}`
|
|
1229
|
+
),
|
|
1230
|
+
role: "slider",
|
|
1231
|
+
tabIndex: 0,
|
|
1232
|
+
"aria-orientation": isVertical ? "vertical" : "horizontal",
|
|
1233
|
+
"aria-label": `Resize panel from ${handle.replace("-", " ")} ${isCorner ? "corner" : "edge"}`,
|
|
1234
|
+
"aria-valuenow": getAriaValueNow(handle),
|
|
1235
|
+
"aria-valuemin": min2,
|
|
1236
|
+
"aria-valuemax": max2,
|
|
1237
|
+
"aria-valuetext": `${getAriaValueNow(handle)} pixels`,
|
|
1238
|
+
style: isCorner ? { "--handle-radius": "6px" } : void 0,
|
|
1239
|
+
onPointerDown: (e) => onResizeStart(e, handle),
|
|
1240
|
+
onKeyDown: (e) => handleDetachedKeyDown(e, handle)
|
|
1241
|
+
},
|
|
1242
|
+
handle
|
|
1243
|
+
);
|
|
1244
|
+
}) });
|
|
1245
|
+
}
|
|
1246
|
+
const pinnedHandle = (0, import_data_panel_core.getPinnedResizeHandle)(edge);
|
|
1247
|
+
const isHorizontal = edge === "left" || edge === "right";
|
|
1248
|
+
const { min, max } = getAriaValueMinMax(pinnedHandle);
|
|
1249
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1250
|
+
"div",
|
|
1251
|
+
{
|
|
1252
|
+
className: cn(
|
|
1253
|
+
"resize-handle",
|
|
1254
|
+
edge === "left" && "resize-handle--vertical resize-handle--right",
|
|
1255
|
+
edge === "right" && "resize-handle--vertical resize-handle--left",
|
|
1256
|
+
edge === "top" && "resize-handle--horizontal resize-handle--bottom",
|
|
1257
|
+
edge === "bottom" && "resize-handle--horizontal resize-handle--top"
|
|
1258
|
+
),
|
|
1259
|
+
role: "slider",
|
|
1260
|
+
tabIndex: 0,
|
|
1261
|
+
"aria-orientation": isHorizontal ? "horizontal" : "vertical",
|
|
1262
|
+
"aria-label": `Resize panel from ${edge} edge`,
|
|
1263
|
+
"aria-valuenow": pinnedSize,
|
|
1264
|
+
"aria-valuemin": min,
|
|
1265
|
+
"aria-valuemax": max,
|
|
1266
|
+
"aria-valuetext": `${pinnedSize} pixels`,
|
|
1267
|
+
onPointerDown: (e) => onResizeStart(e, pinnedHandle),
|
|
1268
|
+
onKeyDown: handlePinnedKeyDown
|
|
1269
|
+
}
|
|
1270
|
+
);
|
|
1271
|
+
}
|
|
1272
|
+
var DataPanel = React13.forwardRef(
|
|
899
1273
|
({
|
|
900
1274
|
open: controlledOpen,
|
|
901
1275
|
onOpenChange,
|
|
@@ -924,31 +1298,33 @@ var DataPanel = React12.forwardRef(
|
|
|
924
1298
|
className
|
|
925
1299
|
}, ref) => {
|
|
926
1300
|
const resolvedConstraints = { ...import_data_panel_core.DEFAULT_CONSTRAINTS, ...constraints };
|
|
927
|
-
const
|
|
928
|
-
const
|
|
929
|
-
const [
|
|
930
|
-
const [
|
|
1301
|
+
const panelId = React13.useId();
|
|
1302
|
+
const titleId = `${panelId}-title`;
|
|
1303
|
+
const [internalOpen, setInternalOpen] = React13.useState(true);
|
|
1304
|
+
const [internalMode, setInternalMode] = React13.useState(import_data_panel_core.DEFAULT_PANEL_STATE.mode);
|
|
1305
|
+
const [internalEdge, setInternalEdge] = React13.useState(import_data_panel_core.DEFAULT_PANEL_STATE.edge);
|
|
1306
|
+
const [internalExpanded, setInternalExpanded] = React13.useState(
|
|
931
1307
|
import_data_panel_core.DEFAULT_PANEL_STATE.isExpanded
|
|
932
1308
|
);
|
|
933
|
-
const [detachedPosition, setDetachedPosition] =
|
|
1309
|
+
const [detachedPosition, setDetachedPosition] = React13.useState(
|
|
934
1310
|
import_data_panel_core.DEFAULT_PANEL_STATE.detachedPosition
|
|
935
1311
|
);
|
|
936
|
-
const [detachedSize, setDetachedSize] =
|
|
937
|
-
const [pinnedSize, setPinnedSize] =
|
|
938
|
-
const [isDragging, setIsDragging] =
|
|
939
|
-
const [isResizing, setIsResizing] =
|
|
940
|
-
const [snapPreview, setSnapPreview] =
|
|
941
|
-
const [isPinnedDragging, setIsPinnedDragging] =
|
|
942
|
-
const [pullOffset, setPullOffset] =
|
|
943
|
-
const dragStateRef =
|
|
1312
|
+
const [detachedSize, setDetachedSize] = React13.useState(import_data_panel_core.DEFAULT_PANEL_STATE.detachedSize);
|
|
1313
|
+
const [pinnedSize, setPinnedSize] = React13.useState(import_data_panel_core.DEFAULT_PANEL_STATE.pinnedSize);
|
|
1314
|
+
const [isDragging, setIsDragging] = React13.useState(false);
|
|
1315
|
+
const [isResizing, setIsResizing] = React13.useState(false);
|
|
1316
|
+
const [snapPreview, setSnapPreview] = React13.useState(null);
|
|
1317
|
+
const [isPinnedDragging, setIsPinnedDragging] = React13.useState(false);
|
|
1318
|
+
const [pullOffset, setPullOffset] = React13.useState(0);
|
|
1319
|
+
const dragStateRef = React13.useRef({
|
|
944
1320
|
startPosition: { x: 0, y: 0 },
|
|
945
1321
|
startPanelPosition: { x: 0, y: 0 }
|
|
946
1322
|
});
|
|
947
|
-
const pinnedDragStateRef =
|
|
1323
|
+
const pinnedDragStateRef = React13.useRef({
|
|
948
1324
|
startPosition: { x: 0, y: 0 },
|
|
949
1325
|
hasDetached: false
|
|
950
1326
|
});
|
|
951
|
-
const resizeStateRef =
|
|
1327
|
+
const resizeStateRef = React13.useRef({
|
|
952
1328
|
handle: null,
|
|
953
1329
|
startPosition: { x: 0, y: 0 },
|
|
954
1330
|
startSize: { width: 0, height: 0 },
|
|
@@ -958,8 +1334,8 @@ var DataPanel = React12.forwardRef(
|
|
|
958
1334
|
const mode = controlledMode ?? internalMode;
|
|
959
1335
|
const edge = controlledEdge ?? internalEdge;
|
|
960
1336
|
const isExpanded = controlledExpanded ?? internalExpanded;
|
|
961
|
-
const saveTimeoutRef =
|
|
962
|
-
const debouncedSave =
|
|
1337
|
+
const saveTimeoutRef = React13.useRef(null);
|
|
1338
|
+
const debouncedSave = React13.useCallback(() => {
|
|
963
1339
|
if (!persistKey) return;
|
|
964
1340
|
if (saveTimeoutRef.current) {
|
|
965
1341
|
clearTimeout(saveTimeoutRef.current);
|
|
@@ -985,7 +1361,7 @@ var DataPanel = React12.forwardRef(
|
|
|
985
1361
|
detachedSize,
|
|
986
1362
|
pinnedSize
|
|
987
1363
|
]);
|
|
988
|
-
|
|
1364
|
+
React13.useEffect(() => {
|
|
989
1365
|
if (!persistKey) return;
|
|
990
1366
|
const persisted = (0, import_data_panel_core.loadPanelState)(persistKey);
|
|
991
1367
|
if (persisted) {
|
|
@@ -998,7 +1374,7 @@ var DataPanel = React12.forwardRef(
|
|
|
998
1374
|
if (persisted.pinnedSize) setPinnedSize(persisted.pinnedSize);
|
|
999
1375
|
}
|
|
1000
1376
|
}, [persistKey, controlledMode, controlledEdge, controlledExpanded]);
|
|
1001
|
-
|
|
1377
|
+
React13.useEffect(() => {
|
|
1002
1378
|
if (mode === "detached" && detachedPosition.x === import_data_panel_core.DEFAULT_PANEL_STATE.detachedPosition.x && detachedPosition.y === import_data_panel_core.DEFAULT_PANEL_STATE.detachedPosition.y) {
|
|
1003
1379
|
setDetachedPosition(
|
|
1004
1380
|
(0, import_data_panel_core.getInitialDetachedPosition)(detachedSize, window.innerWidth, window.innerHeight)
|
|
@@ -1056,7 +1432,7 @@ var DataPanel = React12.forwardRef(
|
|
|
1056
1432
|
document.body.style.userSelect = "none";
|
|
1057
1433
|
}
|
|
1058
1434
|
};
|
|
1059
|
-
const handleDragMove =
|
|
1435
|
+
const handleDragMove = React13.useCallback(
|
|
1060
1436
|
(e) => {
|
|
1061
1437
|
if (!isDragging) return;
|
|
1062
1438
|
const currentPos = (0, import_data_panel_core.getPointerPosition)(e);
|
|
@@ -1083,7 +1459,7 @@ var DataPanel = React12.forwardRef(
|
|
|
1083
1459
|
},
|
|
1084
1460
|
[isDragging, detachedSize, snapThreshold]
|
|
1085
1461
|
);
|
|
1086
|
-
const handleDragEnd =
|
|
1462
|
+
const handleDragEnd = React13.useCallback(() => {
|
|
1087
1463
|
if (!isDragging) return;
|
|
1088
1464
|
setIsDragging(false);
|
|
1089
1465
|
document.body.style.cursor = "";
|
|
@@ -1096,7 +1472,7 @@ var DataPanel = React12.forwardRef(
|
|
|
1096
1472
|
debouncedSave();
|
|
1097
1473
|
}
|
|
1098
1474
|
}, [isDragging, snapPreview, handleModeChange, handleEdgeChange, debouncedSave]);
|
|
1099
|
-
const handlePinnedDragMove =
|
|
1475
|
+
const handlePinnedDragMove = React13.useCallback(
|
|
1100
1476
|
(e) => {
|
|
1101
1477
|
if (!isPinnedDragging) return;
|
|
1102
1478
|
const currentPos = (0, import_data_panel_core.getPointerPosition)(e);
|
|
@@ -1132,7 +1508,7 @@ var DataPanel = React12.forwardRef(
|
|
|
1132
1508
|
},
|
|
1133
1509
|
[isPinnedDragging, edge, detachThreshold, pinnedSize, detachedSize, handleModeChange]
|
|
1134
1510
|
);
|
|
1135
|
-
const handlePinnedDragEnd =
|
|
1511
|
+
const handlePinnedDragEnd = React13.useCallback(() => {
|
|
1136
1512
|
if (!isPinnedDragging) return;
|
|
1137
1513
|
setIsPinnedDragging(false);
|
|
1138
1514
|
setPullOffset(0);
|
|
@@ -1154,7 +1530,7 @@ var DataPanel = React12.forwardRef(
|
|
|
1154
1530
|
document.body.style.cursor = (0, import_data_panel_core.getResizeCursor)(handle);
|
|
1155
1531
|
document.body.style.userSelect = "none";
|
|
1156
1532
|
};
|
|
1157
|
-
const handleResizeMove =
|
|
1533
|
+
const handleResizeMove = React13.useCallback(
|
|
1158
1534
|
(e) => {
|
|
1159
1535
|
if (!isResizing || !resizeStateRef.current.handle) return;
|
|
1160
1536
|
const currentPos = (0, import_data_panel_core.getPointerPosition)(e);
|
|
@@ -1192,7 +1568,7 @@ var DataPanel = React12.forwardRef(
|
|
|
1192
1568
|
},
|
|
1193
1569
|
[isResizing, mode, edge, resolvedConstraints]
|
|
1194
1570
|
);
|
|
1195
|
-
const handleResizeEnd =
|
|
1571
|
+
const handleResizeEnd = React13.useCallback(() => {
|
|
1196
1572
|
if (!isResizing) return;
|
|
1197
1573
|
setIsResizing(false);
|
|
1198
1574
|
resizeStateRef.current.handle = null;
|
|
@@ -1200,7 +1576,7 @@ var DataPanel = React12.forwardRef(
|
|
|
1200
1576
|
document.body.style.userSelect = "";
|
|
1201
1577
|
debouncedSave();
|
|
1202
1578
|
}, [isResizing, debouncedSave]);
|
|
1203
|
-
|
|
1579
|
+
React13.useEffect(() => {
|
|
1204
1580
|
if (isDragging) {
|
|
1205
1581
|
window.addEventListener("pointermove", handleDragMove);
|
|
1206
1582
|
window.addEventListener("pointerup", handleDragEnd);
|
|
@@ -1210,7 +1586,7 @@ var DataPanel = React12.forwardRef(
|
|
|
1210
1586
|
};
|
|
1211
1587
|
}
|
|
1212
1588
|
}, [isDragging, handleDragMove, handleDragEnd]);
|
|
1213
|
-
|
|
1589
|
+
React13.useEffect(() => {
|
|
1214
1590
|
if (isPinnedDragging) {
|
|
1215
1591
|
window.addEventListener("pointermove", handlePinnedDragMove);
|
|
1216
1592
|
window.addEventListener("pointerup", handlePinnedDragEnd);
|
|
@@ -1220,7 +1596,7 @@ var DataPanel = React12.forwardRef(
|
|
|
1220
1596
|
};
|
|
1221
1597
|
}
|
|
1222
1598
|
}, [isPinnedDragging, handlePinnedDragMove, handlePinnedDragEnd]);
|
|
1223
|
-
|
|
1599
|
+
React13.useEffect(() => {
|
|
1224
1600
|
if (isResizing) {
|
|
1225
1601
|
window.addEventListener("pointermove", handleResizeMove);
|
|
1226
1602
|
window.addEventListener("pointerup", handleResizeEnd);
|
|
@@ -1230,7 +1606,7 @@ var DataPanel = React12.forwardRef(
|
|
|
1230
1606
|
};
|
|
1231
1607
|
}
|
|
1232
1608
|
}, [isResizing, handleResizeMove, handleResizeEnd]);
|
|
1233
|
-
const panelStyles =
|
|
1609
|
+
const panelStyles = React13.useMemo(() => {
|
|
1234
1610
|
if (mode === "pinned") {
|
|
1235
1611
|
const baseStyles = (0, import_data_panel_core.getPinnedPositionStyles)(edge, pinnedSize);
|
|
1236
1612
|
if (pullOffset > 0) {
|
|
@@ -1283,9 +1659,10 @@ var DataPanel = React12.forwardRef(
|
|
|
1283
1659
|
className
|
|
1284
1660
|
),
|
|
1285
1661
|
style: panelStyles,
|
|
1286
|
-
role: mode === "detached" ? "dialog" :
|
|
1662
|
+
role: mode === "detached" ? "dialog" : "complementary",
|
|
1287
1663
|
"aria-modal": mode === "detached" ? "true" : void 0,
|
|
1288
|
-
"aria-labelledby": title ?
|
|
1664
|
+
"aria-labelledby": title ? titleId : void 0,
|
|
1665
|
+
"aria-label": !title ? "Side panel" : void 0,
|
|
1289
1666
|
onPointerDown: handleDragStart,
|
|
1290
1667
|
children: [
|
|
1291
1668
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
@@ -1293,6 +1670,7 @@ var DataPanel = React12.forwardRef(
|
|
|
1293
1670
|
{
|
|
1294
1671
|
title,
|
|
1295
1672
|
subtitle,
|
|
1673
|
+
titleId,
|
|
1296
1674
|
mode,
|
|
1297
1675
|
edge,
|
|
1298
1676
|
isExpanded,
|
|
@@ -1316,80 +1694,31 @@ var DataPanel = React12.forwardRef(
|
|
|
1316
1694
|
footerActions
|
|
1317
1695
|
}
|
|
1318
1696
|
),
|
|
1319
|
-
!disableResize && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1320
|
-
|
|
1321
|
-
"div",
|
|
1322
|
-
{
|
|
1323
|
-
className: "resize-handle resize-handle--horizontal resize-handle--top",
|
|
1324
|
-
onPointerDown: (e) => handleResizeStart(e, "top")
|
|
1325
|
-
}
|
|
1326
|
-
),
|
|
1327
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1328
|
-
"div",
|
|
1329
|
-
{
|
|
1330
|
-
className: "resize-handle resize-handle--horizontal resize-handle--bottom",
|
|
1331
|
-
onPointerDown: (e) => handleResizeStart(e, "bottom")
|
|
1332
|
-
}
|
|
1333
|
-
),
|
|
1334
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1335
|
-
"div",
|
|
1336
|
-
{
|
|
1337
|
-
className: "resize-handle resize-handle--vertical resize-handle--left",
|
|
1338
|
-
onPointerDown: (e) => handleResizeStart(e, "left")
|
|
1339
|
-
}
|
|
1340
|
-
),
|
|
1341
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1342
|
-
"div",
|
|
1343
|
-
{
|
|
1344
|
-
className: "resize-handle resize-handle--vertical resize-handle--right",
|
|
1345
|
-
onPointerDown: (e) => handleResizeStart(e, "right")
|
|
1346
|
-
}
|
|
1347
|
-
),
|
|
1348
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1349
|
-
"div",
|
|
1350
|
-
{
|
|
1351
|
-
className: "resize-handle resize-handle--corner resize-handle--top-left",
|
|
1352
|
-
style: { "--handle-radius": "6px" },
|
|
1353
|
-
onPointerDown: (e) => handleResizeStart(e, "top-left")
|
|
1354
|
-
}
|
|
1355
|
-
),
|
|
1356
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1357
|
-
"div",
|
|
1358
|
-
{
|
|
1359
|
-
className: "resize-handle resize-handle--corner resize-handle--top-right",
|
|
1360
|
-
style: { "--handle-radius": "6px" },
|
|
1361
|
-
onPointerDown: (e) => handleResizeStart(e, "top-right")
|
|
1362
|
-
}
|
|
1363
|
-
),
|
|
1364
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1365
|
-
"div",
|
|
1366
|
-
{
|
|
1367
|
-
className: "resize-handle resize-handle--corner resize-handle--bottom-left",
|
|
1368
|
-
style: { "--handle-radius": "6px" },
|
|
1369
|
-
onPointerDown: (e) => handleResizeStart(e, "bottom-left")
|
|
1370
|
-
}
|
|
1371
|
-
),
|
|
1372
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1373
|
-
"div",
|
|
1374
|
-
{
|
|
1375
|
-
className: "resize-handle resize-handle--corner resize-handle--bottom-right",
|
|
1376
|
-
style: { "--handle-radius": "6px" },
|
|
1377
|
-
onPointerDown: (e) => handleResizeStart(e, "bottom-right")
|
|
1378
|
-
}
|
|
1379
|
-
)
|
|
1380
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1381
|
-
"div",
|
|
1697
|
+
!disableResize && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1698
|
+
ResizeHandles,
|
|
1382
1699
|
{
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
)
|
|
1390
|
-
|
|
1700
|
+
mode,
|
|
1701
|
+
edge,
|
|
1702
|
+
detachedSize,
|
|
1703
|
+
pinnedSize,
|
|
1704
|
+
onResizeStart: handleResizeStart,
|
|
1705
|
+
onSizeChange: (size) => setDetachedSize((0, import_data_panel_core.constrainSize)(size, resolvedConstraints)),
|
|
1706
|
+
onPinnedSizeChange: (size) => {
|
|
1707
|
+
if (typeof window === "undefined") {
|
|
1708
|
+
setPinnedSize(size);
|
|
1709
|
+
return;
|
|
1710
|
+
}
|
|
1711
|
+
if ((0, import_data_panel_core.isHorizontalEdge)(edge)) {
|
|
1712
|
+
setPinnedSize((0, import_data_panel_core.constrainPinnedWidth)(size, resolvedConstraints, window.innerWidth));
|
|
1713
|
+
} else {
|
|
1714
|
+
setPinnedSize(
|
|
1715
|
+
(0, import_data_panel_core.constrainPinnedHeight)(size, resolvedConstraints, window.innerHeight)
|
|
1716
|
+
);
|
|
1717
|
+
}
|
|
1718
|
+
},
|
|
1719
|
+
constraints: resolvedConstraints
|
|
1391
1720
|
}
|
|
1392
|
-
)
|
|
1721
|
+
)
|
|
1393
1722
|
]
|
|
1394
1723
|
}
|
|
1395
1724
|
)
|
|
@@ -1397,6 +1726,891 @@ var DataPanel = React12.forwardRef(
|
|
|
1397
1726
|
}
|
|
1398
1727
|
);
|
|
1399
1728
|
DataPanel.displayName = "DataPanel";
|
|
1729
|
+
|
|
1730
|
+
// src/components/Skeleton.tsx
|
|
1731
|
+
var React14 = __toESM(require("react"));
|
|
1732
|
+
var import_class_variance_authority5 = require("class-variance-authority");
|
|
1733
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1734
|
+
var skeletonVariants = (0, import_class_variance_authority5.cva)("rounded-md bg-muted", {
|
|
1735
|
+
variants: {
|
|
1736
|
+
variant: {
|
|
1737
|
+
default: "",
|
|
1738
|
+
text: "h-4 w-full",
|
|
1739
|
+
avatar: "h-12 w-12 rounded-full",
|
|
1740
|
+
card: "h-32 w-full",
|
|
1741
|
+
button: "h-10 w-24",
|
|
1742
|
+
title: "h-6 w-3/4"
|
|
1743
|
+
}
|
|
1744
|
+
},
|
|
1745
|
+
defaultVariants: {
|
|
1746
|
+
variant: "default"
|
|
1747
|
+
}
|
|
1748
|
+
});
|
|
1749
|
+
var Skeleton = React14.forwardRef(
|
|
1750
|
+
({ className, variant, animation = "pulse", ...props }, ref) => {
|
|
1751
|
+
const animationClass = animation === "pulse" ? "animate-pulse" : animation === "shimmer" ? "animate-shimmer" : "";
|
|
1752
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1753
|
+
"div",
|
|
1754
|
+
{
|
|
1755
|
+
ref,
|
|
1756
|
+
className: cn(skeletonVariants({ variant }), animationClass, className),
|
|
1757
|
+
...props
|
|
1758
|
+
}
|
|
1759
|
+
);
|
|
1760
|
+
}
|
|
1761
|
+
);
|
|
1762
|
+
Skeleton.displayName = "Skeleton";
|
|
1763
|
+
|
|
1764
|
+
// src/components/Spinner.tsx
|
|
1765
|
+
var React15 = __toESM(require("react"));
|
|
1766
|
+
var import_class_variance_authority6 = require("class-variance-authority");
|
|
1767
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1768
|
+
var spinnerVariants = (0, import_class_variance_authority6.cva)("animate-spin text-current", {
|
|
1769
|
+
variants: {
|
|
1770
|
+
size: {
|
|
1771
|
+
sm: "h-4 w-4",
|
|
1772
|
+
md: "h-6 w-6",
|
|
1773
|
+
lg: "h-8 w-8",
|
|
1774
|
+
xl: "h-12 w-12"
|
|
1775
|
+
}
|
|
1776
|
+
},
|
|
1777
|
+
defaultVariants: {
|
|
1778
|
+
size: "md"
|
|
1779
|
+
}
|
|
1780
|
+
});
|
|
1781
|
+
var Spinner = React15.forwardRef(
|
|
1782
|
+
({ className, size, label = "Loading...", ...props }, ref) => {
|
|
1783
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1784
|
+
"svg",
|
|
1785
|
+
{
|
|
1786
|
+
ref,
|
|
1787
|
+
className: cn(spinnerVariants({ size }), className),
|
|
1788
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1789
|
+
fill: "none",
|
|
1790
|
+
viewBox: "0 0 24 24",
|
|
1791
|
+
"aria-label": label,
|
|
1792
|
+
role: "status",
|
|
1793
|
+
...props,
|
|
1794
|
+
children: [
|
|
1795
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1796
|
+
"circle",
|
|
1797
|
+
{
|
|
1798
|
+
className: "opacity-25",
|
|
1799
|
+
cx: "12",
|
|
1800
|
+
cy: "12",
|
|
1801
|
+
r: "10",
|
|
1802
|
+
stroke: "currentColor",
|
|
1803
|
+
strokeWidth: "4"
|
|
1804
|
+
}
|
|
1805
|
+
),
|
|
1806
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1807
|
+
"path",
|
|
1808
|
+
{
|
|
1809
|
+
className: "opacity-75",
|
|
1810
|
+
fill: "currentColor",
|
|
1811
|
+
d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
1812
|
+
}
|
|
1813
|
+
),
|
|
1814
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("title", { children: label })
|
|
1815
|
+
]
|
|
1816
|
+
}
|
|
1817
|
+
);
|
|
1818
|
+
}
|
|
1819
|
+
);
|
|
1820
|
+
Spinner.displayName = "Spinner";
|
|
1821
|
+
|
|
1822
|
+
// src/components/LoadingLogo.tsx
|
|
1823
|
+
var React16 = __toESM(require("react"));
|
|
1824
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1825
|
+
var logoPaths = [
|
|
1826
|
+
"M9.902 16.6c.3.7 1.7.8 1-.6-.6-1.4-2.3-5.1-6.1-6.3-1.7-.5-3.7.4-4.3 1.6-.4.7-1.1 2.9.5 4.3.8.7 1.9 1.2 3.6 1 .4-.1.9-.5.6-.8-.5-.4-1.9-1.7-1.1-2.7.7-.8 1.4-.6 2-.3.4.2 2.1 1 3.7 3.6l.1.2z",
|
|
1827
|
+
"M14.602 16.6c-.3.7-1.7.8-1-.6.6-1.4 2.3-5.1 6.1-6.3 1.7-.5 3.7.4 4.3 1.6.4.7 1.1 2.9-.5 4.3-.8.7-1.9 1.2-3.6 1-.4-.1-.9-.5-.6-.8.5-.4 1.9-1.7 1.1-2.7-.7-.8-1.4-.6-2-.3-.4.2-2.1 1-3.7 3.6l-.1.2z",
|
|
1828
|
+
"M12.202 0c.7 1.3 2.1 3.2 2.3 5.3.1 1.5-.8 8.3-2.3 11.7-1.5-3.5-2.4-10.3-2.3-11.7.2-2.1 1.6-4 2.3-5.3z",
|
|
1829
|
+
"M9.002 18.1c-.8 0-.7.8-.1.8h6.7c.7 0 .7-.8-.1-.8h-6.5z",
|
|
1830
|
+
"M13.802 24.8c-1.1-1.1-.9-4.6-.9-4.6h-1.3s.2 3.6-.9 4.6h3.1z",
|
|
1831
|
+
"M14.202 22.5c-.1-.3-.5-1.4-.6-2.3 0-.2.6-.5.7.1.1.6.4 1.6.6 1.9.3.5-.4.9-.7.3z",
|
|
1832
|
+
"M10.302 22.5c.1-.3.5-1.4.6-2.2 0-.3-.5-.6-.7 0-.1.6-.4 1.6-.6 1.9-.3.5.4.9.7.3z"
|
|
1833
|
+
];
|
|
1834
|
+
var colors = {
|
|
1835
|
+
dark: {
|
|
1836
|
+
fill: "#C50F22",
|
|
1837
|
+
fillLoading: "#ffffff",
|
|
1838
|
+
stroke: "#C50F22"
|
|
1839
|
+
},
|
|
1840
|
+
light: {
|
|
1841
|
+
fill: "#ffffff",
|
|
1842
|
+
fillLoading: "#C50F22",
|
|
1843
|
+
stroke: "#ffffff"
|
|
1844
|
+
}
|
|
1845
|
+
};
|
|
1846
|
+
var LoadingLogo = React16.forwardRef(
|
|
1847
|
+
({ width = 40, height = 40, loading = false, variant = "dark", className, ...props }, ref) => {
|
|
1848
|
+
const currentColors = colors[variant];
|
|
1849
|
+
const fillColor = loading ? currentColors.fillLoading : currentColors.fill;
|
|
1850
|
+
const strokeColor = currentColors.stroke;
|
|
1851
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
1852
|
+
"div",
|
|
1853
|
+
{
|
|
1854
|
+
ref,
|
|
1855
|
+
className: cn("inline-flex items-center justify-center", className),
|
|
1856
|
+
style: { width: `${width}px`, height: `${height}px` },
|
|
1857
|
+
role: loading ? "status" : "img",
|
|
1858
|
+
"aria-label": loading ? "Loading" : "Classic Homes",
|
|
1859
|
+
...props,
|
|
1860
|
+
children: [
|
|
1861
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
1862
|
+
"svg",
|
|
1863
|
+
{
|
|
1864
|
+
width: "100%",
|
|
1865
|
+
height: "100%",
|
|
1866
|
+
viewBox: "-1 0 26 25",
|
|
1867
|
+
fill: "none",
|
|
1868
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1869
|
+
"aria-hidden": "true",
|
|
1870
|
+
children: [
|
|
1871
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("g", { fill: fillColor, className: "transition-all duration-300", children: logoPaths.map((path, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: path }, i)) }),
|
|
1872
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1873
|
+
"g",
|
|
1874
|
+
{
|
|
1875
|
+
fill: "none",
|
|
1876
|
+
stroke: strokeColor,
|
|
1877
|
+
strokeWidth: "0.5",
|
|
1878
|
+
strokeDasharray: "10 4",
|
|
1879
|
+
className: "animate-trace",
|
|
1880
|
+
children: logoPaths.map((path, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: path }, i))
|
|
1881
|
+
}
|
|
1882
|
+
)
|
|
1883
|
+
]
|
|
1884
|
+
}
|
|
1885
|
+
),
|
|
1886
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "sr-only", children: "Loading" })
|
|
1887
|
+
]
|
|
1888
|
+
}
|
|
1889
|
+
);
|
|
1890
|
+
}
|
|
1891
|
+
);
|
|
1892
|
+
LoadingLogo.displayName = "LoadingLogo";
|
|
1893
|
+
|
|
1894
|
+
// src/components/ProgressBar.tsx
|
|
1895
|
+
var React17 = __toESM(require("react"));
|
|
1896
|
+
var import_class_variance_authority7 = require("class-variance-authority");
|
|
1897
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1898
|
+
var progressBarVariants = (0, import_class_variance_authority7.cva)("w-full overflow-hidden rounded-full bg-muted", {
|
|
1899
|
+
variants: {
|
|
1900
|
+
size: {
|
|
1901
|
+
sm: "h-1",
|
|
1902
|
+
md: "h-2",
|
|
1903
|
+
lg: "h-3"
|
|
1904
|
+
}
|
|
1905
|
+
},
|
|
1906
|
+
defaultVariants: {
|
|
1907
|
+
size: "md"
|
|
1908
|
+
}
|
|
1909
|
+
});
|
|
1910
|
+
var progressFillVariants = (0, import_class_variance_authority7.cva)("h-full rounded-full transition-all duration-300", {
|
|
1911
|
+
variants: {
|
|
1912
|
+
variant: {
|
|
1913
|
+
default: "bg-primary",
|
|
1914
|
+
success: "bg-success",
|
|
1915
|
+
warning: "bg-warning",
|
|
1916
|
+
destructive: "bg-destructive"
|
|
1917
|
+
}
|
|
1918
|
+
},
|
|
1919
|
+
defaultVariants: {
|
|
1920
|
+
variant: "default"
|
|
1921
|
+
}
|
|
1922
|
+
});
|
|
1923
|
+
var ProgressBar = React17.forwardRef(
|
|
1924
|
+
({ className, size, variant, value, max = 100, label = "Progress", showValue = false, ...props }, ref) => {
|
|
1925
|
+
const isIndeterminate = value === void 0;
|
|
1926
|
+
const clampedValue = isIndeterminate ? 0 : Math.min(Math.max(0, value), max);
|
|
1927
|
+
const percentage = isIndeterminate ? 0 : Math.round(clampedValue / max * 100);
|
|
1928
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
1929
|
+
"div",
|
|
1930
|
+
{
|
|
1931
|
+
ref,
|
|
1932
|
+
role: "progressbar",
|
|
1933
|
+
"aria-label": label,
|
|
1934
|
+
"aria-valuenow": isIndeterminate ? void 0 : clampedValue,
|
|
1935
|
+
"aria-valuemin": 0,
|
|
1936
|
+
"aria-valuemax": max,
|
|
1937
|
+
className: cn("flex items-center gap-2", className),
|
|
1938
|
+
...props,
|
|
1939
|
+
children: [
|
|
1940
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: cn(progressBarVariants({ size })), children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1941
|
+
"div",
|
|
1942
|
+
{
|
|
1943
|
+
className: cn(
|
|
1944
|
+
progressFillVariants({ variant }),
|
|
1945
|
+
isIndeterminate && "w-1/4 animate-progress-indeterminate"
|
|
1946
|
+
),
|
|
1947
|
+
style: isIndeterminate ? void 0 : { width: `${percentage}%` }
|
|
1948
|
+
}
|
|
1949
|
+
) }),
|
|
1950
|
+
showValue && !isIndeterminate && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: "text-sm tabular-nums text-muted-foreground", children: [
|
|
1951
|
+
percentage,
|
|
1952
|
+
"%"
|
|
1953
|
+
] })
|
|
1954
|
+
]
|
|
1955
|
+
}
|
|
1956
|
+
);
|
|
1957
|
+
}
|
|
1958
|
+
);
|
|
1959
|
+
ProgressBar.displayName = "ProgressBar";
|
|
1960
|
+
|
|
1961
|
+
// src/components/LoadingOverlay.tsx
|
|
1962
|
+
var React18 = __toESM(require("react"));
|
|
1963
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1964
|
+
var spinnerSizeMap = { sm: "sm", md: "md", lg: "lg", xl: "xl" };
|
|
1965
|
+
var logoSizeMap = { sm: 32, md: 40, lg: 56, xl: 80 };
|
|
1966
|
+
var LoadingOverlay = React18.forwardRef(
|
|
1967
|
+
({
|
|
1968
|
+
loading = true,
|
|
1969
|
+
variant = "spinner",
|
|
1970
|
+
mode = "overlay",
|
|
1971
|
+
size = "md",
|
|
1972
|
+
message,
|
|
1973
|
+
progress,
|
|
1974
|
+
blur = true,
|
|
1975
|
+
opaque = false,
|
|
1976
|
+
delay = 0,
|
|
1977
|
+
className,
|
|
1978
|
+
children,
|
|
1979
|
+
...props
|
|
1980
|
+
}, ref) => {
|
|
1981
|
+
const [visible, setVisible] = React18.useState(delay === 0 && loading);
|
|
1982
|
+
React18.useEffect(() => {
|
|
1983
|
+
if (!loading) {
|
|
1984
|
+
setVisible(false);
|
|
1985
|
+
return;
|
|
1986
|
+
}
|
|
1987
|
+
if (delay === 0) {
|
|
1988
|
+
setVisible(true);
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1991
|
+
const timer = setTimeout(() => setVisible(true), delay);
|
|
1992
|
+
return () => clearTimeout(timer);
|
|
1993
|
+
}, [loading, delay]);
|
|
1994
|
+
if (!visible) {
|
|
1995
|
+
return mode === "inline" ? null : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_jsx_runtime17.Fragment, { children });
|
|
1996
|
+
}
|
|
1997
|
+
const indicator = /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
1998
|
+
variant === "spinner" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Spinner, { size: spinnerSizeMap[size] }),
|
|
1999
|
+
variant === "logo" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(LoadingLogo, { loading: true, width: logoSizeMap[size], height: logoSizeMap[size] }),
|
|
2000
|
+
variant === "progress" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ProgressBar, { value: progress, className: "w-48 max-w-full" }),
|
|
2001
|
+
variant === "skeleton" && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "w-full space-y-3", children: [
|
|
2002
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Skeleton, { variant: "title" }),
|
|
2003
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Skeleton, { variant: "text" }),
|
|
2004
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Skeleton, { variant: "text" }),
|
|
2005
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Skeleton, { variant: "text", className: "w-2/3" })
|
|
2006
|
+
] }),
|
|
2007
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "mt-2 text-sm text-muted-foreground animate-pulse-subtle", children: message }),
|
|
2008
|
+
!message && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "sr-only", children: "Loading" })
|
|
2009
|
+
] });
|
|
2010
|
+
if (mode === "inline") {
|
|
2011
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2012
|
+
"div",
|
|
2013
|
+
{
|
|
2014
|
+
ref,
|
|
2015
|
+
role: "status",
|
|
2016
|
+
"aria-live": "polite",
|
|
2017
|
+
className: cn("inline-flex items-center gap-2", className),
|
|
2018
|
+
...props,
|
|
2019
|
+
children: indicator
|
|
2020
|
+
}
|
|
2021
|
+
);
|
|
2022
|
+
}
|
|
2023
|
+
const bgClass = opaque ? "bg-background" : mode === "fullscreen" ? "bg-background/80" : "bg-background/60";
|
|
2024
|
+
const positionClass = mode === "fullscreen" ? "fixed inset-0 z-50" : "absolute inset-0 z-10";
|
|
2025
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
2026
|
+
children,
|
|
2027
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2028
|
+
"div",
|
|
2029
|
+
{
|
|
2030
|
+
ref,
|
|
2031
|
+
role: "status",
|
|
2032
|
+
"aria-live": "polite",
|
|
2033
|
+
className: cn(
|
|
2034
|
+
positionClass,
|
|
2035
|
+
bgClass,
|
|
2036
|
+
blur && "backdrop-blur-sm",
|
|
2037
|
+
"flex flex-col items-center justify-center",
|
|
2038
|
+
className
|
|
2039
|
+
),
|
|
2040
|
+
...props,
|
|
2041
|
+
children: indicator
|
|
2042
|
+
}
|
|
2043
|
+
)
|
|
2044
|
+
] });
|
|
2045
|
+
}
|
|
2046
|
+
);
|
|
2047
|
+
LoadingOverlay.displayName = "LoadingOverlay";
|
|
2048
|
+
|
|
2049
|
+
// src/components/LoadingPage.tsx
|
|
2050
|
+
var React19 = __toESM(require("react"));
|
|
2051
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
2052
|
+
var LoadingPage = React19.forwardRef(
|
|
2053
|
+
({
|
|
2054
|
+
loading = true,
|
|
2055
|
+
message,
|
|
2056
|
+
progress,
|
|
2057
|
+
showLogo = true,
|
|
2058
|
+
logoVariant = "dark",
|
|
2059
|
+
delay = 200,
|
|
2060
|
+
className,
|
|
2061
|
+
...props
|
|
2062
|
+
}, ref) => {
|
|
2063
|
+
const [visible, setVisible] = React19.useState(delay === 0 && loading);
|
|
2064
|
+
React19.useEffect(() => {
|
|
2065
|
+
if (!loading) {
|
|
2066
|
+
setVisible(false);
|
|
2067
|
+
return;
|
|
2068
|
+
}
|
|
2069
|
+
if (delay === 0) {
|
|
2070
|
+
setVisible(true);
|
|
2071
|
+
return;
|
|
2072
|
+
}
|
|
2073
|
+
const timer = setTimeout(() => setVisible(true), delay);
|
|
2074
|
+
return () => clearTimeout(timer);
|
|
2075
|
+
}, [loading, delay]);
|
|
2076
|
+
if (!visible) return null;
|
|
2077
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2078
|
+
"div",
|
|
2079
|
+
{
|
|
2080
|
+
ref,
|
|
2081
|
+
role: "status",
|
|
2082
|
+
"aria-live": "polite",
|
|
2083
|
+
className: cn(
|
|
2084
|
+
"fixed inset-0 z-50 flex flex-col items-center justify-center bg-background",
|
|
2085
|
+
className
|
|
2086
|
+
),
|
|
2087
|
+
...props,
|
|
2088
|
+
children: [
|
|
2089
|
+
showLogo ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(LoadingLogo, { loading: true, width: 64, height: 64, variant: logoVariant }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Spinner, { size: "xl" }),
|
|
2090
|
+
progress !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ProgressBar, { value: progress, className: "mt-6 w-48 max-w-full" }),
|
|
2091
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "mt-4 text-sm text-muted-foreground animate-pulse-subtle", children: message }),
|
|
2092
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "sr-only", children: [
|
|
2093
|
+
message || "Loading",
|
|
2094
|
+
progress !== void 0 && `, ${Math.round(progress)}% complete`
|
|
2095
|
+
] })
|
|
2096
|
+
]
|
|
2097
|
+
}
|
|
2098
|
+
);
|
|
2099
|
+
}
|
|
2100
|
+
);
|
|
2101
|
+
LoadingPage.displayName = "LoadingPage";
|
|
2102
|
+
|
|
2103
|
+
// src/components/LoadingSection.tsx
|
|
2104
|
+
var React20 = __toESM(require("react"));
|
|
2105
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2106
|
+
var LoadingSection = React20.forwardRef(
|
|
2107
|
+
({
|
|
2108
|
+
loading = false,
|
|
2109
|
+
variant = "spinner",
|
|
2110
|
+
message,
|
|
2111
|
+
progress,
|
|
2112
|
+
minHeight = "12rem",
|
|
2113
|
+
blur = true,
|
|
2114
|
+
delay = 0,
|
|
2115
|
+
className,
|
|
2116
|
+
children,
|
|
2117
|
+
...props
|
|
2118
|
+
}, ref) => {
|
|
2119
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2120
|
+
"div",
|
|
2121
|
+
{
|
|
2122
|
+
ref,
|
|
2123
|
+
className: cn("relative", className),
|
|
2124
|
+
style: { minHeight },
|
|
2125
|
+
"aria-busy": loading,
|
|
2126
|
+
...props,
|
|
2127
|
+
children: [
|
|
2128
|
+
children,
|
|
2129
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2130
|
+
LoadingOverlay,
|
|
2131
|
+
{
|
|
2132
|
+
mode: "overlay",
|
|
2133
|
+
variant,
|
|
2134
|
+
message,
|
|
2135
|
+
progress,
|
|
2136
|
+
blur,
|
|
2137
|
+
delay
|
|
2138
|
+
}
|
|
2139
|
+
)
|
|
2140
|
+
]
|
|
2141
|
+
}
|
|
2142
|
+
);
|
|
2143
|
+
}
|
|
2144
|
+
);
|
|
2145
|
+
LoadingSection.displayName = "LoadingSection";
|
|
2146
|
+
|
|
2147
|
+
// src/components/LiveRegion.tsx
|
|
2148
|
+
var React21 = __toESM(require("react"));
|
|
2149
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2150
|
+
var LiveRegion = React21.forwardRef(
|
|
2151
|
+
({ message, politeness = "polite", atomic = true, visuallyHidden = true, className, children }, ref) => {
|
|
2152
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2153
|
+
"div",
|
|
2154
|
+
{
|
|
2155
|
+
ref,
|
|
2156
|
+
role: "status",
|
|
2157
|
+
"aria-live": politeness,
|
|
2158
|
+
"aria-atomic": atomic,
|
|
2159
|
+
className: cn(
|
|
2160
|
+
visuallyHidden && "sr-only absolute h-px w-px overflow-hidden whitespace-nowrap border-0 p-0",
|
|
2161
|
+
className
|
|
2162
|
+
),
|
|
2163
|
+
children: message || children
|
|
2164
|
+
}
|
|
2165
|
+
);
|
|
2166
|
+
}
|
|
2167
|
+
);
|
|
2168
|
+
LiveRegion.displayName = "LiveRegion";
|
|
2169
|
+
|
|
2170
|
+
// src/components/SkipLink.tsx
|
|
2171
|
+
var React22 = __toESM(require("react"));
|
|
2172
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2173
|
+
var SkipLink = React22.forwardRef(
|
|
2174
|
+
({ targetId, className, children = "Skip to main content", ...props }, ref) => {
|
|
2175
|
+
const handleClick = (e) => {
|
|
2176
|
+
e.preventDefault();
|
|
2177
|
+
const target = document.getElementById(targetId);
|
|
2178
|
+
if (target) {
|
|
2179
|
+
if (target.tabIndex === -1) {
|
|
2180
|
+
target.setAttribute("tabindex", "-1");
|
|
2181
|
+
}
|
|
2182
|
+
target.focus();
|
|
2183
|
+
target.scrollIntoView();
|
|
2184
|
+
} else if (process.env.NODE_ENV !== "production") {
|
|
2185
|
+
console.warn(
|
|
2186
|
+
`SkipLink: Target element with id="${targetId}" not found. Ensure the target element exists and has the correct id attribute.`
|
|
2187
|
+
);
|
|
2188
|
+
}
|
|
2189
|
+
props.onClick?.(e);
|
|
2190
|
+
};
|
|
2191
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2192
|
+
"a",
|
|
2193
|
+
{
|
|
2194
|
+
ref,
|
|
2195
|
+
href: `#${targetId}`,
|
|
2196
|
+
className: cn("skip-link", className),
|
|
2197
|
+
onClick: handleClick,
|
|
2198
|
+
...props,
|
|
2199
|
+
children
|
|
2200
|
+
}
|
|
2201
|
+
);
|
|
2202
|
+
}
|
|
2203
|
+
);
|
|
2204
|
+
SkipLink.displayName = "SkipLink";
|
|
2205
|
+
|
|
2206
|
+
// src/hooks/useFocusTrap.ts
|
|
2207
|
+
var import_react = require("react");
|
|
2208
|
+
var FOCUSABLE_SELECTOR = [
|
|
2209
|
+
"a[href]",
|
|
2210
|
+
"area[href]",
|
|
2211
|
+
'input:not([disabled]):not([type="hidden"])',
|
|
2212
|
+
"select:not([disabled])",
|
|
2213
|
+
"textarea:not([disabled])",
|
|
2214
|
+
"button:not([disabled])",
|
|
2215
|
+
"iframe",
|
|
2216
|
+
"object",
|
|
2217
|
+
"embed",
|
|
2218
|
+
"[contenteditable]",
|
|
2219
|
+
'[tabindex]:not([tabindex="-1"])'
|
|
2220
|
+
].join(",");
|
|
2221
|
+
function getFocusableElements(container) {
|
|
2222
|
+
const elements = container.querySelectorAll(FOCUSABLE_SELECTOR);
|
|
2223
|
+
return Array.from(elements).filter(
|
|
2224
|
+
(el) => el.offsetParent !== null && getComputedStyle(el).visibility !== "hidden"
|
|
2225
|
+
);
|
|
2226
|
+
}
|
|
2227
|
+
function useFocusTrap(options = {}) {
|
|
2228
|
+
const { active = true, returnFocusTo, initialFocus, preventScroll = false } = options;
|
|
2229
|
+
const containerRef = (0, import_react.useRef)(null);
|
|
2230
|
+
const previousActiveElementRef = (0, import_react.useRef)(null);
|
|
2231
|
+
const handleKeyDown = (0, import_react.useCallback)(
|
|
2232
|
+
(event) => {
|
|
2233
|
+
if (!active || event.key !== "Tab") return;
|
|
2234
|
+
const container = containerRef.current;
|
|
2235
|
+
if (!container) return;
|
|
2236
|
+
const focusableElements = getFocusableElements(container);
|
|
2237
|
+
if (focusableElements.length === 0) return;
|
|
2238
|
+
const firstElement = focusableElements[0];
|
|
2239
|
+
const lastElement = focusableElements[focusableElements.length - 1];
|
|
2240
|
+
if (event.shiftKey) {
|
|
2241
|
+
if (document.activeElement === firstElement) {
|
|
2242
|
+
event.preventDefault();
|
|
2243
|
+
lastElement.focus({ preventScroll });
|
|
2244
|
+
}
|
|
2245
|
+
} else {
|
|
2246
|
+
if (document.activeElement === lastElement) {
|
|
2247
|
+
event.preventDefault();
|
|
2248
|
+
firstElement.focus({ preventScroll });
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2251
|
+
},
|
|
2252
|
+
[active, preventScroll]
|
|
2253
|
+
);
|
|
2254
|
+
(0, import_react.useEffect)(() => {
|
|
2255
|
+
if (!active) return;
|
|
2256
|
+
const container = containerRef.current;
|
|
2257
|
+
if (!container) return;
|
|
2258
|
+
previousActiveElementRef.current = document.activeElement;
|
|
2259
|
+
const focusableElements = getFocusableElements(container);
|
|
2260
|
+
if (focusableElements.length > 0) {
|
|
2261
|
+
let elementToFocus = null;
|
|
2262
|
+
if (initialFocus) {
|
|
2263
|
+
elementToFocus = container.querySelector(initialFocus);
|
|
2264
|
+
}
|
|
2265
|
+
if (!elementToFocus) {
|
|
2266
|
+
elementToFocus = focusableElements[0];
|
|
2267
|
+
}
|
|
2268
|
+
requestAnimationFrame(() => {
|
|
2269
|
+
elementToFocus?.focus({ preventScroll });
|
|
2270
|
+
});
|
|
2271
|
+
}
|
|
2272
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
2273
|
+
return () => {
|
|
2274
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
2275
|
+
const elementToReturn = returnFocusTo ?? previousActiveElementRef.current;
|
|
2276
|
+
if (elementToReturn && typeof elementToReturn.focus === "function") {
|
|
2277
|
+
elementToReturn.focus({ preventScroll });
|
|
2278
|
+
}
|
|
2279
|
+
};
|
|
2280
|
+
}, [active, initialFocus, returnFocusTo, handleKeyDown, preventScroll]);
|
|
2281
|
+
return containerRef;
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
// src/hooks/useFocusRef.ts
|
|
2285
|
+
var import_react2 = require("react");
|
|
2286
|
+
function useFocusRef(options = {}) {
|
|
2287
|
+
const { focusOnMount = false, preventScroll = false, delay = 0 } = options;
|
|
2288
|
+
const ref = (0, import_react2.useRef)(null);
|
|
2289
|
+
(0, import_react2.useEffect)(() => {
|
|
2290
|
+
if (!focusOnMount) return;
|
|
2291
|
+
const focus = () => {
|
|
2292
|
+
if (ref.current && typeof ref.current.focus === "function") {
|
|
2293
|
+
ref.current.focus({ preventScroll });
|
|
2294
|
+
}
|
|
2295
|
+
};
|
|
2296
|
+
if (delay > 0) {
|
|
2297
|
+
const timer = setTimeout(focus, delay);
|
|
2298
|
+
return () => clearTimeout(timer);
|
|
2299
|
+
} else {
|
|
2300
|
+
const frame = requestAnimationFrame(focus);
|
|
2301
|
+
return () => cancelAnimationFrame(frame);
|
|
2302
|
+
}
|
|
2303
|
+
}, [focusOnMount, preventScroll, delay]);
|
|
2304
|
+
return ref;
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
// src/hooks/useReducedMotion.ts
|
|
2308
|
+
var import_react3 = require("react");
|
|
2309
|
+
function useReducedMotion() {
|
|
2310
|
+
const [reducedMotion, setReducedMotion] = (0, import_react3.useState)(false);
|
|
2311
|
+
(0, import_react3.useEffect)(() => {
|
|
2312
|
+
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
2313
|
+
setReducedMotion(mediaQuery.matches);
|
|
2314
|
+
const handleChange = (event) => {
|
|
2315
|
+
setReducedMotion(event.matches);
|
|
2316
|
+
};
|
|
2317
|
+
mediaQuery.addEventListener("change", handleChange);
|
|
2318
|
+
return () => {
|
|
2319
|
+
mediaQuery.removeEventListener("change", handleChange);
|
|
2320
|
+
};
|
|
2321
|
+
}, []);
|
|
2322
|
+
return reducedMotion;
|
|
2323
|
+
}
|
|
2324
|
+
|
|
2325
|
+
// src/hooks/useArrowNavigation.ts
|
|
2326
|
+
var import_react4 = require("react");
|
|
2327
|
+
var DEFAULT_SELECTOR = '[role="menuitem"], [role="option"], [role="tab"], button, a, [tabindex]:not([tabindex="-1"])';
|
|
2328
|
+
function useArrowNavigation(options = {}) {
|
|
2329
|
+
const {
|
|
2330
|
+
orientation = "vertical",
|
|
2331
|
+
loop = true,
|
|
2332
|
+
itemSelector = DEFAULT_SELECTOR,
|
|
2333
|
+
onFocusChange
|
|
2334
|
+
} = options;
|
|
2335
|
+
const containerRef = (0, import_react4.useRef)(null);
|
|
2336
|
+
const focusedIndexRef = (0, import_react4.useRef)(-1);
|
|
2337
|
+
const getFocusableItems = (0, import_react4.useCallback)(() => {
|
|
2338
|
+
if (!containerRef.current) return [];
|
|
2339
|
+
return Array.from(containerRef.current.querySelectorAll(itemSelector));
|
|
2340
|
+
}, [itemSelector]);
|
|
2341
|
+
const focusItem = (0, import_react4.useCallback)(
|
|
2342
|
+
(index) => {
|
|
2343
|
+
const items = getFocusableItems();
|
|
2344
|
+
if (items.length === 0) return;
|
|
2345
|
+
let targetIndex = index;
|
|
2346
|
+
if (loop) {
|
|
2347
|
+
if (targetIndex < 0) targetIndex = items.length - 1;
|
|
2348
|
+
if (targetIndex >= items.length) targetIndex = 0;
|
|
2349
|
+
} else {
|
|
2350
|
+
targetIndex = Math.max(0, Math.min(targetIndex, items.length - 1));
|
|
2351
|
+
}
|
|
2352
|
+
const element = items[targetIndex];
|
|
2353
|
+
if (element) {
|
|
2354
|
+
element.focus();
|
|
2355
|
+
focusedIndexRef.current = targetIndex;
|
|
2356
|
+
onFocusChange?.(targetIndex, element);
|
|
2357
|
+
}
|
|
2358
|
+
},
|
|
2359
|
+
[getFocusableItems, loop, onFocusChange]
|
|
2360
|
+
);
|
|
2361
|
+
const handleKeyDown = (0, import_react4.useCallback)(
|
|
2362
|
+
(event) => {
|
|
2363
|
+
const items = getFocusableItems();
|
|
2364
|
+
if (items.length === 0) return;
|
|
2365
|
+
const currentIndex = focusedIndexRef.current;
|
|
2366
|
+
let handled = false;
|
|
2367
|
+
switch (event.key) {
|
|
2368
|
+
case "ArrowUp":
|
|
2369
|
+
if (orientation === "vertical" || orientation === "both") {
|
|
2370
|
+
focusItem(currentIndex - 1);
|
|
2371
|
+
handled = true;
|
|
2372
|
+
}
|
|
2373
|
+
break;
|
|
2374
|
+
case "ArrowDown":
|
|
2375
|
+
if (orientation === "vertical" || orientation === "both") {
|
|
2376
|
+
focusItem(currentIndex + 1);
|
|
2377
|
+
handled = true;
|
|
2378
|
+
}
|
|
2379
|
+
break;
|
|
2380
|
+
case "ArrowLeft":
|
|
2381
|
+
if (orientation === "horizontal" || orientation === "both") {
|
|
2382
|
+
focusItem(currentIndex - 1);
|
|
2383
|
+
handled = true;
|
|
2384
|
+
}
|
|
2385
|
+
break;
|
|
2386
|
+
case "ArrowRight":
|
|
2387
|
+
if (orientation === "horizontal" || orientation === "both") {
|
|
2388
|
+
focusItem(currentIndex + 1);
|
|
2389
|
+
handled = true;
|
|
2390
|
+
}
|
|
2391
|
+
break;
|
|
2392
|
+
case "Home":
|
|
2393
|
+
focusItem(0);
|
|
2394
|
+
handled = true;
|
|
2395
|
+
break;
|
|
2396
|
+
case "End":
|
|
2397
|
+
focusItem(items.length - 1);
|
|
2398
|
+
handled = true;
|
|
2399
|
+
break;
|
|
2400
|
+
}
|
|
2401
|
+
if (handled) {
|
|
2402
|
+
event.preventDefault();
|
|
2403
|
+
event.stopPropagation();
|
|
2404
|
+
}
|
|
2405
|
+
},
|
|
2406
|
+
[orientation, focusItem, getFocusableItems]
|
|
2407
|
+
);
|
|
2408
|
+
const handleFocus = (0, import_react4.useCallback)(
|
|
2409
|
+
(event) => {
|
|
2410
|
+
const items = getFocusableItems();
|
|
2411
|
+
const index = items.indexOf(event.target);
|
|
2412
|
+
if (index !== -1) {
|
|
2413
|
+
focusedIndexRef.current = index;
|
|
2414
|
+
}
|
|
2415
|
+
},
|
|
2416
|
+
[getFocusableItems]
|
|
2417
|
+
);
|
|
2418
|
+
const containerProps = {
|
|
2419
|
+
ref: (node) => {
|
|
2420
|
+
containerRef.current = node;
|
|
2421
|
+
},
|
|
2422
|
+
onKeyDown: handleKeyDown,
|
|
2423
|
+
onFocus: handleFocus
|
|
2424
|
+
};
|
|
2425
|
+
const getItemProps = (0, import_react4.useCallback)(
|
|
2426
|
+
(index) => ({
|
|
2427
|
+
tabIndex: index === 0 ? 0 : -1,
|
|
2428
|
+
onFocus: () => {
|
|
2429
|
+
focusedIndexRef.current = index;
|
|
2430
|
+
}
|
|
2431
|
+
}),
|
|
2432
|
+
[]
|
|
2433
|
+
);
|
|
2434
|
+
return {
|
|
2435
|
+
containerProps,
|
|
2436
|
+
getItemProps,
|
|
2437
|
+
focusItem,
|
|
2438
|
+
getFocusedIndex: () => focusedIndexRef.current
|
|
2439
|
+
};
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
// src/hooks/useRovingTabindex.ts
|
|
2443
|
+
var import_react5 = require("react");
|
|
2444
|
+
var DEFAULT_SELECTOR2 = "[data-roving-tabindex-item]";
|
|
2445
|
+
function useRovingTabindex(options = {}) {
|
|
2446
|
+
const { loop = true, itemSelector = DEFAULT_SELECTOR2, initialIndex = 0, onIndexChange } = options;
|
|
2447
|
+
const [activeIndex, setActiveIndex] = (0, import_react5.useState)(initialIndex);
|
|
2448
|
+
const containerRef = (0, import_react5.useRef)(null);
|
|
2449
|
+
const itemsRef = (0, import_react5.useRef)(/* @__PURE__ */ new Map());
|
|
2450
|
+
const getItems = (0, import_react5.useCallback)(() => {
|
|
2451
|
+
if (!containerRef.current) {
|
|
2452
|
+
return Array.from(itemsRef.current.values());
|
|
2453
|
+
}
|
|
2454
|
+
return Array.from(containerRef.current.querySelectorAll(itemSelector));
|
|
2455
|
+
}, [itemSelector]);
|
|
2456
|
+
const focusIndex = (0, import_react5.useCallback)(
|
|
2457
|
+
(index) => {
|
|
2458
|
+
const items = getItems();
|
|
2459
|
+
if (items.length === 0) return;
|
|
2460
|
+
let targetIndex = index;
|
|
2461
|
+
if (loop) {
|
|
2462
|
+
if (targetIndex < 0) targetIndex = items.length - 1;
|
|
2463
|
+
if (targetIndex >= items.length) targetIndex = 0;
|
|
2464
|
+
} else {
|
|
2465
|
+
targetIndex = Math.max(0, Math.min(targetIndex, items.length - 1));
|
|
2466
|
+
}
|
|
2467
|
+
setActiveIndex(targetIndex);
|
|
2468
|
+
onIndexChange?.(targetIndex);
|
|
2469
|
+
const element = items[targetIndex];
|
|
2470
|
+
if (element) {
|
|
2471
|
+
element.focus();
|
|
2472
|
+
}
|
|
2473
|
+
},
|
|
2474
|
+
[getItems, loop, onIndexChange]
|
|
2475
|
+
);
|
|
2476
|
+
const handleKeyDown = (0, import_react5.useCallback)(
|
|
2477
|
+
(event) => {
|
|
2478
|
+
const items = getItems();
|
|
2479
|
+
if (items.length === 0) return;
|
|
2480
|
+
let handled = false;
|
|
2481
|
+
switch (event.key) {
|
|
2482
|
+
case "ArrowUp":
|
|
2483
|
+
case "ArrowLeft":
|
|
2484
|
+
focusIndex(activeIndex - 1);
|
|
2485
|
+
handled = true;
|
|
2486
|
+
break;
|
|
2487
|
+
case "ArrowDown":
|
|
2488
|
+
case "ArrowRight":
|
|
2489
|
+
focusIndex(activeIndex + 1);
|
|
2490
|
+
handled = true;
|
|
2491
|
+
break;
|
|
2492
|
+
case "Home":
|
|
2493
|
+
focusIndex(0);
|
|
2494
|
+
handled = true;
|
|
2495
|
+
break;
|
|
2496
|
+
case "End":
|
|
2497
|
+
focusIndex(items.length - 1);
|
|
2498
|
+
handled = true;
|
|
2499
|
+
break;
|
|
2500
|
+
}
|
|
2501
|
+
if (handled) {
|
|
2502
|
+
event.preventDefault();
|
|
2503
|
+
event.stopPropagation();
|
|
2504
|
+
}
|
|
2505
|
+
},
|
|
2506
|
+
[activeIndex, focusIndex, getItems]
|
|
2507
|
+
);
|
|
2508
|
+
const containerProps = {
|
|
2509
|
+
ref: (node) => {
|
|
2510
|
+
containerRef.current = node;
|
|
2511
|
+
},
|
|
2512
|
+
onKeyDown: handleKeyDown
|
|
2513
|
+
};
|
|
2514
|
+
const getItemProps = (0, import_react5.useCallback)(
|
|
2515
|
+
(index) => ({
|
|
2516
|
+
"data-roving-tabindex-item": true,
|
|
2517
|
+
tabIndex: index === activeIndex ? 0 : -1,
|
|
2518
|
+
ref: (node) => {
|
|
2519
|
+
if (node) {
|
|
2520
|
+
itemsRef.current.set(index, node);
|
|
2521
|
+
} else {
|
|
2522
|
+
itemsRef.current.delete(index);
|
|
2523
|
+
}
|
|
2524
|
+
},
|
|
2525
|
+
onClick: () => {
|
|
2526
|
+
setActiveIndex(index);
|
|
2527
|
+
onIndexChange?.(index);
|
|
2528
|
+
},
|
|
2529
|
+
onFocus: () => {
|
|
2530
|
+
if (activeIndex !== index) {
|
|
2531
|
+
setActiveIndex(index);
|
|
2532
|
+
onIndexChange?.(index);
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
}),
|
|
2536
|
+
[activeIndex, onIndexChange]
|
|
2537
|
+
);
|
|
2538
|
+
return {
|
|
2539
|
+
containerProps,
|
|
2540
|
+
getItemProps,
|
|
2541
|
+
activeIndex,
|
|
2542
|
+
setActiveIndex: focusIndex,
|
|
2543
|
+
focusNext: () => focusIndex(activeIndex + 1),
|
|
2544
|
+
focusPrevious: () => focusIndex(activeIndex - 1),
|
|
2545
|
+
focusFirst: () => focusIndex(0),
|
|
2546
|
+
focusLast: () => focusIndex(getItems().length - 1)
|
|
2547
|
+
};
|
|
2548
|
+
}
|
|
2549
|
+
|
|
2550
|
+
// src/hooks/useEscapeKey.ts
|
|
2551
|
+
var React23 = __toESM(require("react"));
|
|
2552
|
+
function useEscapeKey(callback, options) {
|
|
2553
|
+
const { enabled = true, preventDefault = true, stopPropagation = false } = options ?? {};
|
|
2554
|
+
const callbackRef = React23.useRef(callback);
|
|
2555
|
+
React23.useEffect(() => {
|
|
2556
|
+
callbackRef.current = callback;
|
|
2557
|
+
}, [callback]);
|
|
2558
|
+
React23.useEffect(() => {
|
|
2559
|
+
if (!enabled) return;
|
|
2560
|
+
const handleKeyDown = (event) => {
|
|
2561
|
+
if (event.key === "Escape") {
|
|
2562
|
+
if (preventDefault) {
|
|
2563
|
+
event.preventDefault();
|
|
2564
|
+
}
|
|
2565
|
+
if (stopPropagation) {
|
|
2566
|
+
event.stopPropagation();
|
|
2567
|
+
}
|
|
2568
|
+
callbackRef.current(event);
|
|
2569
|
+
}
|
|
2570
|
+
};
|
|
2571
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
2572
|
+
return () => {
|
|
2573
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
2574
|
+
};
|
|
2575
|
+
}, [enabled, preventDefault, stopPropagation]);
|
|
2576
|
+
}
|
|
2577
|
+
|
|
2578
|
+
// src/hooks/useClickOutside.ts
|
|
2579
|
+
var React24 = __toESM(require("react"));
|
|
2580
|
+
function useClickOutside(ref, callback, options) {
|
|
2581
|
+
const {
|
|
2582
|
+
enabled = true,
|
|
2583
|
+
events = ["mousedown", "touchstart"],
|
|
2584
|
+
ignoreElements = []
|
|
2585
|
+
} = options ?? {};
|
|
2586
|
+
const callbackRef = React24.useRef(callback);
|
|
2587
|
+
React24.useEffect(() => {
|
|
2588
|
+
callbackRef.current = callback;
|
|
2589
|
+
}, [callback]);
|
|
2590
|
+
React24.useEffect(() => {
|
|
2591
|
+
if (!enabled) return;
|
|
2592
|
+
const handleEvent = (event) => {
|
|
2593
|
+
const target = event.target;
|
|
2594
|
+
if (ref.current?.contains(target)) {
|
|
2595
|
+
return;
|
|
2596
|
+
}
|
|
2597
|
+
for (const ignoreRef of ignoreElements) {
|
|
2598
|
+
if (ignoreRef.current?.contains(target)) {
|
|
2599
|
+
return;
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
callbackRef.current(event);
|
|
2603
|
+
};
|
|
2604
|
+
events.forEach((eventType) => {
|
|
2605
|
+
document.addEventListener(eventType, handleEvent);
|
|
2606
|
+
});
|
|
2607
|
+
return () => {
|
|
2608
|
+
events.forEach((eventType) => {
|
|
2609
|
+
document.removeEventListener(eventType, handleEvent);
|
|
2610
|
+
});
|
|
2611
|
+
};
|
|
2612
|
+
}, [enabled, events, ignoreElements, ref]);
|
|
2613
|
+
}
|
|
1400
2614
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1401
2615
|
0 && (module.exports = {
|
|
1402
2616
|
Avatar,
|
|
@@ -1427,9 +2641,18 @@ DataPanel.displayName = "DataPanel";
|
|
|
1427
2641
|
DialogTrigger,
|
|
1428
2642
|
Input,
|
|
1429
2643
|
Label,
|
|
2644
|
+
LiveRegion,
|
|
2645
|
+
LoadingLogo,
|
|
2646
|
+
LoadingOverlay,
|
|
2647
|
+
LoadingPage,
|
|
2648
|
+
LoadingSection,
|
|
1430
2649
|
PageHeader,
|
|
1431
2650
|
PasswordInput,
|
|
2651
|
+
ProgressBar,
|
|
1432
2652
|
Separator,
|
|
2653
|
+
Skeleton,
|
|
2654
|
+
SkipLink,
|
|
2655
|
+
Spinner,
|
|
1433
2656
|
Switch,
|
|
1434
2657
|
badgeVariants,
|
|
1435
2658
|
buttonVariants,
|
|
@@ -1438,5 +2661,16 @@ DataPanel.displayName = "DataPanel";
|
|
|
1438
2661
|
pageHeaderContainerVariants,
|
|
1439
2662
|
pageHeaderSubtitleVariants,
|
|
1440
2663
|
pageHeaderTitleVariants,
|
|
1441
|
-
|
|
2664
|
+
progressBarVariants,
|
|
2665
|
+
skeletonVariants,
|
|
2666
|
+
spinnerVariants,
|
|
2667
|
+
useAnnounce,
|
|
2668
|
+
useArrowNavigation,
|
|
2669
|
+
useClickOutside,
|
|
2670
|
+
useDataPanel,
|
|
2671
|
+
useEscapeKey,
|
|
2672
|
+
useFocusRef,
|
|
2673
|
+
useFocusTrap,
|
|
2674
|
+
useReducedMotion,
|
|
2675
|
+
useRovingTabindex
|
|
1442
2676
|
});
|