@kjaniec-dev/ui 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.cjs +3825 -180
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +666 -3
- package/dist/index.d.ts +666 -3
- package/dist/index.js +3765 -180
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
'use strict';
|
|
2
3
|
|
|
3
4
|
var clsx = require('clsx');
|
|
4
5
|
var tailwindMerge = require('tailwind-merge');
|
|
5
|
-
var
|
|
6
|
+
var React52 = require('react');
|
|
6
7
|
var classVarianceAuthority = require('class-variance-authority');
|
|
7
8
|
var jsxRuntime = require('react/jsx-runtime');
|
|
8
9
|
|
|
@@ -24,7 +25,7 @@ function _interopNamespace(e) {
|
|
|
24
25
|
return Object.freeze(n);
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
var
|
|
28
|
+
var React52__namespace = /*#__PURE__*/_interopNamespace(React52);
|
|
28
29
|
|
|
29
30
|
// src/lib/cn.ts
|
|
30
31
|
function cn(...inputs) {
|
|
@@ -60,7 +61,7 @@ var buttonVariants = classVarianceAuthority.cva(
|
|
|
60
61
|
defaultVariants: { variant: "primary", size: "md" }
|
|
61
62
|
}
|
|
62
63
|
);
|
|
63
|
-
var Button =
|
|
64
|
+
var Button = React52__namespace.forwardRef(
|
|
64
65
|
({ className, variant, size, loading, leadingIcon, trailingIcon, children, disabled, ...props }, ref) => {
|
|
65
66
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
66
67
|
"button",
|
|
@@ -107,7 +108,7 @@ var badgeVariants = classVarianceAuthority.cva(
|
|
|
107
108
|
defaultVariants: { variant: "neutral" }
|
|
108
109
|
}
|
|
109
110
|
);
|
|
110
|
-
var Badge =
|
|
111
|
+
var Badge = React52__namespace.forwardRef(
|
|
111
112
|
({ className, variant, dot, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs("span", { ref, className: cn(badgeVariants({ variant }), className), ...props, children: [
|
|
112
113
|
dot && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-current", "aria-hidden": true }),
|
|
113
114
|
children
|
|
@@ -134,7 +135,7 @@ var iconColor = {
|
|
|
134
135
|
warning: "text-warning",
|
|
135
136
|
danger: "text-danger"
|
|
136
137
|
};
|
|
137
|
-
var Alert =
|
|
138
|
+
var Alert = React52__namespace.forwardRef(
|
|
138
139
|
({ className, variant = "info", icon, title, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, role: "alert", className: cn(alertVariants({ variant }), className), ...props, children: [
|
|
139
140
|
icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("shrink-0 mt-0.5 [&_svg]:h-[1.15rem] [&_svg]:w-[1.15rem]", iconColor[variant ?? "info"]), children: icon }),
|
|
140
141
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-foreground", children: [
|
|
@@ -144,7 +145,7 @@ var Alert = React18__namespace.forwardRef(
|
|
|
144
145
|
] })
|
|
145
146
|
);
|
|
146
147
|
Alert.displayName = "Alert";
|
|
147
|
-
var Spinner =
|
|
148
|
+
var Spinner = React52__namespace.forwardRef(
|
|
148
149
|
({ className, size = 24, style, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
149
150
|
"span",
|
|
150
151
|
{
|
|
@@ -161,7 +162,7 @@ var Spinner = React18__namespace.forwardRef(
|
|
|
161
162
|
)
|
|
162
163
|
);
|
|
163
164
|
Spinner.displayName = "Spinner";
|
|
164
|
-
var Progress =
|
|
165
|
+
var Progress = React52__namespace.forwardRef(
|
|
165
166
|
({ className, value = 0, tone = "primary", barClassName, ...props }, ref) => {
|
|
166
167
|
const pct = Math.max(0, Math.min(100, value));
|
|
167
168
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -191,14 +192,14 @@ var Progress = React18__namespace.forwardRef(
|
|
|
191
192
|
}
|
|
192
193
|
);
|
|
193
194
|
Progress.displayName = "Progress";
|
|
194
|
-
var Label =
|
|
195
|
+
var Label = React52__namespace.forwardRef(
|
|
195
196
|
({ className, required, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs("label", { ref, className: cn("text-[0.8rem] font-semibold text-foreground", className), ...props, children: [
|
|
196
197
|
children,
|
|
197
198
|
required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-danger", children: " *" })
|
|
198
199
|
] })
|
|
199
200
|
);
|
|
200
201
|
Label.displayName = "Label";
|
|
201
|
-
var Hint =
|
|
202
|
+
var Hint = React52__namespace.forwardRef(
|
|
202
203
|
({ className, error, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
203
204
|
"span",
|
|
204
205
|
{
|
|
@@ -209,17 +210,17 @@ var Hint = React18__namespace.forwardRef(
|
|
|
209
210
|
)
|
|
210
211
|
);
|
|
211
212
|
Hint.displayName = "Hint";
|
|
212
|
-
var Field =
|
|
213
|
+
var Field = React52__namespace.forwardRef(
|
|
213
214
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex flex-col gap-1.5", className), ...props })
|
|
214
215
|
);
|
|
215
216
|
Field.displayName = "Field";
|
|
216
|
-
var FormField =
|
|
217
|
+
var FormField = React52__namespace.forwardRef(
|
|
217
218
|
({ className, label, hint, error, required, children, ...props }, ref) => {
|
|
218
|
-
const id =
|
|
219
|
+
const id = React52__namespace.useId();
|
|
219
220
|
const hintId = `${id}-hint`;
|
|
220
221
|
const errorId = `${id}-error`;
|
|
221
|
-
const child =
|
|
222
|
-
const clonedChild =
|
|
222
|
+
const child = React52__namespace.Children.only(children);
|
|
223
|
+
const clonedChild = React52__namespace.cloneElement(child, {
|
|
223
224
|
id: child.props.id ?? id,
|
|
224
225
|
"aria-describedby": cn(
|
|
225
226
|
hint && hintId,
|
|
@@ -238,9 +239,136 @@ var FormField = React18__namespace.forwardRef(
|
|
|
238
239
|
}
|
|
239
240
|
);
|
|
240
241
|
FormField.displayName = "FormField";
|
|
242
|
+
var sizeDimensions = {
|
|
243
|
+
sm: 36,
|
|
244
|
+
md: 64,
|
|
245
|
+
lg: 96,
|
|
246
|
+
xl: 128
|
|
247
|
+
};
|
|
248
|
+
var defaultStrokeWidths = {
|
|
249
|
+
sm: 3.5,
|
|
250
|
+
md: 6,
|
|
251
|
+
lg: 8,
|
|
252
|
+
xl: 10
|
|
253
|
+
};
|
|
254
|
+
var textSizeClasses = {
|
|
255
|
+
sm: "text-[0.65rem] font-semibold leading-none",
|
|
256
|
+
md: "text-xs font-semibold leading-none",
|
|
257
|
+
lg: "text-base font-bold leading-none",
|
|
258
|
+
xl: "text-xl font-bold leading-none"
|
|
259
|
+
};
|
|
260
|
+
var toneClasses = {
|
|
261
|
+
primary: "text-primary stroke-current",
|
|
262
|
+
secondary: "text-secondary stroke-current",
|
|
263
|
+
success: "text-success stroke-current",
|
|
264
|
+
warning: "text-warning stroke-current",
|
|
265
|
+
danger: "text-danger stroke-current",
|
|
266
|
+
info: "text-info stroke-current"
|
|
267
|
+
};
|
|
268
|
+
var ProgressRing = React52__namespace.forwardRef(
|
|
269
|
+
({
|
|
270
|
+
className,
|
|
271
|
+
style,
|
|
272
|
+
value = 0,
|
|
273
|
+
min = 0,
|
|
274
|
+
max = 100,
|
|
275
|
+
size = "md",
|
|
276
|
+
strokeWidth,
|
|
277
|
+
tone = "primary",
|
|
278
|
+
showValue = false,
|
|
279
|
+
formatValue,
|
|
280
|
+
trackClassName,
|
|
281
|
+
indicatorClassName,
|
|
282
|
+
children,
|
|
283
|
+
"aria-label": ariaLabel,
|
|
284
|
+
...props
|
|
285
|
+
}, ref) => {
|
|
286
|
+
const range2 = max > min ? max - min : 100;
|
|
287
|
+
const clampedValue = Math.max(min, Math.min(max, value));
|
|
288
|
+
const percentage = Math.max(0, Math.min(100, (clampedValue - min) / range2 * 100));
|
|
289
|
+
const dimension = sizeDimensions[size];
|
|
290
|
+
const strokeWidthVal = strokeWidth ?? defaultStrokeWidths[size];
|
|
291
|
+
const radius = Math.max(0, (dimension - strokeWidthVal) / 2);
|
|
292
|
+
const circumference = 2 * Math.PI * radius;
|
|
293
|
+
const strokeDashoffset = circumference - percentage / 100 * circumference;
|
|
294
|
+
const computedAriaLabel = ariaLabel ?? (props["aria-labelledby"] ? void 0 : "Progress");
|
|
295
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
296
|
+
"div",
|
|
297
|
+
{
|
|
298
|
+
ref,
|
|
299
|
+
role: "progressbar",
|
|
300
|
+
"aria-label": computedAriaLabel,
|
|
301
|
+
"aria-valuenow": clampedValue,
|
|
302
|
+
"aria-valuemin": min,
|
|
303
|
+
"aria-valuemax": max,
|
|
304
|
+
className: cn("relative inline-flex items-center justify-center shrink-0", className),
|
|
305
|
+
style: { width: dimension, height: dimension, ...style },
|
|
306
|
+
...props,
|
|
307
|
+
children: [
|
|
308
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
309
|
+
"svg",
|
|
310
|
+
{
|
|
311
|
+
width: dimension,
|
|
312
|
+
height: dimension,
|
|
313
|
+
viewBox: `0 0 ${dimension} ${dimension}`,
|
|
314
|
+
className: "-rotate-90 transform",
|
|
315
|
+
children: [
|
|
316
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
317
|
+
"circle",
|
|
318
|
+
{
|
|
319
|
+
cx: dimension / 2,
|
|
320
|
+
cy: dimension / 2,
|
|
321
|
+
r: radius,
|
|
322
|
+
strokeWidth: strokeWidthVal,
|
|
323
|
+
className: cn("stroke-muted/30 fill-none", trackClassName)
|
|
324
|
+
}
|
|
325
|
+
),
|
|
326
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
327
|
+
"circle",
|
|
328
|
+
{
|
|
329
|
+
cx: dimension / 2,
|
|
330
|
+
cy: dimension / 2,
|
|
331
|
+
r: radius,
|
|
332
|
+
strokeWidth: strokeWidthVal,
|
|
333
|
+
strokeDasharray: circumference,
|
|
334
|
+
strokeDashoffset,
|
|
335
|
+
strokeLinecap: percentage === 0 ? "butt" : "round",
|
|
336
|
+
className: cn(
|
|
337
|
+
"fill-none transition-[stroke-dashoffset,opacity] duration-500 ease-in-out",
|
|
338
|
+
percentage === 0 && "opacity-0",
|
|
339
|
+
toneClasses[tone],
|
|
340
|
+
indicatorClassName
|
|
341
|
+
)
|
|
342
|
+
}
|
|
343
|
+
)
|
|
344
|
+
]
|
|
345
|
+
}
|
|
346
|
+
),
|
|
347
|
+
(children || showValue) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
348
|
+
"div",
|
|
349
|
+
{
|
|
350
|
+
className: cn(
|
|
351
|
+
"absolute inset-0 flex flex-col items-center justify-center text-center text-foreground p-1",
|
|
352
|
+
textSizeClasses[size]
|
|
353
|
+
),
|
|
354
|
+
children: children ?? (formatValue ? formatValue(clampedValue, Math.round(percentage)) : `${Math.round(percentage)}%`)
|
|
355
|
+
}
|
|
356
|
+
)
|
|
357
|
+
]
|
|
358
|
+
}
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
);
|
|
362
|
+
ProgressRing.displayName = "ProgressRing";
|
|
363
|
+
var ProgressRingField = React52__namespace.forwardRef(
|
|
364
|
+
({ label, hint, error, required, fieldClassName, ...ringProps }, ref) => {
|
|
365
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FormField, { label, hint, error, required, className: fieldClassName, children: /* @__PURE__ */ jsxRuntime.jsx(ProgressRing, { ref, "aria-label": ringProps["aria-label"] ?? label, ...ringProps }) });
|
|
366
|
+
}
|
|
367
|
+
);
|
|
368
|
+
ProgressRingField.displayName = "ProgressRingField";
|
|
241
369
|
var baseField = "w-full font-sans text-sm text-foreground bg-surface border rounded-kj-md px-[0.85rem] transition-[border-color,box-shadow] duration-150 placeholder:text-muted-foreground focus:outline-none focus:border-ring focus:ring-[3px] focus:ring-ring/30 disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed";
|
|
242
|
-
var Input =
|
|
243
|
-
({ className, error, leadingIcon,
|
|
370
|
+
var Input = React52__namespace.forwardRef(
|
|
371
|
+
({ className, error, leadingIcon, ...props }, ref) => {
|
|
244
372
|
const field = /* @__PURE__ */ jsxRuntime.jsx(
|
|
245
373
|
"input",
|
|
246
374
|
{
|
|
@@ -264,7 +392,7 @@ var Input = React18__namespace.forwardRef(
|
|
|
264
392
|
}
|
|
265
393
|
);
|
|
266
394
|
Input.displayName = "Input";
|
|
267
|
-
var Textarea =
|
|
395
|
+
var Textarea = React52__namespace.forwardRef(
|
|
268
396
|
({ className, error, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
269
397
|
"textarea",
|
|
270
398
|
{
|
|
@@ -281,14 +409,14 @@ var Textarea = React18__namespace.forwardRef(
|
|
|
281
409
|
)
|
|
282
410
|
);
|
|
283
411
|
Textarea.displayName = "Textarea";
|
|
284
|
-
var TextField =
|
|
412
|
+
var TextField = React52__namespace.forwardRef(
|
|
285
413
|
({ label, hint, error, required, className, ...props }, ref) => {
|
|
286
414
|
return /* @__PURE__ */ jsxRuntime.jsx(FormField, { label, hint, error, required, className, children: /* @__PURE__ */ jsxRuntime.jsx(Input, { ref, error: !!error, ...props }) });
|
|
287
415
|
}
|
|
288
416
|
);
|
|
289
417
|
TextField.displayName = "TextField";
|
|
290
418
|
var chevron = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2371717a' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E";
|
|
291
|
-
var Select =
|
|
419
|
+
var Select = React52__namespace.forwardRef(
|
|
292
420
|
({ className, error, style, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
293
421
|
"select",
|
|
294
422
|
{
|
|
@@ -316,15 +444,15 @@ var Select = React18__namespace.forwardRef(
|
|
|
316
444
|
)
|
|
317
445
|
);
|
|
318
446
|
Select.displayName = "Select";
|
|
319
|
-
var SelectField =
|
|
447
|
+
var SelectField = React52__namespace.forwardRef(
|
|
320
448
|
({ label, hint, error, required, className, children, ...props }, ref) => {
|
|
321
449
|
return /* @__PURE__ */ jsxRuntime.jsx(FormField, { label, hint, error, required, className, children: /* @__PURE__ */ jsxRuntime.jsx(Select, { ref, error: !!error, ...props, children }) });
|
|
322
450
|
}
|
|
323
451
|
);
|
|
324
452
|
SelectField.displayName = "SelectField";
|
|
325
|
-
var Checkbox =
|
|
453
|
+
var Checkbox = React52__namespace.forwardRef(
|
|
326
454
|
({ className, label, id, ...props }, ref) => {
|
|
327
|
-
const autoId =
|
|
455
|
+
const autoId = React52__namespace.useId();
|
|
328
456
|
const inputId = id ?? autoId;
|
|
329
457
|
return /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: inputId, className: cn("inline-flex items-center gap-2.5 cursor-pointer text-sm select-none", className), children: [
|
|
330
458
|
/* @__PURE__ */ jsxRuntime.jsx("input", { ref, id: inputId, type: "checkbox", className: "peer sr-only", ...props }),
|
|
@@ -334,9 +462,9 @@ var Checkbox = React18__namespace.forwardRef(
|
|
|
334
462
|
}
|
|
335
463
|
);
|
|
336
464
|
Checkbox.displayName = "Checkbox";
|
|
337
|
-
var Radio =
|
|
465
|
+
var Radio = React52__namespace.forwardRef(
|
|
338
466
|
({ className, label, id, ...props }, ref) => {
|
|
339
|
-
const autoId =
|
|
467
|
+
const autoId = React52__namespace.useId();
|
|
340
468
|
const inputId = id ?? autoId;
|
|
341
469
|
return /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: inputId, className: cn("inline-flex items-center gap-2.5 cursor-pointer text-sm select-none", className), children: [
|
|
342
470
|
/* @__PURE__ */ jsxRuntime.jsx("input", { ref, id: inputId, type: "radio", className: "peer sr-only", ...props }),
|
|
@@ -346,9 +474,9 @@ var Radio = React18__namespace.forwardRef(
|
|
|
346
474
|
}
|
|
347
475
|
);
|
|
348
476
|
Radio.displayName = "Radio";
|
|
349
|
-
var CheckboxField =
|
|
477
|
+
var CheckboxField = React52__namespace.forwardRef(
|
|
350
478
|
({ label, hint, error, className, ...props }, ref) => {
|
|
351
|
-
const id =
|
|
479
|
+
const id = React52__namespace.useId();
|
|
352
480
|
const hintId = `${id}-hint`;
|
|
353
481
|
const errorId = `${id}-error`;
|
|
354
482
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-1 w-full", className), children: [
|
|
@@ -369,9 +497,9 @@ var CheckboxField = React18__namespace.forwardRef(
|
|
|
369
497
|
}
|
|
370
498
|
);
|
|
371
499
|
CheckboxField.displayName = "CheckboxField";
|
|
372
|
-
var Switch =
|
|
500
|
+
var Switch = React52__namespace.forwardRef(
|
|
373
501
|
({ className, label, id, ...props }, ref) => {
|
|
374
|
-
const autoId =
|
|
502
|
+
const autoId = React52__namespace.useId();
|
|
375
503
|
const inputId = id ?? autoId;
|
|
376
504
|
return /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: inputId, className: cn("inline-flex items-center gap-2.5 cursor-pointer text-sm select-none", className), children: [
|
|
377
505
|
/* @__PURE__ */ jsxRuntime.jsx("input", { ref, id: inputId, type: "checkbox", role: "switch", className: "peer sr-only", ...props }),
|
|
@@ -381,19 +509,47 @@ var Switch = React18__namespace.forwardRef(
|
|
|
381
509
|
}
|
|
382
510
|
);
|
|
383
511
|
Switch.displayName = "Switch";
|
|
384
|
-
var Slider =
|
|
385
|
-
({ className, ...props }, ref) =>
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
512
|
+
var Slider = React52__namespace.forwardRef(
|
|
513
|
+
({ className, style, value, defaultValue, min = 0, max = 100, onChange, ...props }, ref) => {
|
|
514
|
+
const [localValue, setLocalValue] = React52__namespace.useState(
|
|
515
|
+
Number(defaultValue ?? value ?? 50)
|
|
516
|
+
);
|
|
517
|
+
const isControlled = value !== void 0;
|
|
518
|
+
const currentVal = isControlled ? Number(value) : localValue;
|
|
519
|
+
const numMin = Number(min);
|
|
520
|
+
const numMax = Number(max);
|
|
521
|
+
const percentage = Math.min(
|
|
522
|
+
100,
|
|
523
|
+
Math.max(0, (currentVal - numMin) / (numMax - numMin) * 100)
|
|
524
|
+
);
|
|
525
|
+
const handleChange = (e) => {
|
|
526
|
+
if (!isControlled) {
|
|
527
|
+
setLocalValue(Number(e.target.value));
|
|
528
|
+
}
|
|
529
|
+
onChange?.(e);
|
|
530
|
+
};
|
|
531
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
532
|
+
"input",
|
|
533
|
+
{
|
|
534
|
+
ref,
|
|
535
|
+
type: "range",
|
|
536
|
+
value,
|
|
537
|
+
defaultValue,
|
|
538
|
+
min,
|
|
539
|
+
max,
|
|
540
|
+
onChange: handleChange,
|
|
541
|
+
style: {
|
|
542
|
+
background: `linear-gradient(to right, var(--kj-primary) ${percentage}%, var(--kj-border, rgba(120, 120, 128, 0.2)) ${percentage}%)`,
|
|
543
|
+
...style
|
|
544
|
+
},
|
|
545
|
+
className: cn(
|
|
546
|
+
"kj-slider w-full h-1.5 rounded-full appearance-none cursor-pointer accent-primary",
|
|
547
|
+
className
|
|
548
|
+
),
|
|
549
|
+
...props
|
|
550
|
+
}
|
|
551
|
+
);
|
|
552
|
+
}
|
|
397
553
|
);
|
|
398
554
|
Slider.displayName = "Slider";
|
|
399
555
|
var sliderThumbCSS = `
|
|
@@ -434,7 +590,47 @@ function Segmented({
|
|
|
434
590
|
}
|
|
435
591
|
);
|
|
436
592
|
}
|
|
437
|
-
|
|
593
|
+
function ToggleGroup({
|
|
594
|
+
options,
|
|
595
|
+
value,
|
|
596
|
+
onChange,
|
|
597
|
+
disabled,
|
|
598
|
+
className,
|
|
599
|
+
...props
|
|
600
|
+
}) {
|
|
601
|
+
const toggle = (optionValue) => {
|
|
602
|
+
if (disabled) return;
|
|
603
|
+
const next = value.includes(optionValue) ? value.filter((v) => v !== optionValue) : [...value, optionValue];
|
|
604
|
+
onChange(next);
|
|
605
|
+
};
|
|
606
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
607
|
+
"div",
|
|
608
|
+
{
|
|
609
|
+
role: "group",
|
|
610
|
+
className: cn("inline-flex gap-0.5 p-[3px] rounded-kj-md bg-muted", className),
|
|
611
|
+
...props,
|
|
612
|
+
children: options.map((opt) => {
|
|
613
|
+
const active = value.includes(opt.value);
|
|
614
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
615
|
+
"button",
|
|
616
|
+
{
|
|
617
|
+
type: "button",
|
|
618
|
+
"aria-pressed": active,
|
|
619
|
+
disabled,
|
|
620
|
+
onClick: () => toggle(opt.value),
|
|
621
|
+
className: cn(
|
|
622
|
+
"px-3.5 py-1.5 text-[0.82rem] font-semibold rounded-[calc(var(--kj-radius-md)-3px)] cursor-pointer transition-all duration-150 disabled:cursor-not-allowed disabled:opacity-50",
|
|
623
|
+
active ? "bg-surface text-foreground shadow-kj-xs" : "bg-transparent text-muted-foreground hover:text-foreground"
|
|
624
|
+
),
|
|
625
|
+
children: opt.label
|
|
626
|
+
},
|
|
627
|
+
opt.value
|
|
628
|
+
);
|
|
629
|
+
})
|
|
630
|
+
}
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
var Card = React52__namespace.forwardRef(
|
|
438
634
|
({ as: Tag = "div", className, elevated, interactive, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
439
635
|
Tag,
|
|
440
636
|
{
|
|
@@ -450,23 +646,23 @@ var Card = React18__namespace.forwardRef(
|
|
|
450
646
|
)
|
|
451
647
|
);
|
|
452
648
|
Card.displayName = "Card";
|
|
453
|
-
var CardHeader =
|
|
649
|
+
var CardHeader = React52__namespace.forwardRef(
|
|
454
650
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("p-[1.35rem] flex flex-col gap-1", className), ...props })
|
|
455
651
|
);
|
|
456
652
|
CardHeader.displayName = "CardHeader";
|
|
457
|
-
var CardTitle =
|
|
458
|
-
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("h3", { ref, className: cn("m-0 text-base font-bold tracking-[-0.01em]", className), ...props })
|
|
653
|
+
var CardTitle = React52__namespace.forwardRef(
|
|
654
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("h3", { ref, className: cn("m-0 text-base font-bold tracking-[-0.01em]", className), ...props, children })
|
|
459
655
|
);
|
|
460
656
|
CardTitle.displayName = "CardTitle";
|
|
461
|
-
var CardDescription =
|
|
657
|
+
var CardDescription = React52__namespace.forwardRef(
|
|
462
658
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("p", { ref, className: cn("m-0 text-[0.85rem] text-muted-foreground", className), ...props })
|
|
463
659
|
);
|
|
464
660
|
CardDescription.displayName = "CardDescription";
|
|
465
|
-
var CardContent =
|
|
661
|
+
var CardContent = React52__namespace.forwardRef(
|
|
466
662
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("px-[1.35rem] pb-[1.35rem]", className), ...props })
|
|
467
663
|
);
|
|
468
664
|
CardContent.displayName = "CardContent";
|
|
469
|
-
var CardFooter =
|
|
665
|
+
var CardFooter = React52__namespace.forwardRef(
|
|
470
666
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
471
667
|
"div",
|
|
472
668
|
{
|
|
@@ -477,7 +673,7 @@ var CardFooter = React18__namespace.forwardRef(
|
|
|
477
673
|
)
|
|
478
674
|
);
|
|
479
675
|
CardFooter.displayName = "CardFooter";
|
|
480
|
-
var Stat =
|
|
676
|
+
var Stat = React52__namespace.forwardRef(
|
|
481
677
|
({ className, label, value, delta, trend, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(Card, { ref, className: cn("p-[1.35rem] flex flex-col gap-2", className), ...props, children: [
|
|
482
678
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.78rem] font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: label }),
|
|
483
679
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[2rem] font-bold tracking-[-0.03em] tabular-nums leading-none", children: value }),
|
|
@@ -517,7 +713,7 @@ var avatarVariants = classVarianceAuthority.cva(
|
|
|
517
713
|
defaultVariants: { size: "md", tone: "secondary" }
|
|
518
714
|
}
|
|
519
715
|
);
|
|
520
|
-
var Avatar =
|
|
716
|
+
var Avatar = React52__namespace.forwardRef(
|
|
521
717
|
({ className, size, tone, src, alt, status, children, ...props }, ref) => {
|
|
522
718
|
const node = /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn(avatarVariants({ size, tone }), "overflow-hidden", className), ...props, children: src ? /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt, className: "h-full w-full object-cover" }) : children });
|
|
523
719
|
if (!status) return node;
|
|
@@ -528,21 +724,21 @@ var Avatar = React18__namespace.forwardRef(
|
|
|
528
724
|
}
|
|
529
725
|
);
|
|
530
726
|
Avatar.displayName = "Avatar";
|
|
531
|
-
var AvatarGroup =
|
|
727
|
+
var AvatarGroup = React52__namespace.forwardRef(
|
|
532
728
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex [&>*:not(:first-child)]:-ml-2.5", className), ...props })
|
|
533
729
|
);
|
|
534
730
|
AvatarGroup.displayName = "AvatarGroup";
|
|
535
|
-
var TabsContext =
|
|
731
|
+
var TabsContext = React52__namespace.createContext(null);
|
|
536
732
|
function useTabs() {
|
|
537
|
-
const ctx =
|
|
733
|
+
const ctx = React52__namespace.useContext(TabsContext);
|
|
538
734
|
if (!ctx) throw new Error("Tabs.* must be used within <Tabs>");
|
|
539
735
|
return ctx;
|
|
540
736
|
}
|
|
541
737
|
function Tabs({ value, defaultValue, onValueChange, className, children, ...props }) {
|
|
542
|
-
const [internal, setInternal] =
|
|
543
|
-
const uid =
|
|
738
|
+
const [internal, setInternal] = React52__namespace.useState(defaultValue ?? "");
|
|
739
|
+
const uid = React52__namespace.useId();
|
|
544
740
|
const current = value ?? internal;
|
|
545
|
-
const setValue =
|
|
741
|
+
const setValue = React52__namespace.useCallback(
|
|
546
742
|
(v) => {
|
|
547
743
|
if (value === void 0) setInternal(v);
|
|
548
744
|
onValueChange?.(v);
|
|
@@ -551,7 +747,7 @@ function Tabs({ value, defaultValue, onValueChange, className, children, ...prop
|
|
|
551
747
|
);
|
|
552
748
|
return /* @__PURE__ */ jsxRuntime.jsx(TabsContext.Provider, { value: { value: current, setValue, uid }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, ...props, children }) });
|
|
553
749
|
}
|
|
554
|
-
var TabsList =
|
|
750
|
+
var TabsList = React52__namespace.forwardRef(
|
|
555
751
|
({ className, onKeyDown, ...props }, ref) => {
|
|
556
752
|
const handleKeyDown = (e) => {
|
|
557
753
|
const container = e.currentTarget;
|
|
@@ -598,7 +794,7 @@ var TabsList = React18__namespace.forwardRef(
|
|
|
598
794
|
}
|
|
599
795
|
);
|
|
600
796
|
TabsList.displayName = "TabsList";
|
|
601
|
-
var TabsTrigger =
|
|
797
|
+
var TabsTrigger = React52__namespace.forwardRef(
|
|
602
798
|
({ className, value, children, ...props }, ref) => {
|
|
603
799
|
const { value: current, setValue, uid } = useTabs();
|
|
604
800
|
const active = current === value;
|
|
@@ -627,7 +823,7 @@ var TabsTrigger = React18__namespace.forwardRef(
|
|
|
627
823
|
}
|
|
628
824
|
);
|
|
629
825
|
TabsTrigger.displayName = "TabsTrigger";
|
|
630
|
-
var TabsContent =
|
|
826
|
+
var TabsContent = React52__namespace.forwardRef(
|
|
631
827
|
({ className, value, ...props }, ref) => {
|
|
632
828
|
const { value: current, uid } = useTabs();
|
|
633
829
|
const active = current === value;
|
|
@@ -647,10 +843,10 @@ var TabsContent = React18__namespace.forwardRef(
|
|
|
647
843
|
}
|
|
648
844
|
);
|
|
649
845
|
TabsContent.displayName = "TabsContent";
|
|
650
|
-
var AccordionContext =
|
|
846
|
+
var AccordionContext = React52__namespace.createContext(null);
|
|
651
847
|
function Accordion({ type = "single", defaultValue = [], className, children, ...props }) {
|
|
652
|
-
const [open, setOpen] =
|
|
653
|
-
const toggle =
|
|
848
|
+
const [open, setOpen] = React52__namespace.useState(defaultValue);
|
|
849
|
+
const toggle = React52__namespace.useCallback(
|
|
654
850
|
(v) => {
|
|
655
851
|
setOpen((prev) => {
|
|
656
852
|
const isOpen = prev.includes(v);
|
|
@@ -662,15 +858,15 @@ function Accordion({ type = "single", defaultValue = [], className, children, ..
|
|
|
662
858
|
);
|
|
663
859
|
return /* @__PURE__ */ jsxRuntime.jsx(AccordionContext.Provider, { value: { open, toggle }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("border border-border rounded-kj-lg overflow-hidden", className), ...props, children }) });
|
|
664
860
|
}
|
|
665
|
-
var ItemContext =
|
|
666
|
-
var AccordionItem =
|
|
861
|
+
var ItemContext = React52__namespace.createContext("");
|
|
862
|
+
var AccordionItem = React52__namespace.forwardRef(
|
|
667
863
|
({ className, value, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(ItemContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("border-t border-border first:border-t-0", className), ...props }) })
|
|
668
864
|
);
|
|
669
865
|
AccordionItem.displayName = "AccordionItem";
|
|
670
|
-
var AccordionTrigger =
|
|
866
|
+
var AccordionTrigger = React52__namespace.forwardRef(
|
|
671
867
|
({ className, children, ...props }, ref) => {
|
|
672
|
-
const ctx =
|
|
673
|
-
const value =
|
|
868
|
+
const ctx = React52__namespace.useContext(AccordionContext);
|
|
869
|
+
const value = React52__namespace.useContext(ItemContext);
|
|
674
870
|
const isOpen = ctx.open.includes(value);
|
|
675
871
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
676
872
|
"button",
|
|
@@ -707,10 +903,10 @@ var AccordionTrigger = React18__namespace.forwardRef(
|
|
|
707
903
|
}
|
|
708
904
|
);
|
|
709
905
|
AccordionTrigger.displayName = "AccordionTrigger";
|
|
710
|
-
var AccordionContent =
|
|
906
|
+
var AccordionContent = React52__namespace.forwardRef(
|
|
711
907
|
({ className, children, ...props }, ref) => {
|
|
712
|
-
const ctx =
|
|
713
|
-
const value =
|
|
908
|
+
const ctx = React52__namespace.useContext(AccordionContext);
|
|
909
|
+
const value = React52__namespace.useContext(ItemContext);
|
|
714
910
|
const isOpen = ctx.open.includes(value);
|
|
715
911
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
716
912
|
"div",
|
|
@@ -724,11 +920,11 @@ var AccordionContent = React18__namespace.forwardRef(
|
|
|
724
920
|
}
|
|
725
921
|
);
|
|
726
922
|
AccordionContent.displayName = "AccordionContent";
|
|
727
|
-
var MenuContext =
|
|
923
|
+
var MenuContext = React52__namespace.createContext(null);
|
|
728
924
|
function DropdownMenu({ children, className }) {
|
|
729
|
-
const [open, setOpen] =
|
|
730
|
-
const ref =
|
|
731
|
-
|
|
925
|
+
const [open, setOpen] = React52__namespace.useState(false);
|
|
926
|
+
const ref = React52__namespace.useRef(null);
|
|
927
|
+
React52__namespace.useEffect(() => {
|
|
732
928
|
if (!open) return;
|
|
733
929
|
const onDoc = (e) => {
|
|
734
930
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -743,11 +939,11 @@ function DropdownMenu({ children, className }) {
|
|
|
743
939
|
}, [open]);
|
|
744
940
|
return /* @__PURE__ */ jsxRuntime.jsx(MenuContext.Provider, { value: { open, setOpen }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("relative inline-block", className), children }) });
|
|
745
941
|
}
|
|
746
|
-
var DropdownMenuTrigger =
|
|
747
|
-
const ctx =
|
|
942
|
+
var DropdownMenuTrigger = React52__namespace.forwardRef(({ onClick, asChild, ...props }, ref) => {
|
|
943
|
+
const ctx = React52__namespace.useContext(MenuContext);
|
|
748
944
|
if (asChild) {
|
|
749
|
-
const child =
|
|
750
|
-
return
|
|
945
|
+
const child = React52__namespace.Children.only(props.children);
|
|
946
|
+
return React52__namespace.cloneElement(child, {
|
|
751
947
|
ref,
|
|
752
948
|
...props,
|
|
753
949
|
...child.props,
|
|
@@ -777,9 +973,9 @@ var DropdownMenuTrigger = React18__namespace.forwardRef(({ onClick, asChild, ...
|
|
|
777
973
|
});
|
|
778
974
|
DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
|
|
779
975
|
function DropdownMenuContent({ className, align = "start", children, ...props }) {
|
|
780
|
-
const ctx =
|
|
781
|
-
const ref =
|
|
782
|
-
|
|
976
|
+
const ctx = React52__namespace.useContext(MenuContext);
|
|
977
|
+
const ref = React52__namespace.useRef(null);
|
|
978
|
+
React52__namespace.useEffect(() => {
|
|
783
979
|
if (!ctx.open) return;
|
|
784
980
|
const container = ref.current;
|
|
785
981
|
if (container) {
|
|
@@ -826,9 +1022,9 @@ function DropdownMenuContent({ className, align = "start", children, ...props })
|
|
|
826
1022
|
}
|
|
827
1023
|
);
|
|
828
1024
|
}
|
|
829
|
-
var DropdownMenuItem =
|
|
1025
|
+
var DropdownMenuItem = React52__namespace.forwardRef(
|
|
830
1026
|
({ className, danger, icon, children, onClick, ...props }, ref) => {
|
|
831
|
-
const ctx =
|
|
1027
|
+
const ctx = React52__namespace.useContext(MenuContext);
|
|
832
1028
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
833
1029
|
"button",
|
|
834
1030
|
{
|
|
@@ -858,11 +1054,11 @@ DropdownMenuItem.displayName = "DropdownMenuItem";
|
|
|
858
1054
|
function DropdownMenuSeparator({ className }) {
|
|
859
1055
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("h-px bg-border my-1.5", className), role: "separator" });
|
|
860
1056
|
}
|
|
861
|
-
var Breadcrumb =
|
|
1057
|
+
var Breadcrumb = React52__namespace.forwardRef(
|
|
862
1058
|
({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("nav", { ref, "aria-label": "Breadcrumb", className: cn("flex items-center gap-1.5 text-[0.85rem] text-muted-foreground", className), ...props, children })
|
|
863
1059
|
);
|
|
864
1060
|
Breadcrumb.displayName = "Breadcrumb";
|
|
865
|
-
var BreadcrumbItem =
|
|
1061
|
+
var BreadcrumbItem = React52__namespace.forwardRef(
|
|
866
1062
|
({ className, current, children, ...props }, ref) => {
|
|
867
1063
|
if (current) {
|
|
868
1064
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-current": "page", className: cn("text-foreground font-semibold", className), children });
|
|
@@ -909,7 +1105,7 @@ function Pagination({ page, pageCount, onPageChange, className }) {
|
|
|
909
1105
|
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Next", disabled: page >= pageCount, onClick: () => onPageChange(page + 1), children: /* @__PURE__ */ jsxRuntime.jsx(Chevron, { dir: "right" }) })
|
|
910
1106
|
] });
|
|
911
1107
|
}
|
|
912
|
-
var BottomNavigation =
|
|
1108
|
+
var BottomNavigation = React52__namespace.forwardRef(
|
|
913
1109
|
({ className, items, showLabels = "always", fixed = true, ...props }, ref) => {
|
|
914
1110
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
915
1111
|
"nav",
|
|
@@ -981,27 +1177,27 @@ var BottomNavigation = React18__namespace.forwardRef(
|
|
|
981
1177
|
}
|
|
982
1178
|
);
|
|
983
1179
|
BottomNavigation.displayName = "BottomNavigation";
|
|
984
|
-
var TableWrap =
|
|
1180
|
+
var TableWrap = React52__namespace.forwardRef(
|
|
985
1181
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("border border-border rounded-kj-lg overflow-x-auto w-full", className), ...props })
|
|
986
1182
|
);
|
|
987
1183
|
TableWrap.displayName = "TableWrap";
|
|
988
|
-
var Table =
|
|
1184
|
+
var Table = React52__namespace.forwardRef(
|
|
989
1185
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("table", { ref, className: cn("w-full border-collapse text-[0.85rem]", className), ...props })
|
|
990
1186
|
);
|
|
991
1187
|
Table.displayName = "Table";
|
|
992
|
-
var TableHeader =
|
|
1188
|
+
var TableHeader = React52__namespace.forwardRef(
|
|
993
1189
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("thead", { ref, className, ...props })
|
|
994
1190
|
);
|
|
995
1191
|
TableHeader.displayName = "TableHeader";
|
|
996
|
-
var TableBody =
|
|
1192
|
+
var TableBody = React52__namespace.forwardRef(
|
|
997
1193
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tbody", { ref, className, ...props })
|
|
998
1194
|
);
|
|
999
1195
|
TableBody.displayName = "TableBody";
|
|
1000
|
-
var TableRow =
|
|
1196
|
+
var TableRow = React52__namespace.forwardRef(
|
|
1001
1197
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tr", { ref, className: cn("transition-colors hover:bg-muted/50", className), ...props })
|
|
1002
1198
|
);
|
|
1003
1199
|
TableRow.displayName = "TableRow";
|
|
1004
|
-
var TableHead =
|
|
1200
|
+
var TableHead = React52__namespace.forwardRef(
|
|
1005
1201
|
({ className, numeric, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1006
1202
|
"th",
|
|
1007
1203
|
{
|
|
@@ -1016,7 +1212,7 @@ var TableHead = React18__namespace.forwardRef(
|
|
|
1016
1212
|
)
|
|
1017
1213
|
);
|
|
1018
1214
|
TableHead.displayName = "TableHead";
|
|
1019
|
-
var TableCell =
|
|
1215
|
+
var TableCell = React52__namespace.forwardRef(
|
|
1020
1216
|
({ className, numeric, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1021
1217
|
"td",
|
|
1022
1218
|
{
|
|
@@ -1032,30 +1228,33 @@ var TableCell = React18__namespace.forwardRef(
|
|
|
1032
1228
|
);
|
|
1033
1229
|
TableCell.displayName = "TableCell";
|
|
1034
1230
|
function Tooltip({ content, children, className }) {
|
|
1035
|
-
return
|
|
1036
|
-
|
|
1037
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1231
|
+
return (
|
|
1232
|
+
/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */
|
|
1233
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("relative inline-flex group", className), tabIndex: 0, children: [
|
|
1234
|
+
children,
|
|
1235
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1236
|
+
"span",
|
|
1237
|
+
{
|
|
1238
|
+
role: "tooltip",
|
|
1239
|
+
className: cn(
|
|
1240
|
+
"pointer-events-none absolute bottom-[calc(100%+8px)] left-1/2 -translate-x-1/2 translate-y-1 whitespace-nowrap",
|
|
1241
|
+
"rounded-kj-sm bg-foreground text-background text-xs font-medium px-2.5 py-1.5 shadow-kj-md",
|
|
1242
|
+
"opacity-0 transition-all duration-150 group-hover:opacity-100 group-hover:translate-y-0 group-focus-visible:opacity-100 group-focus-visible:translate-y-0",
|
|
1243
|
+
"after:content-[''] after:absolute after:top-full after:left-1/2 after:-translate-x-1/2 after:border-[5px] after:border-transparent after:border-t-foreground"
|
|
1244
|
+
),
|
|
1245
|
+
children: content
|
|
1246
|
+
}
|
|
1247
|
+
)
|
|
1248
|
+
] })
|
|
1249
|
+
);
|
|
1051
1250
|
}
|
|
1052
|
-
var ModalContext =
|
|
1251
|
+
var ModalContext = React52__namespace.createContext(null);
|
|
1053
1252
|
function Modal({ open, onClose, children, width = 440, className, showClose = true }) {
|
|
1054
|
-
const titleId =
|
|
1055
|
-
const descId =
|
|
1056
|
-
const containerRef =
|
|
1057
|
-
const lastActiveElement =
|
|
1058
|
-
|
|
1253
|
+
const titleId = React52__namespace.useId();
|
|
1254
|
+
const descId = React52__namespace.useId();
|
|
1255
|
+
const containerRef = React52__namespace.useRef(null);
|
|
1256
|
+
const lastActiveElement = React52__namespace.useRef(null);
|
|
1257
|
+
React52__namespace.useEffect(() => {
|
|
1059
1258
|
if (!open) {
|
|
1060
1259
|
if (lastActiveElement.current) {
|
|
1061
1260
|
lastActiveElement.current.focus();
|
|
@@ -1156,20 +1355,20 @@ function Modal({ open, onClose, children, width = 440, className, showClose = tr
|
|
|
1156
1355
|
}
|
|
1157
1356
|
);
|
|
1158
1357
|
}
|
|
1159
|
-
function ModalTitle({ className, id, ...props }) {
|
|
1160
|
-
const ctx =
|
|
1161
|
-
return /* @__PURE__ */ jsxRuntime.jsx("h3", { id: id ?? ctx?.titleId, className: cn("m-0 mb-2 text-[1.15rem] font-bold tracking-[-0.01em]", className), ...props });
|
|
1358
|
+
function ModalTitle({ className, id, children, ...props }) {
|
|
1359
|
+
const ctx = React52__namespace.useContext(ModalContext);
|
|
1360
|
+
return /* @__PURE__ */ jsxRuntime.jsx("h3", { id: id ?? ctx?.titleId, className: cn("m-0 mb-2 text-[1.15rem] font-bold tracking-[-0.01em]", className), ...props, children });
|
|
1162
1361
|
}
|
|
1163
1362
|
function ModalDescription({ className, id, ...props }) {
|
|
1164
|
-
const ctx =
|
|
1363
|
+
const ctx = React52__namespace.useContext(ModalContext);
|
|
1165
1364
|
return /* @__PURE__ */ jsxRuntime.jsx("p", { id: id ?? ctx?.descId, className: cn("m-0 text-[0.9rem] text-muted-foreground", className), ...props });
|
|
1166
1365
|
}
|
|
1167
1366
|
function ModalActions({ className, ...props }) {
|
|
1168
1367
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex gap-2.5 justify-end mt-6", className), ...props });
|
|
1169
1368
|
}
|
|
1170
|
-
var ToastContext =
|
|
1369
|
+
var ToastContext = React52__namespace.createContext(null);
|
|
1171
1370
|
function useToast() {
|
|
1172
|
-
const ctx =
|
|
1371
|
+
const ctx = React52__namespace.useContext(ToastContext);
|
|
1173
1372
|
if (!ctx) throw new Error("useToast must be used within <ToastProvider>");
|
|
1174
1373
|
return ctx;
|
|
1175
1374
|
}
|
|
@@ -1190,13 +1389,13 @@ var toneBorder = {
|
|
|
1190
1389
|
danger: "border-l-danger"
|
|
1191
1390
|
};
|
|
1192
1391
|
function ToastProvider({ children }) {
|
|
1193
|
-
const [items, setItems] =
|
|
1194
|
-
const idRef =
|
|
1195
|
-
const remove =
|
|
1392
|
+
const [items, setItems] = React52__namespace.useState([]);
|
|
1393
|
+
const idRef = React52__namespace.useRef(0);
|
|
1394
|
+
const remove = React52__namespace.useCallback((id) => {
|
|
1196
1395
|
setItems((prev) => prev.map((t) => t.id === id ? { ...t, leaving: true } : t));
|
|
1197
1396
|
setTimeout(() => setItems((prev) => prev.filter((t) => t.id !== id)), 250);
|
|
1198
1397
|
}, []);
|
|
1199
|
-
const toast =
|
|
1398
|
+
const toast = React52__namespace.useCallback(
|
|
1200
1399
|
({ message, tone = "default", duration = 3200 }) => {
|
|
1201
1400
|
const id = ++idRef.current;
|
|
1202
1401
|
setItems((prev) => [...prev, { id, message, tone, duration }]);
|
|
@@ -1226,7 +1425,7 @@ function ToastProvider({ children }) {
|
|
|
1226
1425
|
)) })
|
|
1227
1426
|
] });
|
|
1228
1427
|
}
|
|
1229
|
-
var PageHeader =
|
|
1428
|
+
var PageHeader = React52__namespace.forwardRef(
|
|
1230
1429
|
({ eyebrow, title, description, actions }, ref) => /* @__PURE__ */ jsxRuntime.jsx("header", { ref, className: "py-12 md:py-16", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6 md:flex-row md:items-end md:justify-between", children: [
|
|
1231
1430
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 max-w-2xl", children: [
|
|
1232
1431
|
eyebrow && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-mono text-xs font-bold uppercase tracking-[0.2em] text-primary", children: eyebrow }),
|
|
@@ -1237,7 +1436,111 @@ var PageHeader = React18__namespace.forwardRef(
|
|
|
1237
1436
|
] }) })
|
|
1238
1437
|
);
|
|
1239
1438
|
PageHeader.displayName = "PageHeader";
|
|
1240
|
-
var
|
|
1439
|
+
var SectionHeaderKicker = React52__namespace.forwardRef(
|
|
1440
|
+
({ className, children, ...props }, ref) => {
|
|
1441
|
+
if (!children) return null;
|
|
1442
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1443
|
+
"p",
|
|
1444
|
+
{
|
|
1445
|
+
ref,
|
|
1446
|
+
className: cn(
|
|
1447
|
+
"font-mono text-xs font-bold uppercase tracking-[0.2em] text-primary",
|
|
1448
|
+
className
|
|
1449
|
+
),
|
|
1450
|
+
...props,
|
|
1451
|
+
children
|
|
1452
|
+
}
|
|
1453
|
+
);
|
|
1454
|
+
}
|
|
1455
|
+
);
|
|
1456
|
+
SectionHeaderKicker.displayName = "SectionHeaderKicker";
|
|
1457
|
+
var SectionHeaderTitle = React52__namespace.forwardRef(
|
|
1458
|
+
({ className, as: Component = "h2", children, ...props }, ref) => {
|
|
1459
|
+
if (!children) return null;
|
|
1460
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1461
|
+
Component,
|
|
1462
|
+
{
|
|
1463
|
+
ref,
|
|
1464
|
+
className: cn("text-2xl font-bold tracking-tight text-foreground sm:text-3xl", className),
|
|
1465
|
+
...props,
|
|
1466
|
+
children
|
|
1467
|
+
}
|
|
1468
|
+
);
|
|
1469
|
+
}
|
|
1470
|
+
);
|
|
1471
|
+
SectionHeaderTitle.displayName = "SectionHeaderTitle";
|
|
1472
|
+
var SectionHeaderDescription = React52__namespace.forwardRef(({ className, children, ...props }, ref) => {
|
|
1473
|
+
if (!children) return null;
|
|
1474
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1475
|
+
"p",
|
|
1476
|
+
{
|
|
1477
|
+
ref,
|
|
1478
|
+
className: cn("text-base leading-relaxed text-muted-foreground max-w-2xl", className),
|
|
1479
|
+
...props,
|
|
1480
|
+
children
|
|
1481
|
+
}
|
|
1482
|
+
);
|
|
1483
|
+
});
|
|
1484
|
+
SectionHeaderDescription.displayName = "SectionHeaderDescription";
|
|
1485
|
+
var SectionHeaderActions = React52__namespace.forwardRef(
|
|
1486
|
+
({ className, children, ...props }, ref) => {
|
|
1487
|
+
if (!children) return null;
|
|
1488
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex flex-wrap items-center gap-3", className), ...props, children });
|
|
1489
|
+
}
|
|
1490
|
+
);
|
|
1491
|
+
SectionHeaderActions.displayName = "SectionHeaderActions";
|
|
1492
|
+
var SectionHeader = React52__namespace.forwardRef(
|
|
1493
|
+
({
|
|
1494
|
+
kicker,
|
|
1495
|
+
title,
|
|
1496
|
+
description,
|
|
1497
|
+
actions,
|
|
1498
|
+
align = "left",
|
|
1499
|
+
headingLevel = "h2",
|
|
1500
|
+
divider = false,
|
|
1501
|
+
className,
|
|
1502
|
+
children,
|
|
1503
|
+
...props
|
|
1504
|
+
}, ref) => {
|
|
1505
|
+
const isCentered = align === "center";
|
|
1506
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1507
|
+
"div",
|
|
1508
|
+
{
|
|
1509
|
+
ref,
|
|
1510
|
+
className: cn(
|
|
1511
|
+
"space-y-4",
|
|
1512
|
+
isCentered ? "text-center items-center mx-auto max-w-3xl" : "md:flex md:items-end md:justify-between md:space-y-0",
|
|
1513
|
+
divider && "border-b border-border pb-6",
|
|
1514
|
+
className
|
|
1515
|
+
),
|
|
1516
|
+
...props,
|
|
1517
|
+
children: children ? children : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1518
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1519
|
+
"div",
|
|
1520
|
+
{
|
|
1521
|
+
className: cn(
|
|
1522
|
+
"space-y-2",
|
|
1523
|
+
isCentered && "flex flex-col items-center"
|
|
1524
|
+
),
|
|
1525
|
+
children: [
|
|
1526
|
+
kicker && /* @__PURE__ */ jsxRuntime.jsx(SectionHeaderKicker, { children: kicker }),
|
|
1527
|
+
title && /* @__PURE__ */ jsxRuntime.jsx(SectionHeaderTitle, { as: headingLevel, children: title }),
|
|
1528
|
+
description && /* @__PURE__ */ jsxRuntime.jsx(SectionHeaderDescription, { children: description })
|
|
1529
|
+
]
|
|
1530
|
+
}
|
|
1531
|
+
),
|
|
1532
|
+
actions && /* @__PURE__ */ jsxRuntime.jsx(SectionHeaderActions, { className: cn(isCentered && "justify-center mt-4"), children: actions })
|
|
1533
|
+
] })
|
|
1534
|
+
}
|
|
1535
|
+
);
|
|
1536
|
+
}
|
|
1537
|
+
);
|
|
1538
|
+
SectionHeader.displayName = "SectionHeader";
|
|
1539
|
+
SectionHeader.Kicker = SectionHeaderKicker;
|
|
1540
|
+
SectionHeader.Title = SectionHeaderTitle;
|
|
1541
|
+
SectionHeader.Description = SectionHeaderDescription;
|
|
1542
|
+
SectionHeader.Actions = SectionHeaderActions;
|
|
1543
|
+
var EmptyState = React52__namespace.forwardRef(
|
|
1241
1544
|
({ className, icon, title, description, action, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1242
1545
|
"div",
|
|
1243
1546
|
{
|
|
@@ -1257,7 +1560,7 @@ var EmptyState = React18__namespace.forwardRef(
|
|
|
1257
1560
|
)
|
|
1258
1561
|
);
|
|
1259
1562
|
EmptyState.displayName = "EmptyState";
|
|
1260
|
-
var MetricCard =
|
|
1563
|
+
var MetricCard = React52__namespace.forwardRef(
|
|
1261
1564
|
({ className, title, value, trend, trendDirection = "neutral", description, icon, ...props }, ref) => {
|
|
1262
1565
|
const trendColor = {
|
|
1263
1566
|
up: "text-success bg-success-surface border-success/20",
|
|
@@ -1298,22 +1601,22 @@ function DataTable({
|
|
|
1298
1601
|
onSort,
|
|
1299
1602
|
...props
|
|
1300
1603
|
}) {
|
|
1301
|
-
const getRowId =
|
|
1604
|
+
const getRowId = React52__namespace.useCallback(
|
|
1302
1605
|
(row, index) => getRowKey ? getRowKey(row, index) : index,
|
|
1303
1606
|
[getRowKey]
|
|
1304
1607
|
);
|
|
1305
1608
|
const isSelectionActive = selectedRows !== void 0 && onSelectionChange !== void 0;
|
|
1306
|
-
const allSelected =
|
|
1609
|
+
const allSelected = React52__namespace.useMemo(() => {
|
|
1307
1610
|
if (!isSelectionActive || data.length === 0) return false;
|
|
1308
1611
|
return data.every((row, idx) => selectedRows.has(getRowId(row, idx)));
|
|
1309
1612
|
}, [isSelectionActive, data, selectedRows, getRowId]);
|
|
1310
|
-
const someSelected =
|
|
1613
|
+
const someSelected = React52__namespace.useMemo(() => {
|
|
1311
1614
|
if (!isSelectionActive || data.length === 0) return false;
|
|
1312
1615
|
const selectedCount = data.filter((row, idx) => selectedRows.has(getRowId(row, idx))).length;
|
|
1313
1616
|
return selectedCount > 0 && selectedCount < data.length;
|
|
1314
1617
|
}, [isSelectionActive, data, selectedRows, getRowId]);
|
|
1315
|
-
const headerCheckboxRef =
|
|
1316
|
-
|
|
1618
|
+
const headerCheckboxRef = React52__namespace.useRef(null);
|
|
1619
|
+
React52__namespace.useEffect(() => {
|
|
1317
1620
|
if (headerCheckboxRef.current) {
|
|
1318
1621
|
headerCheckboxRef.current.indeterminate = someSelected;
|
|
1319
1622
|
}
|
|
@@ -1467,7 +1770,7 @@ function DataTable({
|
|
|
1467
1770
|
] });
|
|
1468
1771
|
}
|
|
1469
1772
|
DataTable.displayName = "DataTable";
|
|
1470
|
-
var ErrorState =
|
|
1773
|
+
var ErrorState = React52__namespace.forwardRef(
|
|
1471
1774
|
({ className, title = "Wyst\u0105pi\u0142 b\u0142\u0105d", message, onRetry, retryLabel = "Spr\xF3buj ponownie", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1472
1775
|
"div",
|
|
1473
1776
|
{
|
|
@@ -1487,7 +1790,7 @@ var ErrorState = React18__namespace.forwardRef(
|
|
|
1487
1790
|
)
|
|
1488
1791
|
);
|
|
1489
1792
|
ErrorState.displayName = "ErrorState";
|
|
1490
|
-
var Skeleton =
|
|
1793
|
+
var Skeleton = React52__namespace.forwardRef(
|
|
1491
1794
|
({ className, variant = "rectangular", width, height, style, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1492
1795
|
"div",
|
|
1493
1796
|
{
|
|
@@ -1509,7 +1812,7 @@ var Skeleton = React18__namespace.forwardRef(
|
|
|
1509
1812
|
)
|
|
1510
1813
|
);
|
|
1511
1814
|
Skeleton.displayName = "Skeleton";
|
|
1512
|
-
var DashboardShell =
|
|
1815
|
+
var DashboardShell = React52__namespace.forwardRef(
|
|
1513
1816
|
({
|
|
1514
1817
|
className,
|
|
1515
1818
|
sidebar,
|
|
@@ -1521,7 +1824,7 @@ var DashboardShell = React18__namespace.forwardRef(
|
|
|
1521
1824
|
mobileSidebar,
|
|
1522
1825
|
...props
|
|
1523
1826
|
}, ref) => {
|
|
1524
|
-
const [mobileOpen, setMobileOpen] =
|
|
1827
|
+
const [mobileOpen, setMobileOpen] = React52__namespace.useState(false);
|
|
1525
1828
|
const contentWidthClass = {
|
|
1526
1829
|
default: "max-w-7xl w-full mx-auto",
|
|
1527
1830
|
wide: "max-w-screen-2xl w-full mx-auto",
|
|
@@ -1612,7 +1915,7 @@ var DashboardShell = React18__namespace.forwardRef(
|
|
|
1612
1915
|
}
|
|
1613
1916
|
);
|
|
1614
1917
|
DashboardShell.displayName = "DashboardShell";
|
|
1615
|
-
var SettingsLayout =
|
|
1918
|
+
var SettingsLayout = React52__namespace.forwardRef(
|
|
1616
1919
|
({ className, sidebar, children, title, description, ...props }, ref) => {
|
|
1617
1920
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn("space-y-6 w-full", className), ...props, children: [
|
|
1618
1921
|
(title || description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-border pb-4", children: [
|
|
@@ -1627,7 +1930,7 @@ var SettingsLayout = React18__namespace.forwardRef(
|
|
|
1627
1930
|
}
|
|
1628
1931
|
);
|
|
1629
1932
|
SettingsLayout.displayName = "SettingsLayout";
|
|
1630
|
-
var DetailPageLayout =
|
|
1933
|
+
var DetailPageLayout = React52__namespace.forwardRef(
|
|
1631
1934
|
({ className, title, description, backHref, backLabel = "Back", onBackClick, actions, aside, children, ...props }, ref) => {
|
|
1632
1935
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn("space-y-6 w-full", className), ...props, children: [
|
|
1633
1936
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
@@ -1673,7 +1976,7 @@ var DetailPageLayout = React18__namespace.forwardRef(
|
|
|
1673
1976
|
}
|
|
1674
1977
|
);
|
|
1675
1978
|
DetailPageLayout.displayName = "DetailPageLayout";
|
|
1676
|
-
var TableToolbar =
|
|
1979
|
+
var TableToolbar = React52__namespace.forwardRef(
|
|
1677
1980
|
({ className, searchQuery, onSearchChange, searchPlaceholder = "Search...", actions, filters, ...props }, ref) => {
|
|
1678
1981
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1679
1982
|
"div",
|
|
@@ -1742,9 +2045,9 @@ function Drawer({
|
|
|
1742
2045
|
width = "max-w-md",
|
|
1743
2046
|
side = "right"
|
|
1744
2047
|
}) {
|
|
1745
|
-
const containerRef =
|
|
1746
|
-
const lastActiveElement =
|
|
1747
|
-
|
|
2048
|
+
const containerRef = React52__namespace.useRef(null);
|
|
2049
|
+
const lastActiveElement = React52__namespace.useRef(null);
|
|
2050
|
+
React52__namespace.useEffect(() => {
|
|
1748
2051
|
if (!open) {
|
|
1749
2052
|
if (lastActiveElement.current) {
|
|
1750
2053
|
lastActiveElement.current.focus();
|
|
@@ -1863,11 +2166,11 @@ function Drawer({
|
|
|
1863
2166
|
}
|
|
1864
2167
|
Drawer.displayName = "Drawer";
|
|
1865
2168
|
function CommandPalette({ open, onClose, items, placeholder = "Type a command or search..." }) {
|
|
1866
|
-
const [search, setSearch] =
|
|
1867
|
-
const [activeIndex, setActiveIndex] =
|
|
1868
|
-
const containerRef =
|
|
1869
|
-
const listRef =
|
|
1870
|
-
|
|
2169
|
+
const [search, setSearch] = React52__namespace.useState("");
|
|
2170
|
+
const [activeIndex, setActiveIndex] = React52__namespace.useState(0);
|
|
2171
|
+
const containerRef = React52__namespace.useRef(null);
|
|
2172
|
+
const listRef = React52__namespace.useRef(null);
|
|
2173
|
+
React52__namespace.useEffect(() => {
|
|
1871
2174
|
if (open) {
|
|
1872
2175
|
setSearch("");
|
|
1873
2176
|
setActiveIndex(0);
|
|
@@ -1876,17 +2179,17 @@ function CommandPalette({ open, onClose, items, placeholder = "Type a command or
|
|
|
1876
2179
|
document.body.style.overflow = "";
|
|
1877
2180
|
}
|
|
1878
2181
|
}, [open]);
|
|
1879
|
-
const filteredItems =
|
|
2182
|
+
const filteredItems = React52__namespace.useMemo(() => {
|
|
1880
2183
|
if (!search) return items;
|
|
1881
2184
|
const cleanSearch = search.toLowerCase();
|
|
1882
2185
|
return items.filter(
|
|
1883
2186
|
(item) => item.title.toLowerCase().includes(cleanSearch) || item.subtitle?.toLowerCase().includes(cleanSearch) || item.category?.toLowerCase().includes(cleanSearch)
|
|
1884
2187
|
);
|
|
1885
2188
|
}, [search, items]);
|
|
1886
|
-
|
|
2189
|
+
React52__namespace.useEffect(() => {
|
|
1887
2190
|
setActiveIndex(0);
|
|
1888
2191
|
}, [filteredItems]);
|
|
1889
|
-
|
|
2192
|
+
React52__namespace.useEffect(() => {
|
|
1890
2193
|
if (!open) return;
|
|
1891
2194
|
const handleKeyDown = (e) => {
|
|
1892
2195
|
if (e.key === "Escape") {
|
|
@@ -1910,7 +2213,7 @@ function CommandPalette({ open, onClose, items, placeholder = "Type a command or
|
|
|
1910
2213
|
document.addEventListener("keydown", handleKeyDown);
|
|
1911
2214
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
1912
2215
|
}, [open, filteredItems, activeIndex, onClose]);
|
|
1913
|
-
|
|
2216
|
+
React52__namespace.useEffect(() => {
|
|
1914
2217
|
if (listRef.current) {
|
|
1915
2218
|
const activeEl = listRef.current.querySelector('[aria-selected="true"]');
|
|
1916
2219
|
if (activeEl) {
|
|
@@ -2113,7 +2416,7 @@ var fabVariants = classVarianceAuthority.cva(
|
|
|
2113
2416
|
defaultVariants: { variant: "primary", size: "md", position: "bottom-right" }
|
|
2114
2417
|
}
|
|
2115
2418
|
);
|
|
2116
|
-
var Fab =
|
|
2419
|
+
var Fab = React52__namespace.forwardRef(
|
|
2117
2420
|
({ className, variant, size, position, mobileOnly, icon, label, loading, disabled, ...props }, ref) => {
|
|
2118
2421
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2119
2422
|
"button",
|
|
@@ -2140,7 +2443,7 @@ var Fab = React18__namespace.forwardRef(
|
|
|
2140
2443
|
}
|
|
2141
2444
|
);
|
|
2142
2445
|
Fab.displayName = "Fab";
|
|
2143
|
-
var BottomSheetContext =
|
|
2446
|
+
var BottomSheetContext = React52__namespace.createContext(null);
|
|
2144
2447
|
function BottomSheet({
|
|
2145
2448
|
open,
|
|
2146
2449
|
onClose,
|
|
@@ -2149,12 +2452,12 @@ function BottomSheet({
|
|
|
2149
2452
|
className,
|
|
2150
2453
|
showClose = true
|
|
2151
2454
|
}) {
|
|
2152
|
-
const titleId =
|
|
2153
|
-
const descId =
|
|
2154
|
-
const containerRef =
|
|
2155
|
-
const lastActiveElement =
|
|
2156
|
-
const [mounted, setMounted] =
|
|
2157
|
-
|
|
2455
|
+
const titleId = React52__namespace.useId();
|
|
2456
|
+
const descId = React52__namespace.useId();
|
|
2457
|
+
const containerRef = React52__namespace.useRef(null);
|
|
2458
|
+
const lastActiveElement = React52__namespace.useRef(null);
|
|
2459
|
+
const [mounted, setMounted] = React52__namespace.useState(open);
|
|
2460
|
+
React52__namespace.useEffect(() => {
|
|
2158
2461
|
if (open) {
|
|
2159
2462
|
setMounted(true);
|
|
2160
2463
|
} else {
|
|
@@ -2162,7 +2465,7 @@ function BottomSheet({
|
|
|
2162
2465
|
return () => clearTimeout(timer);
|
|
2163
2466
|
}
|
|
2164
2467
|
}, [open]);
|
|
2165
|
-
|
|
2468
|
+
React52__namespace.useEffect(() => {
|
|
2166
2469
|
if (!open) return;
|
|
2167
2470
|
lastActiveElement.current = document.activeElement;
|
|
2168
2471
|
const container = containerRef.current;
|
|
@@ -2284,12 +2587,12 @@ function BottomSheet({
|
|
|
2284
2587
|
function BottomSheetHeader({ className, ...props }) {
|
|
2285
2588
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("p-6 flex flex-col gap-1.5 border-b border-border", className), ...props });
|
|
2286
2589
|
}
|
|
2287
|
-
function BottomSheetTitle({ className, id, ...props }) {
|
|
2288
|
-
const ctx =
|
|
2289
|
-
return /* @__PURE__ */ jsxRuntime.jsx("h2", { id: id ?? ctx?.titleId, className: cn("m-0 text-[1.15rem] font-bold tracking-[-0.01em]", className), ...props });
|
|
2590
|
+
function BottomSheetTitle({ className, id, children, ...props }) {
|
|
2591
|
+
const ctx = React52__namespace.useContext(BottomSheetContext);
|
|
2592
|
+
return /* @__PURE__ */ jsxRuntime.jsx("h2", { id: id ?? ctx?.titleId, className: cn("m-0 text-[1.15rem] font-bold tracking-[-0.01em]", className), ...props, children });
|
|
2290
2593
|
}
|
|
2291
2594
|
function BottomSheetDescription({ className, id, ...props }) {
|
|
2292
|
-
const ctx =
|
|
2595
|
+
const ctx = React52__namespace.useContext(BottomSheetContext);
|
|
2293
2596
|
return /* @__PURE__ */ jsxRuntime.jsx("p", { id: id ?? ctx?.descId, className: cn("m-0 text-[0.9rem] text-muted-foreground", className), ...props });
|
|
2294
2597
|
}
|
|
2295
2598
|
function BottomSheetContent({ className, ...props }) {
|
|
@@ -2310,7 +2613,7 @@ var kbdVariants = classVarianceAuthority.cva(
|
|
|
2310
2613
|
defaultVariants: { size: "sm" }
|
|
2311
2614
|
}
|
|
2312
2615
|
);
|
|
2313
|
-
var Kbd =
|
|
2616
|
+
var Kbd = React52__namespace.forwardRef(
|
|
2314
2617
|
({ className, size, keys, children, ...props }, ref) => {
|
|
2315
2618
|
if (keys && keys.length > 0) {
|
|
2316
2619
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2327,9 +2630,9 @@ var Kbd = React18__namespace.forwardRef(
|
|
|
2327
2630
|
}
|
|
2328
2631
|
);
|
|
2329
2632
|
Kbd.displayName = "Kbd";
|
|
2330
|
-
var CodeBlock =
|
|
2633
|
+
var CodeBlock = React52__namespace.forwardRef(
|
|
2331
2634
|
({ className, code, language, filename, copyable = true, maxHeight, ...props }, ref) => {
|
|
2332
|
-
const [copied, setCopied] =
|
|
2635
|
+
const [copied, setCopied] = React52__namespace.useState(false);
|
|
2333
2636
|
const canCopy = copyable && typeof navigator !== "undefined" && !!navigator.clipboard;
|
|
2334
2637
|
const onCopy = () => {
|
|
2335
2638
|
navigator.clipboard.writeText(code).then(
|
|
@@ -2375,26 +2678,40 @@ var CodeBlock = React18__namespace.forwardRef(
|
|
|
2375
2678
|
}
|
|
2376
2679
|
);
|
|
2377
2680
|
CodeBlock.displayName = "CodeBlock";
|
|
2378
|
-
|
|
2681
|
+
function Separator({ orientation = "horizontal", decorative = true, className }) {
|
|
2682
|
+
const semanticProps = decorative ? { role: "none", "aria-hidden": true } : { role: "separator", "aria-orientation": orientation };
|
|
2683
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2684
|
+
"div",
|
|
2685
|
+
{
|
|
2686
|
+
className: cn(
|
|
2687
|
+
"shrink-0 bg-border",
|
|
2688
|
+
orientation === "horizontal" ? "h-px w-full" : "w-px h-full",
|
|
2689
|
+
className
|
|
2690
|
+
),
|
|
2691
|
+
...semanticProps
|
|
2692
|
+
}
|
|
2693
|
+
);
|
|
2694
|
+
}
|
|
2695
|
+
var PopoverContext = React52__namespace.createContext(null);
|
|
2379
2696
|
function usePopoverContext(part) {
|
|
2380
|
-
const ctx =
|
|
2697
|
+
const ctx = React52__namespace.useContext(PopoverContext);
|
|
2381
2698
|
if (!ctx) throw new Error(`${part} must be used inside <Popover>`);
|
|
2382
2699
|
return ctx;
|
|
2383
2700
|
}
|
|
2384
2701
|
function Popover({ children, className, open: openProp, onOpenChange }) {
|
|
2385
|
-
const [openState, setOpenState] =
|
|
2702
|
+
const [openState, setOpenState] = React52__namespace.useState(false);
|
|
2386
2703
|
const controlled = openProp !== void 0;
|
|
2387
2704
|
const open = controlled ? openProp : openState;
|
|
2388
|
-
const triggerRef =
|
|
2389
|
-
const ref =
|
|
2390
|
-
const setOpen =
|
|
2705
|
+
const triggerRef = React52__namespace.useRef(null);
|
|
2706
|
+
const ref = React52__namespace.useRef(null);
|
|
2707
|
+
const setOpen = React52__namespace.useCallback(
|
|
2391
2708
|
(v) => {
|
|
2392
2709
|
if (!controlled) setOpenState(v);
|
|
2393
2710
|
onOpenChange?.(v);
|
|
2394
2711
|
},
|
|
2395
2712
|
[controlled, onOpenChange]
|
|
2396
2713
|
);
|
|
2397
|
-
|
|
2714
|
+
React52__namespace.useEffect(() => {
|
|
2398
2715
|
if (!open) return;
|
|
2399
2716
|
const onDoc = (e) => {
|
|
2400
2717
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -2414,7 +2731,7 @@ function Popover({ children, className, open: openProp, onOpenChange }) {
|
|
|
2414
2731
|
}, [open, setOpen]);
|
|
2415
2732
|
return /* @__PURE__ */ jsxRuntime.jsx(PopoverContext.Provider, { value: { open, setOpen, triggerRef }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("relative inline-block", className), children }) });
|
|
2416
2733
|
}
|
|
2417
|
-
var PopoverTrigger =
|
|
2734
|
+
var PopoverTrigger = React52__namespace.forwardRef(({ onClick, asChild, ...props }, ref) => {
|
|
2418
2735
|
const ctx = usePopoverContext("PopoverTrigger");
|
|
2419
2736
|
const setRefs = (node) => {
|
|
2420
2737
|
ctx.triggerRef.current = node;
|
|
@@ -2422,8 +2739,8 @@ var PopoverTrigger = React18__namespace.forwardRef(({ onClick, asChild, ...props
|
|
|
2422
2739
|
else if (ref) ref.current = node;
|
|
2423
2740
|
};
|
|
2424
2741
|
if (asChild) {
|
|
2425
|
-
const child =
|
|
2426
|
-
return
|
|
2742
|
+
const child = React52__namespace.Children.only(props.children);
|
|
2743
|
+
return React52__namespace.cloneElement(child, {
|
|
2427
2744
|
ref: setRefs,
|
|
2428
2745
|
...props,
|
|
2429
2746
|
...child.props,
|
|
@@ -2474,8 +2791,8 @@ function PopoverContent({
|
|
|
2474
2791
|
...props
|
|
2475
2792
|
}) {
|
|
2476
2793
|
const ctx = usePopoverContext("PopoverContent");
|
|
2477
|
-
const ref =
|
|
2478
|
-
|
|
2794
|
+
const ref = React52__namespace.useRef(null);
|
|
2795
|
+
React52__namespace.useEffect(() => {
|
|
2479
2796
|
if (ctx.open) ref.current?.focus();
|
|
2480
2797
|
}, [ctx.open]);
|
|
2481
2798
|
if (!ctx.open) return null;
|
|
@@ -2496,15 +2813,3289 @@ function PopoverContent({
|
|
|
2496
2813
|
}
|
|
2497
2814
|
);
|
|
2498
2815
|
}
|
|
2816
|
+
function toArray(v) {
|
|
2817
|
+
if (v == null) return [];
|
|
2818
|
+
return Array.isArray(v) ? v : [v];
|
|
2819
|
+
}
|
|
2820
|
+
var Combobox = React52__namespace.forwardRef(
|
|
2821
|
+
function Combobox2(props, ref) {
|
|
2822
|
+
const {
|
|
2823
|
+
options,
|
|
2824
|
+
placeholder = "Select\u2026",
|
|
2825
|
+
searchPlaceholder = "Search\u2026",
|
|
2826
|
+
emptyMessage = "No results",
|
|
2827
|
+
disabled = false,
|
|
2828
|
+
error = false,
|
|
2829
|
+
required = false,
|
|
2830
|
+
className,
|
|
2831
|
+
id,
|
|
2832
|
+
name,
|
|
2833
|
+
"aria-describedby": describedBy
|
|
2834
|
+
} = props;
|
|
2835
|
+
const multiple = props.multiple ?? false;
|
|
2836
|
+
const reactId = React52__namespace.useId();
|
|
2837
|
+
const baseId = id ?? reactId;
|
|
2838
|
+
const listId = `${baseId}-listbox`;
|
|
2839
|
+
const optionId = (i) => `${baseId}-opt-${i}`;
|
|
2840
|
+
const controlled = props.value !== void 0;
|
|
2841
|
+
const [internal, setInternal] = React52__namespace.useState(() => toArray(props.defaultValue));
|
|
2842
|
+
const selected = controlled ? toArray(props.value) : internal;
|
|
2843
|
+
const [open, setOpen] = React52__namespace.useState(false);
|
|
2844
|
+
const [search, setSearch] = React52__namespace.useState("");
|
|
2845
|
+
const [activeIndex, setActiveIndex] = React52__namespace.useState(0);
|
|
2846
|
+
const containerRef = React52__namespace.useRef(null);
|
|
2847
|
+
const triggerRef = React52__namespace.useRef(null);
|
|
2848
|
+
const inputRef = React52__namespace.useRef(null);
|
|
2849
|
+
const listRef = React52__namespace.useRef(null);
|
|
2850
|
+
const setTriggerRef = (node) => {
|
|
2851
|
+
triggerRef.current = node;
|
|
2852
|
+
if (typeof ref === "function") ref(node);
|
|
2853
|
+
else if (ref) ref.current = node;
|
|
2854
|
+
};
|
|
2855
|
+
const filtered = React52__namespace.useMemo(() => {
|
|
2856
|
+
const q = search.trim().toLowerCase();
|
|
2857
|
+
return q ? options.filter((o) => o.label.toLowerCase().includes(q)) : options;
|
|
2858
|
+
}, [search, options]);
|
|
2859
|
+
const firstEnabled = React52__namespace.useCallback(() => {
|
|
2860
|
+
const i = filtered.findIndex((o) => !o.disabled);
|
|
2861
|
+
return i === -1 ? 0 : i;
|
|
2862
|
+
}, [filtered]);
|
|
2863
|
+
const labelFor = (v) => options.find((o) => o.value === v)?.label ?? v;
|
|
2864
|
+
const emit = (next) => {
|
|
2865
|
+
if (!controlled) setInternal(next);
|
|
2866
|
+
if (props.multiple) {
|
|
2867
|
+
props.onChange?.(next);
|
|
2868
|
+
} else {
|
|
2869
|
+
props.onChange?.(next[0] ?? "");
|
|
2870
|
+
}
|
|
2871
|
+
};
|
|
2872
|
+
const closePopup = React52__namespace.useCallback(() => {
|
|
2873
|
+
setOpen(false);
|
|
2874
|
+
setSearch("");
|
|
2875
|
+
}, []);
|
|
2876
|
+
const openPopup = () => {
|
|
2877
|
+
if (!disabled) setOpen(true);
|
|
2878
|
+
};
|
|
2879
|
+
const handleSelect = (opt) => {
|
|
2880
|
+
if (opt.disabled) return;
|
|
2881
|
+
if (multiple) {
|
|
2882
|
+
const next = selected.includes(opt.value) ? selected.filter((v) => v !== opt.value) : [...selected, opt.value];
|
|
2883
|
+
emit(next);
|
|
2884
|
+
inputRef.current?.focus();
|
|
2885
|
+
} else {
|
|
2886
|
+
emit([opt.value]);
|
|
2887
|
+
closePopup();
|
|
2888
|
+
triggerRef.current?.focus();
|
|
2889
|
+
}
|
|
2890
|
+
};
|
|
2891
|
+
const removeValue = (value) => {
|
|
2892
|
+
emit(selected.filter((v) => v !== value));
|
|
2893
|
+
};
|
|
2894
|
+
React52__namespace.useEffect(() => {
|
|
2895
|
+
if (open) setActiveIndex(firstEnabled());
|
|
2896
|
+
}, [open, firstEnabled]);
|
|
2897
|
+
React52__namespace.useEffect(() => {
|
|
2898
|
+
if (open) inputRef.current?.focus();
|
|
2899
|
+
}, [open]);
|
|
2900
|
+
React52__namespace.useEffect(() => {
|
|
2901
|
+
if (!open) return;
|
|
2902
|
+
const onDown = (e) => {
|
|
2903
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) closePopup();
|
|
2904
|
+
};
|
|
2905
|
+
document.addEventListener("mousedown", onDown);
|
|
2906
|
+
return () => document.removeEventListener("mousedown", onDown);
|
|
2907
|
+
}, [open, closePopup]);
|
|
2908
|
+
React52__namespace.useEffect(() => {
|
|
2909
|
+
const el = listRef.current?.querySelector('[data-active="true"]');
|
|
2910
|
+
el?.scrollIntoView({ block: "nearest" });
|
|
2911
|
+
}, [activeIndex]);
|
|
2912
|
+
const moveActive = (dir) => {
|
|
2913
|
+
if (filtered.length === 0) return;
|
|
2914
|
+
setActiveIndex((prev) => {
|
|
2915
|
+
let i = prev;
|
|
2916
|
+
for (let step = 0; step < filtered.length; step++) {
|
|
2917
|
+
i = (i + dir + filtered.length) % filtered.length;
|
|
2918
|
+
if (!filtered[i]?.disabled) return i;
|
|
2919
|
+
}
|
|
2920
|
+
return prev;
|
|
2921
|
+
});
|
|
2922
|
+
};
|
|
2923
|
+
const onInputKeyDown = (e) => {
|
|
2924
|
+
switch (e.key) {
|
|
2925
|
+
case "ArrowDown":
|
|
2926
|
+
e.preventDefault();
|
|
2927
|
+
moveActive(1);
|
|
2928
|
+
break;
|
|
2929
|
+
case "ArrowUp":
|
|
2930
|
+
e.preventDefault();
|
|
2931
|
+
moveActive(-1);
|
|
2932
|
+
break;
|
|
2933
|
+
case "Home":
|
|
2934
|
+
e.preventDefault();
|
|
2935
|
+
setActiveIndex(firstEnabled());
|
|
2936
|
+
break;
|
|
2937
|
+
case "End":
|
|
2938
|
+
e.preventDefault();
|
|
2939
|
+
for (let i = filtered.length - 1; i >= 0; i--) {
|
|
2940
|
+
if (!filtered[i].disabled) {
|
|
2941
|
+
setActiveIndex(i);
|
|
2942
|
+
break;
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
break;
|
|
2946
|
+
case "Enter":
|
|
2947
|
+
e.preventDefault();
|
|
2948
|
+
if (filtered[activeIndex]) handleSelect(filtered[activeIndex]);
|
|
2949
|
+
break;
|
|
2950
|
+
case "Escape":
|
|
2951
|
+
e.preventDefault();
|
|
2952
|
+
closePopup();
|
|
2953
|
+
triggerRef.current?.focus();
|
|
2954
|
+
break;
|
|
2955
|
+
case "Backspace":
|
|
2956
|
+
if (multiple && search === "" && selected.length > 0) {
|
|
2957
|
+
removeValue(selected[selected.length - 1]);
|
|
2958
|
+
}
|
|
2959
|
+
break;
|
|
2960
|
+
}
|
|
2961
|
+
};
|
|
2962
|
+
const onTriggerKeyDown = (e) => {
|
|
2963
|
+
if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
|
|
2964
|
+
e.preventDefault();
|
|
2965
|
+
openPopup();
|
|
2966
|
+
}
|
|
2967
|
+
};
|
|
2968
|
+
const showPlaceholder = multiple ? selected.length === 0 : !selected[0];
|
|
2969
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: cn("relative w-full", className), children: [
|
|
2970
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2971
|
+
"div",
|
|
2972
|
+
{
|
|
2973
|
+
className: cn(
|
|
2974
|
+
"relative flex w-full items-center gap-1.5 flex-wrap border rounded-kj-md bg-surface",
|
|
2975
|
+
"pl-[0.85rem] pr-9 py-[calc(0.45rem*var(--kj-density,1))] min-h-[calc(2.5rem*var(--kj-density,1))]",
|
|
2976
|
+
"transition-[border-color,box-shadow] duration-150",
|
|
2977
|
+
"focus-within:outline-none focus-within:border-ring focus-within:ring-[3px] focus-within:ring-ring/30",
|
|
2978
|
+
disabled && "bg-muted cursor-not-allowed",
|
|
2979
|
+
error ? "border-danger" : "border-input"
|
|
2980
|
+
),
|
|
2981
|
+
children: [
|
|
2982
|
+
multiple && selected.map((value) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2983
|
+
"span",
|
|
2984
|
+
{
|
|
2985
|
+
className: "inline-flex items-center gap-1 rounded-kj-sm bg-primary/10 text-primary text-xs font-medium pl-2 pr-1 py-0.5",
|
|
2986
|
+
children: [
|
|
2987
|
+
labelFor(value),
|
|
2988
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2989
|
+
"button",
|
|
2990
|
+
{
|
|
2991
|
+
type: "button",
|
|
2992
|
+
"aria-label": `Remove ${labelFor(value)}`,
|
|
2993
|
+
disabled,
|
|
2994
|
+
onClick: (e) => {
|
|
2995
|
+
e.stopPropagation();
|
|
2996
|
+
removeValue(value);
|
|
2997
|
+
},
|
|
2998
|
+
className: "rounded-full p-0.5 leading-none hover:bg-primary/20",
|
|
2999
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", className: "h-3 w-3", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 6l12 12M18 6L6 18" }) })
|
|
3000
|
+
}
|
|
3001
|
+
)
|
|
3002
|
+
]
|
|
3003
|
+
},
|
|
3004
|
+
value
|
|
3005
|
+
)),
|
|
3006
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3007
|
+
"button",
|
|
3008
|
+
{
|
|
3009
|
+
ref: setTriggerRef,
|
|
3010
|
+
type: "button",
|
|
3011
|
+
id,
|
|
3012
|
+
disabled,
|
|
3013
|
+
"aria-haspopup": "listbox",
|
|
3014
|
+
"aria-expanded": open,
|
|
3015
|
+
"aria-controls": open && filtered.length > 0 ? listId : void 0,
|
|
3016
|
+
"aria-invalid": error || void 0,
|
|
3017
|
+
"aria-required": required || void 0,
|
|
3018
|
+
"aria-describedby": describedBy,
|
|
3019
|
+
onClick: () => open ? closePopup() : openPopup(),
|
|
3020
|
+
onKeyDown: onTriggerKeyDown,
|
|
3021
|
+
className: cn(
|
|
3022
|
+
"flex-1 min-w-[60px] text-left bg-transparent border-none outline-none cursor-pointer text-sm disabled:cursor-not-allowed",
|
|
3023
|
+
showPlaceholder && "text-muted-foreground"
|
|
3024
|
+
),
|
|
3025
|
+
children: multiple ? selected.length === 0 ? placeholder : "" : (selected[0] ? labelFor(selected[0]) : "") || placeholder
|
|
3026
|
+
}
|
|
3027
|
+
),
|
|
3028
|
+
name && multiple && selected.map((v) => /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: v }, v)),
|
|
3029
|
+
name && !multiple && /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: selected[0] ?? "" }),
|
|
3030
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" }) }) })
|
|
3031
|
+
]
|
|
3032
|
+
}
|
|
3033
|
+
),
|
|
3034
|
+
open && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute z-40 top-[calc(100%+6px)] left-0 w-full min-w-[12rem] bg-surface border border-border rounded-kj-md shadow-kj-lg overflow-hidden animate-[kjpop_.12s_ease]", children: [
|
|
3035
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 border-b border-border", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3036
|
+
"input",
|
|
3037
|
+
{
|
|
3038
|
+
ref: inputRef,
|
|
3039
|
+
type: "text",
|
|
3040
|
+
role: "combobox",
|
|
3041
|
+
"aria-autocomplete": "list",
|
|
3042
|
+
"aria-expanded": open,
|
|
3043
|
+
"aria-controls": filtered.length > 0 ? listId : void 0,
|
|
3044
|
+
"aria-activedescendant": filtered[activeIndex] ? optionId(activeIndex) : void 0,
|
|
3045
|
+
"aria-label": searchPlaceholder,
|
|
3046
|
+
placeholder: searchPlaceholder,
|
|
3047
|
+
value: search,
|
|
3048
|
+
onChange: (e) => setSearch(e.target.value),
|
|
3049
|
+
onKeyDown: onInputKeyDown,
|
|
3050
|
+
className: "w-full bg-transparent text-sm text-foreground placeholder:text-muted-foreground outline-none px-2 py-1"
|
|
3051
|
+
}
|
|
3052
|
+
) }),
|
|
3053
|
+
filtered.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
3054
|
+
"div",
|
|
3055
|
+
{
|
|
3056
|
+
ref: listRef,
|
|
3057
|
+
id: listId,
|
|
3058
|
+
role: "listbox",
|
|
3059
|
+
"aria-multiselectable": multiple || void 0,
|
|
3060
|
+
"aria-label": placeholder,
|
|
3061
|
+
className: "max-h-60 overflow-y-auto p-1",
|
|
3062
|
+
children: filtered.map((opt, i) => {
|
|
3063
|
+
const isSelected = selected.includes(opt.value);
|
|
3064
|
+
const isActive = i === activeIndex;
|
|
3065
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3066
|
+
"div",
|
|
3067
|
+
{
|
|
3068
|
+
id: optionId(i),
|
|
3069
|
+
role: "option",
|
|
3070
|
+
"aria-selected": isSelected,
|
|
3071
|
+
"aria-disabled": opt.disabled || void 0,
|
|
3072
|
+
"data-active": isActive || void 0,
|
|
3073
|
+
onMouseEnter: () => !opt.disabled && setActiveIndex(i),
|
|
3074
|
+
onClick: () => handleSelect(opt),
|
|
3075
|
+
className: cn(
|
|
3076
|
+
"flex items-center justify-between gap-2 px-3 py-2 rounded-kj-sm text-sm cursor-pointer select-none",
|
|
3077
|
+
opt.disabled && "text-muted-foreground opacity-50 cursor-not-allowed",
|
|
3078
|
+
!opt.disabled && isActive && "bg-primary/10 text-primary",
|
|
3079
|
+
!opt.disabled && !isActive && "text-foreground hover:bg-muted"
|
|
3080
|
+
),
|
|
3081
|
+
children: [
|
|
3082
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: opt.label }),
|
|
3083
|
+
isSelected && /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4 text-primary shrink-0", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m5 12 5 5L20 7" }) })
|
|
3084
|
+
]
|
|
3085
|
+
},
|
|
3086
|
+
opt.value
|
|
3087
|
+
);
|
|
3088
|
+
})
|
|
3089
|
+
}
|
|
3090
|
+
)
|
|
3091
|
+
] })
|
|
3092
|
+
] });
|
|
3093
|
+
}
|
|
3094
|
+
);
|
|
3095
|
+
Combobox.displayName = "Combobox";
|
|
3096
|
+
var ComboboxField = React52__namespace.forwardRef(
|
|
3097
|
+
function ComboboxField2({ label, hint, error, required, className, ...props }, ref) {
|
|
3098
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FormField, { label, hint, error, required, className, children: /* @__PURE__ */ jsxRuntime.jsx(Combobox, { ref, error: !!error, ...props }) });
|
|
3099
|
+
}
|
|
3100
|
+
);
|
|
3101
|
+
ComboboxField.displayName = "ComboboxField";
|
|
3102
|
+
|
|
3103
|
+
// src/components/calendar-internals.ts
|
|
3104
|
+
function startOfDay(d) {
|
|
3105
|
+
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
3106
|
+
}
|
|
3107
|
+
function isSameDay(a, b) {
|
|
3108
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
3109
|
+
}
|
|
3110
|
+
function addDays(d, n) {
|
|
3111
|
+
const r = new Date(d);
|
|
3112
|
+
r.setDate(r.getDate() + n);
|
|
3113
|
+
return r;
|
|
3114
|
+
}
|
|
3115
|
+
function addMonths(d, n) {
|
|
3116
|
+
const r = new Date(d);
|
|
3117
|
+
r.setMonth(r.getMonth() + n);
|
|
3118
|
+
return r;
|
|
3119
|
+
}
|
|
3120
|
+
function clampToMonth(year, month, day) {
|
|
3121
|
+
const daysInTarget = new Date(year, month + 1, 0).getDate();
|
|
3122
|
+
return new Date(year, month, Math.min(day, daysInTarget));
|
|
3123
|
+
}
|
|
3124
|
+
function addMonthsClamped(d, n) {
|
|
3125
|
+
return clampToMonth(d.getFullYear(), d.getMonth() + n, d.getDate());
|
|
3126
|
+
}
|
|
3127
|
+
function addYearsClamped(d, n) {
|
|
3128
|
+
return clampToMonth(d.getFullYear() + n, d.getMonth(), d.getDate());
|
|
3129
|
+
}
|
|
3130
|
+
function startOfMonth(d) {
|
|
3131
|
+
return new Date(d.getFullYear(), d.getMonth(), 1);
|
|
3132
|
+
}
|
|
3133
|
+
function startOfWeek(d) {
|
|
3134
|
+
const r = startOfDay(d);
|
|
3135
|
+
r.setDate(r.getDate() - r.getDay());
|
|
3136
|
+
return r;
|
|
3137
|
+
}
|
|
3138
|
+
function buildGridDays(viewMonth) {
|
|
3139
|
+
const gridStart = startOfWeek(startOfMonth(viewMonth));
|
|
3140
|
+
return Array.from({ length: 42 }, (_, i) => addDays(gridStart, i));
|
|
3141
|
+
}
|
|
3142
|
+
function dateKey(d) {
|
|
3143
|
+
return `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
|
|
3144
|
+
}
|
|
3145
|
+
function toISODateString(d) {
|
|
3146
|
+
const y = d.getFullYear();
|
|
3147
|
+
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
3148
|
+
const day = String(d.getDate()).padStart(2, "0");
|
|
3149
|
+
return `${y}-${m}-${day}`;
|
|
3150
|
+
}
|
|
3151
|
+
var monthLabelFormat = new Intl.DateTimeFormat(void 0, { month: "long", year: "numeric" });
|
|
3152
|
+
var fullDateFormat = new Intl.DateTimeFormat(void 0, { dateStyle: "full" });
|
|
3153
|
+
var weekdayShortFormat = new Intl.DateTimeFormat(void 0, { weekday: "short" });
|
|
3154
|
+
var weekdayLongFormat = new Intl.DateTimeFormat(void 0, { weekday: "long" });
|
|
3155
|
+
var weekdayLabels = Array.from({ length: 7 }, (_, i) => {
|
|
3156
|
+
const d = addDays(startOfWeek(/* @__PURE__ */ new Date()), i);
|
|
3157
|
+
return { key: i, short: weekdayShortFormat.format(d), long: weekdayLongFormat.format(d) };
|
|
3158
|
+
});
|
|
3159
|
+
var CalendarGrid = React52__namespace.forwardRef(function CalendarGrid2({ viewMonth, isDayDisabled, cellState, onSelectDay, onFocusDay, initialFocusDate, className }, ref) {
|
|
3160
|
+
const gridDays = React52__namespace.useMemo(() => buildGridDays(viewMonth), [viewMonth]);
|
|
3161
|
+
const inViewMonth = (d) => d.getMonth() === viewMonth.getMonth() && d.getFullYear() === viewMonth.getFullYear();
|
|
3162
|
+
const [focusedDate, setFocusedDate] = React52__namespace.useState(() => startOfDay(initialFocusDate));
|
|
3163
|
+
const pendingFocusRef = React52__namespace.useRef(false);
|
|
3164
|
+
const gridRef = React52__namespace.useRef(null);
|
|
3165
|
+
const rovingTarget = inViewMonth(focusedDate) && !isDayDisabled(focusedDate) ? focusedDate : gridDays.find((d) => inViewMonth(d) && !isDayDisabled(d)) ?? gridDays.find((d) => inViewMonth(d)) ?? gridDays[0];
|
|
3166
|
+
const moveFocusTo = (next, viaKeyboard) => {
|
|
3167
|
+
pendingFocusRef.current = viaKeyboard;
|
|
3168
|
+
setFocusedDate(next);
|
|
3169
|
+
onFocusDay?.(next);
|
|
3170
|
+
};
|
|
3171
|
+
React52__namespace.useEffect(() => {
|
|
3172
|
+
if (!pendingFocusRef.current) return;
|
|
3173
|
+
pendingFocusRef.current = false;
|
|
3174
|
+
const el = gridRef.current?.querySelector(`[data-date="${dateKey(rovingTarget)}"]`);
|
|
3175
|
+
el?.focus();
|
|
3176
|
+
}, [rovingTarget]);
|
|
3177
|
+
const step = (from, delta) => {
|
|
3178
|
+
let next = addDays(from, delta);
|
|
3179
|
+
let guard = 0;
|
|
3180
|
+
while (isDayDisabled(next) && guard < 1e3) {
|
|
3181
|
+
next = addDays(next, delta);
|
|
3182
|
+
guard++;
|
|
3183
|
+
}
|
|
3184
|
+
return isDayDisabled(next) ? from : next;
|
|
3185
|
+
};
|
|
3186
|
+
const selectDay = (d) => {
|
|
3187
|
+
if (isDayDisabled(d)) return;
|
|
3188
|
+
moveFocusTo(d, false);
|
|
3189
|
+
onSelectDay(d);
|
|
3190
|
+
};
|
|
3191
|
+
const onGridKeyDown = (e) => {
|
|
3192
|
+
switch (e.key) {
|
|
3193
|
+
case "ArrowRight":
|
|
3194
|
+
e.preventDefault();
|
|
3195
|
+
moveFocusTo(step(rovingTarget, 1), true);
|
|
3196
|
+
break;
|
|
3197
|
+
case "ArrowLeft":
|
|
3198
|
+
e.preventDefault();
|
|
3199
|
+
moveFocusTo(step(rovingTarget, -1), true);
|
|
3200
|
+
break;
|
|
3201
|
+
case "ArrowDown":
|
|
3202
|
+
e.preventDefault();
|
|
3203
|
+
moveFocusTo(step(rovingTarget, 7), true);
|
|
3204
|
+
break;
|
|
3205
|
+
case "ArrowUp":
|
|
3206
|
+
e.preventDefault();
|
|
3207
|
+
moveFocusTo(step(rovingTarget, -7), true);
|
|
3208
|
+
break;
|
|
3209
|
+
case "Home": {
|
|
3210
|
+
e.preventDefault();
|
|
3211
|
+
const target = startOfWeek(rovingTarget);
|
|
3212
|
+
moveFocusTo(isDayDisabled(target) ? step(target, 1) : target, true);
|
|
3213
|
+
break;
|
|
3214
|
+
}
|
|
3215
|
+
case "End": {
|
|
3216
|
+
e.preventDefault();
|
|
3217
|
+
const target = addDays(startOfWeek(rovingTarget), 6);
|
|
3218
|
+
moveFocusTo(isDayDisabled(target) ? step(target, -1) : target, true);
|
|
3219
|
+
break;
|
|
3220
|
+
}
|
|
3221
|
+
case "PageUp": {
|
|
3222
|
+
e.preventDefault();
|
|
3223
|
+
const target = e.shiftKey ? addYearsClamped(rovingTarget, -1) : addMonthsClamped(rovingTarget, -1);
|
|
3224
|
+
moveFocusTo(isDayDisabled(target) ? step(target, -1) : target, true);
|
|
3225
|
+
break;
|
|
3226
|
+
}
|
|
3227
|
+
case "PageDown": {
|
|
3228
|
+
e.preventDefault();
|
|
3229
|
+
const target = e.shiftKey ? addYearsClamped(rovingTarget, 1) : addMonthsClamped(rovingTarget, 1);
|
|
3230
|
+
moveFocusTo(isDayDisabled(target) ? step(target, 1) : target, true);
|
|
3231
|
+
break;
|
|
3232
|
+
}
|
|
3233
|
+
case "Enter":
|
|
3234
|
+
case " ":
|
|
3235
|
+
e.preventDefault();
|
|
3236
|
+
selectDay(rovingTarget);
|
|
3237
|
+
break;
|
|
3238
|
+
}
|
|
3239
|
+
};
|
|
3240
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn(className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: gridRef, role: "grid", "aria-label": monthLabelFormat.format(viewMonth), onKeyDown: onGridKeyDown, children: [
|
|
3241
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { role: "row", className: "grid grid-cols-7", children: weekdayLabels.map((w) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3242
|
+
"div",
|
|
3243
|
+
{
|
|
3244
|
+
role: "columnheader",
|
|
3245
|
+
"aria-label": w.long,
|
|
3246
|
+
className: "h-8 flex items-center justify-center text-xs font-medium text-muted-foreground",
|
|
3247
|
+
children: w.short
|
|
3248
|
+
},
|
|
3249
|
+
w.key
|
|
3250
|
+
)) }),
|
|
3251
|
+
Array.from({ length: 6 }, (_, week) => /* @__PURE__ */ jsxRuntime.jsx("div", { role: "row", className: "grid grid-cols-7", children: gridDays.slice(week * 7, week * 7 + 7).map((day) => {
|
|
3252
|
+
if (!inViewMonth(day)) {
|
|
3253
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "gridcell", "aria-hidden": "true", className: "h-9" }, dateKey(day));
|
|
3254
|
+
}
|
|
3255
|
+
const disabled = isDayDisabled(day);
|
|
3256
|
+
const state = cellState(day);
|
|
3257
|
+
const isRoving = isSameDay(day, rovingTarget);
|
|
3258
|
+
const isEndpoint = !!(state.selected || state.rangeStart || state.rangeEnd);
|
|
3259
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3260
|
+
"button",
|
|
3261
|
+
{
|
|
3262
|
+
type: "button",
|
|
3263
|
+
role: "gridcell",
|
|
3264
|
+
"data-date": dateKey(day),
|
|
3265
|
+
tabIndex: isRoving ? 0 : -1,
|
|
3266
|
+
"aria-selected": isEndpoint,
|
|
3267
|
+
"aria-disabled": disabled || void 0,
|
|
3268
|
+
"aria-label": fullDateFormat.format(day),
|
|
3269
|
+
onMouseEnter: () => onFocusDay?.(day),
|
|
3270
|
+
onClick: () => selectDay(day),
|
|
3271
|
+
className: cn(
|
|
3272
|
+
"h-9 w-9 mx-auto flex items-center justify-center text-sm",
|
|
3273
|
+
state.inRange && !isEndpoint ? "rounded-none" : "rounded-full",
|
|
3274
|
+
"focus:outline-none focus:ring-[3px] focus:ring-ring/30",
|
|
3275
|
+
disabled && "text-muted-foreground opacity-40 cursor-not-allowed",
|
|
3276
|
+
!disabled && isEndpoint && "bg-primary text-primary-foreground",
|
|
3277
|
+
!disabled && state.inRange && !isEndpoint && "bg-primary/15 text-foreground",
|
|
3278
|
+
!disabled && !isEndpoint && !state.inRange && state.today && "ring-1 ring-primary text-primary font-medium",
|
|
3279
|
+
!disabled && !isEndpoint && !state.inRange && !state.today && "text-foreground hover:bg-muted"
|
|
3280
|
+
),
|
|
3281
|
+
children: day.getDate()
|
|
3282
|
+
},
|
|
3283
|
+
dateKey(day)
|
|
3284
|
+
);
|
|
3285
|
+
}) }, week))
|
|
3286
|
+
] }) });
|
|
3287
|
+
});
|
|
3288
|
+
CalendarGrid.displayName = "CalendarGrid";
|
|
3289
|
+
var Calendar = React52__namespace.forwardRef(
|
|
3290
|
+
function Calendar2({ value, defaultValue, onChange, month, defaultMonth, onMonthChange, min, max, disabledDates, className }, ref) {
|
|
3291
|
+
const controlled = value !== void 0;
|
|
3292
|
+
const [internalValue, setInternalValue] = React52__namespace.useState(defaultValue);
|
|
3293
|
+
const selected = controlled ? value : internalValue;
|
|
3294
|
+
const monthControlled = month !== void 0;
|
|
3295
|
+
const [internalMonth, setInternalMonth] = React52__namespace.useState(
|
|
3296
|
+
() => startOfMonth(month ?? defaultMonth ?? selected ?? /* @__PURE__ */ new Date())
|
|
3297
|
+
);
|
|
3298
|
+
const viewMonth = monthControlled ? startOfMonth(month) : internalMonth;
|
|
3299
|
+
const setViewMonth = (next) => {
|
|
3300
|
+
const normalized = startOfMonth(next);
|
|
3301
|
+
if (!monthControlled) setInternalMonth(normalized);
|
|
3302
|
+
onMonthChange?.(normalized);
|
|
3303
|
+
};
|
|
3304
|
+
const isDayDisabled = React52__namespace.useCallback(
|
|
3305
|
+
(d) => {
|
|
3306
|
+
if (min && d < startOfDay(min)) return true;
|
|
3307
|
+
if (max && d > startOfDay(max)) return true;
|
|
3308
|
+
return disabledDates?.(d) ?? false;
|
|
3309
|
+
},
|
|
3310
|
+
[min, max, disabledDates]
|
|
3311
|
+
);
|
|
3312
|
+
const commitValue = (d) => {
|
|
3313
|
+
if (!controlled) setInternalValue(d);
|
|
3314
|
+
onChange?.(d);
|
|
3315
|
+
};
|
|
3316
|
+
const today = /* @__PURE__ */ new Date();
|
|
3317
|
+
const cellState = (d) => ({
|
|
3318
|
+
selected: selected ? isSameDay(d, selected) : false,
|
|
3319
|
+
today: isSameDay(d, today)
|
|
3320
|
+
});
|
|
3321
|
+
const inViewMonth = (d) => d.getMonth() === viewMonth.getMonth() && d.getFullYear() === viewMonth.getFullYear();
|
|
3322
|
+
const handleFocusDay = (d) => {
|
|
3323
|
+
if (!inViewMonth(d)) setViewMonth(d);
|
|
3324
|
+
};
|
|
3325
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn("w-[280px] select-none", className), children: [
|
|
3326
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
3327
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3328
|
+
"button",
|
|
3329
|
+
{
|
|
3330
|
+
type: "button",
|
|
3331
|
+
"aria-label": "Previous month",
|
|
3332
|
+
onClick: () => setViewMonth(addMonths(viewMonth, -1)),
|
|
3333
|
+
className: "p-1.5 rounded-kj-sm text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
3334
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" }) })
|
|
3335
|
+
}
|
|
3336
|
+
),
|
|
3337
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-foreground", children: monthLabelFormat.format(viewMonth) }),
|
|
3338
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3339
|
+
"button",
|
|
3340
|
+
{
|
|
3341
|
+
type: "button",
|
|
3342
|
+
"aria-label": "Next month",
|
|
3343
|
+
onClick: () => setViewMonth(addMonths(viewMonth, 1)),
|
|
3344
|
+
className: "p-1.5 rounded-kj-sm text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
3345
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" }) })
|
|
3346
|
+
}
|
|
3347
|
+
)
|
|
3348
|
+
] }),
|
|
3349
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3350
|
+
CalendarGrid,
|
|
3351
|
+
{
|
|
3352
|
+
viewMonth,
|
|
3353
|
+
isDayDisabled,
|
|
3354
|
+
cellState,
|
|
3355
|
+
onSelectDay: commitValue,
|
|
3356
|
+
onFocusDay: handleFocusDay,
|
|
3357
|
+
initialFocusDate: selected ?? /* @__PURE__ */ new Date()
|
|
3358
|
+
}
|
|
3359
|
+
)
|
|
3360
|
+
] });
|
|
3361
|
+
}
|
|
3362
|
+
);
|
|
3363
|
+
Calendar.displayName = "Calendar";
|
|
3364
|
+
var displayFormat = new Intl.DateTimeFormat(void 0, { dateStyle: "medium" });
|
|
3365
|
+
var DatePicker = React52__namespace.forwardRef(
|
|
3366
|
+
function DatePicker2({
|
|
3367
|
+
value,
|
|
3368
|
+
defaultValue,
|
|
3369
|
+
onChange,
|
|
3370
|
+
min,
|
|
3371
|
+
max,
|
|
3372
|
+
disabledDates,
|
|
3373
|
+
placeholder = "Pick a date\u2026",
|
|
3374
|
+
disabled = false,
|
|
3375
|
+
error = false,
|
|
3376
|
+
required = false,
|
|
3377
|
+
className,
|
|
3378
|
+
id,
|
|
3379
|
+
name,
|
|
3380
|
+
"aria-describedby": describedBy
|
|
3381
|
+
}, ref) {
|
|
3382
|
+
const controlled = value !== void 0;
|
|
3383
|
+
const [internalValue, setInternalValue] = React52__namespace.useState(defaultValue);
|
|
3384
|
+
const selected = controlled ? value : internalValue;
|
|
3385
|
+
const [open, setOpen] = React52__namespace.useState(false);
|
|
3386
|
+
const containerRef = React52__namespace.useRef(null);
|
|
3387
|
+
const triggerRef = React52__namespace.useRef(null);
|
|
3388
|
+
const setTriggerRef = (node) => {
|
|
3389
|
+
triggerRef.current = node;
|
|
3390
|
+
if (typeof ref === "function") ref(node);
|
|
3391
|
+
else if (ref) ref.current = node;
|
|
3392
|
+
};
|
|
3393
|
+
const commitValue = (d) => {
|
|
3394
|
+
if (!controlled) setInternalValue(d);
|
|
3395
|
+
onChange?.(d);
|
|
3396
|
+
};
|
|
3397
|
+
const closePopup = React52__namespace.useCallback(() => setOpen(false), []);
|
|
3398
|
+
const openPopup = () => {
|
|
3399
|
+
if (!disabled) setOpen(true);
|
|
3400
|
+
};
|
|
3401
|
+
const handleCalendarChange = (d) => {
|
|
3402
|
+
commitValue(d);
|
|
3403
|
+
closePopup();
|
|
3404
|
+
triggerRef.current?.focus();
|
|
3405
|
+
};
|
|
3406
|
+
React52__namespace.useEffect(() => {
|
|
3407
|
+
if (!open) return;
|
|
3408
|
+
const onDown = (e) => {
|
|
3409
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) closePopup();
|
|
3410
|
+
};
|
|
3411
|
+
document.addEventListener("mousedown", onDown);
|
|
3412
|
+
return () => document.removeEventListener("mousedown", onDown);
|
|
3413
|
+
}, [open, closePopup]);
|
|
3414
|
+
const onTriggerKeyDown = (e) => {
|
|
3415
|
+
if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
|
|
3416
|
+
e.preventDefault();
|
|
3417
|
+
openPopup();
|
|
3418
|
+
} else if (e.key === "Escape" && open) {
|
|
3419
|
+
e.preventDefault();
|
|
3420
|
+
closePopup();
|
|
3421
|
+
}
|
|
3422
|
+
};
|
|
3423
|
+
const onPanelKeyDown = (e) => {
|
|
3424
|
+
if (e.key === "Escape") {
|
|
3425
|
+
e.preventDefault();
|
|
3426
|
+
closePopup();
|
|
3427
|
+
triggerRef.current?.focus();
|
|
3428
|
+
}
|
|
3429
|
+
};
|
|
3430
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: cn("relative inline-block w-full", className), children: [
|
|
3431
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3432
|
+
"button",
|
|
3433
|
+
{
|
|
3434
|
+
ref: setTriggerRef,
|
|
3435
|
+
type: "button",
|
|
3436
|
+
id,
|
|
3437
|
+
disabled,
|
|
3438
|
+
"aria-haspopup": "grid",
|
|
3439
|
+
"aria-expanded": open,
|
|
3440
|
+
"aria-invalid": error || void 0,
|
|
3441
|
+
"aria-required": required || void 0,
|
|
3442
|
+
"aria-describedby": describedBy,
|
|
3443
|
+
onClick: () => open ? closePopup() : openPopup(),
|
|
3444
|
+
onKeyDown: onTriggerKeyDown,
|
|
3445
|
+
className: cn(
|
|
3446
|
+
"w-full flex items-center justify-between gap-2 border rounded-kj-md bg-surface text-left text-sm",
|
|
3447
|
+
"pl-[0.85rem] pr-3 py-[calc(0.6rem*var(--kj-density,1))]",
|
|
3448
|
+
"transition-[border-color,box-shadow] duration-150",
|
|
3449
|
+
"focus:outline-none focus:border-ring focus:ring-[3px] focus:ring-ring/30",
|
|
3450
|
+
disabled && "bg-muted text-muted-foreground cursor-not-allowed",
|
|
3451
|
+
error ? "border-danger" : "border-input",
|
|
3452
|
+
!selected && "text-muted-foreground"
|
|
3453
|
+
),
|
|
3454
|
+
children: [
|
|
3455
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: selected ? displayFormat.format(selected) : placeholder }),
|
|
3456
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3457
|
+
"svg",
|
|
3458
|
+
{
|
|
3459
|
+
viewBox: "0 0 24 24",
|
|
3460
|
+
className: "h-4 w-4 text-muted-foreground shrink-0",
|
|
3461
|
+
fill: "none",
|
|
3462
|
+
stroke: "currentColor",
|
|
3463
|
+
strokeWidth: "2",
|
|
3464
|
+
strokeLinecap: "round",
|
|
3465
|
+
strokeLinejoin: "round",
|
|
3466
|
+
children: [
|
|
3467
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2" }),
|
|
3468
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 10h18M8 2v4M16 2v4" })
|
|
3469
|
+
]
|
|
3470
|
+
}
|
|
3471
|
+
)
|
|
3472
|
+
]
|
|
3473
|
+
}
|
|
3474
|
+
),
|
|
3475
|
+
name && /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: selected ? toISODateString(selected) : "" }),
|
|
3476
|
+
open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3477
|
+
"div",
|
|
3478
|
+
{
|
|
3479
|
+
onKeyDown: onPanelKeyDown,
|
|
3480
|
+
className: "absolute z-40 top-[calc(100%+6px)] left-0 bg-surface border border-border rounded-kj-md shadow-kj-lg p-3 animate-[kjpop_.12s_ease]",
|
|
3481
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Calendar, { value: selected, onChange: handleCalendarChange, min, max, disabledDates })
|
|
3482
|
+
}
|
|
3483
|
+
)
|
|
3484
|
+
] });
|
|
3485
|
+
}
|
|
3486
|
+
);
|
|
3487
|
+
DatePicker.displayName = "DatePicker";
|
|
3488
|
+
var DatePickerField = React52__namespace.forwardRef(
|
|
3489
|
+
function DatePickerField2({ label, hint, error, required, className, ...props }, ref) {
|
|
3490
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FormField, { label, hint, error, required, className, children: /* @__PURE__ */ jsxRuntime.jsx(DatePicker, { ref, error: !!error, ...props }) });
|
|
3491
|
+
}
|
|
3492
|
+
);
|
|
3493
|
+
DatePickerField.displayName = "DatePickerField";
|
|
3494
|
+
function isBetweenExclusive(d, lo, hi) {
|
|
3495
|
+
const t = startOfDay(d).getTime();
|
|
3496
|
+
return t > startOfDay(lo).getTime() && t < startOfDay(hi).getTime();
|
|
3497
|
+
}
|
|
3498
|
+
var RangeCalendar = React52__namespace.forwardRef(
|
|
3499
|
+
function RangeCalendar2({ value, defaultValue, onChange, month, defaultMonth, onMonthChange, min, max, disabledDates, className }, ref) {
|
|
3500
|
+
const controlled = value !== void 0;
|
|
3501
|
+
const [internalValue, setInternalValue] = React52__namespace.useState(defaultValue ?? {});
|
|
3502
|
+
const range2 = controlled ? value : internalValue;
|
|
3503
|
+
const monthControlled = month !== void 0;
|
|
3504
|
+
const [internalMonth, setInternalMonth] = React52__namespace.useState(
|
|
3505
|
+
() => startOfMonth(month ?? defaultMonth ?? range2.start ?? /* @__PURE__ */ new Date())
|
|
3506
|
+
);
|
|
3507
|
+
const leftMonth = monthControlled ? startOfMonth(month) : internalMonth;
|
|
3508
|
+
const rightMonth = addMonths(leftMonth, 1);
|
|
3509
|
+
const setViewMonth = (next) => {
|
|
3510
|
+
const normalized = startOfMonth(next);
|
|
3511
|
+
if (!monthControlled) setInternalMonth(normalized);
|
|
3512
|
+
onMonthChange?.(normalized);
|
|
3513
|
+
};
|
|
3514
|
+
const isDayDisabled = React52__namespace.useCallback(
|
|
3515
|
+
(d) => {
|
|
3516
|
+
if (min && d < startOfDay(min)) return true;
|
|
3517
|
+
if (max && d > startOfDay(max)) return true;
|
|
3518
|
+
return disabledDates?.(d) ?? false;
|
|
3519
|
+
},
|
|
3520
|
+
[min, max, disabledDates]
|
|
3521
|
+
);
|
|
3522
|
+
const [pendingStart, setPendingStart] = React52__namespace.useState(void 0);
|
|
3523
|
+
const [hoverDate, setHoverDate] = React52__namespace.useState(void 0);
|
|
3524
|
+
const commitRange = (next) => {
|
|
3525
|
+
if (!controlled) setInternalValue(next);
|
|
3526
|
+
onChange?.(next);
|
|
3527
|
+
};
|
|
3528
|
+
const handleSelectDay = (d) => {
|
|
3529
|
+
const day = startOfDay(d);
|
|
3530
|
+
if (pendingStart === void 0) {
|
|
3531
|
+
setPendingStart(day);
|
|
3532
|
+
setHoverDate(void 0);
|
|
3533
|
+
return;
|
|
3534
|
+
}
|
|
3535
|
+
if (day < startOfDay(pendingStart)) {
|
|
3536
|
+
setPendingStart(day);
|
|
3537
|
+
setHoverDate(void 0);
|
|
3538
|
+
return;
|
|
3539
|
+
}
|
|
3540
|
+
commitRange({ start: pendingStart, end: day });
|
|
3541
|
+
setPendingStart(void 0);
|
|
3542
|
+
setHoverDate(void 0);
|
|
3543
|
+
};
|
|
3544
|
+
const today = /* @__PURE__ */ new Date();
|
|
3545
|
+
const previewEnd = pendingStart !== void 0 ? hoverDate : void 0;
|
|
3546
|
+
const cellState = (d) => {
|
|
3547
|
+
const isToday = isSameDay(d, today);
|
|
3548
|
+
if (pendingStart !== void 0) {
|
|
3549
|
+
if (previewEnd === void 0) {
|
|
3550
|
+
return { rangeStart: isSameDay(d, pendingStart), today: isToday };
|
|
3551
|
+
}
|
|
3552
|
+
if (startOfDay(previewEnd) < startOfDay(pendingStart)) {
|
|
3553
|
+
return { rangeStart: isSameDay(d, previewEnd), today: isToday };
|
|
3554
|
+
}
|
|
3555
|
+
return {
|
|
3556
|
+
rangeStart: isSameDay(d, pendingStart),
|
|
3557
|
+
rangeEnd: isSameDay(d, previewEnd),
|
|
3558
|
+
inRange: isBetweenExclusive(d, pendingStart, previewEnd),
|
|
3559
|
+
today: isToday
|
|
3560
|
+
};
|
|
3561
|
+
}
|
|
3562
|
+
if (range2.start && range2.end) {
|
|
3563
|
+
return {
|
|
3564
|
+
rangeStart: isSameDay(d, range2.start),
|
|
3565
|
+
rangeEnd: isSameDay(d, range2.end),
|
|
3566
|
+
inRange: isBetweenExclusive(d, range2.start, range2.end),
|
|
3567
|
+
today: isToday
|
|
3568
|
+
};
|
|
3569
|
+
}
|
|
3570
|
+
return { rangeStart: range2.start ? isSameDay(d, range2.start) : false, today: isToday };
|
|
3571
|
+
};
|
|
3572
|
+
const inLockedRange = (d) => d.getMonth() === leftMonth.getMonth() && d.getFullYear() === leftMonth.getFullYear() || d.getMonth() === rightMonth.getMonth() && d.getFullYear() === rightMonth.getFullYear();
|
|
3573
|
+
const handleFocusDay = (d) => {
|
|
3574
|
+
if (pendingStart !== void 0) setHoverDate(d);
|
|
3575
|
+
if (!inLockedRange(d)) setViewMonth(d);
|
|
3576
|
+
};
|
|
3577
|
+
const navButton = (direction) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3578
|
+
"button",
|
|
3579
|
+
{
|
|
3580
|
+
type: "button",
|
|
3581
|
+
"aria-label": direction === "prev" ? "Previous month" : "Next month",
|
|
3582
|
+
onClick: () => setViewMonth(addMonths(leftMonth, direction === "prev" ? -1 : 1)),
|
|
3583
|
+
className: "p-1.5 rounded-kj-sm text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
3584
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: direction === "prev" ? /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" }) : /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" }) })
|
|
3585
|
+
}
|
|
3586
|
+
);
|
|
3587
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn("flex gap-6 select-none", className), children: [
|
|
3588
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-[280px]", children: [
|
|
3589
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
3590
|
+
navButton("prev"),
|
|
3591
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-foreground", children: monthLabelFormat.format(leftMonth) }),
|
|
3592
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-[26px]", "aria-hidden": "true" })
|
|
3593
|
+
] }),
|
|
3594
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3595
|
+
CalendarGrid,
|
|
3596
|
+
{
|
|
3597
|
+
viewMonth: leftMonth,
|
|
3598
|
+
isDayDisabled,
|
|
3599
|
+
cellState,
|
|
3600
|
+
onSelectDay: handleSelectDay,
|
|
3601
|
+
onFocusDay: handleFocusDay,
|
|
3602
|
+
initialFocusDate: pendingStart ?? range2.start ?? /* @__PURE__ */ new Date()
|
|
3603
|
+
}
|
|
3604
|
+
)
|
|
3605
|
+
] }),
|
|
3606
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-[280px]", children: [
|
|
3607
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
3608
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-[26px]", "aria-hidden": "true" }),
|
|
3609
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-foreground", children: monthLabelFormat.format(rightMonth) }),
|
|
3610
|
+
navButton("next")
|
|
3611
|
+
] }),
|
|
3612
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3613
|
+
CalendarGrid,
|
|
3614
|
+
{
|
|
3615
|
+
viewMonth: rightMonth,
|
|
3616
|
+
isDayDisabled,
|
|
3617
|
+
cellState,
|
|
3618
|
+
onSelectDay: handleSelectDay,
|
|
3619
|
+
onFocusDay: handleFocusDay,
|
|
3620
|
+
initialFocusDate: pendingStart ?? range2.start ?? /* @__PURE__ */ new Date()
|
|
3621
|
+
}
|
|
3622
|
+
)
|
|
3623
|
+
] })
|
|
3624
|
+
] });
|
|
3625
|
+
}
|
|
3626
|
+
);
|
|
3627
|
+
RangeCalendar.displayName = "RangeCalendar";
|
|
3628
|
+
var displayFormat2 = new Intl.DateTimeFormat(void 0, { dateStyle: "medium" });
|
|
3629
|
+
function formatRangeLabel(range2) {
|
|
3630
|
+
if (!range2.start || !range2.end) return void 0;
|
|
3631
|
+
return `${displayFormat2.format(range2.start)} \u2013 ${displayFormat2.format(range2.end)}`;
|
|
3632
|
+
}
|
|
3633
|
+
var DateRangePicker = React52__namespace.forwardRef(
|
|
3634
|
+
function DateRangePicker2({
|
|
3635
|
+
value,
|
|
3636
|
+
defaultValue,
|
|
3637
|
+
onChange,
|
|
3638
|
+
min,
|
|
3639
|
+
max,
|
|
3640
|
+
disabledDates,
|
|
3641
|
+
placeholder = "Pick a date range\u2026",
|
|
3642
|
+
disabled = false,
|
|
3643
|
+
error = false,
|
|
3644
|
+
required = false,
|
|
3645
|
+
className,
|
|
3646
|
+
id,
|
|
3647
|
+
name,
|
|
3648
|
+
"aria-describedby": describedBy
|
|
3649
|
+
}, ref) {
|
|
3650
|
+
const controlled = value !== void 0;
|
|
3651
|
+
const [internalValue, setInternalValue] = React52__namespace.useState(defaultValue ?? {});
|
|
3652
|
+
const selected = controlled ? value : internalValue;
|
|
3653
|
+
const [open, setOpen] = React52__namespace.useState(false);
|
|
3654
|
+
const containerRef = React52__namespace.useRef(null);
|
|
3655
|
+
const triggerRef = React52__namespace.useRef(null);
|
|
3656
|
+
const setTriggerRef = (node) => {
|
|
3657
|
+
triggerRef.current = node;
|
|
3658
|
+
if (typeof ref === "function") ref(node);
|
|
3659
|
+
else if (ref) ref.current = node;
|
|
3660
|
+
};
|
|
3661
|
+
const commitValue = (r) => {
|
|
3662
|
+
if (!controlled) setInternalValue(r);
|
|
3663
|
+
onChange?.(r);
|
|
3664
|
+
};
|
|
3665
|
+
const closePopup = React52__namespace.useCallback(() => setOpen(false), []);
|
|
3666
|
+
const openPopup = () => {
|
|
3667
|
+
if (!disabled) setOpen(true);
|
|
3668
|
+
};
|
|
3669
|
+
const handleRangeChange = (r) => {
|
|
3670
|
+
commitValue(r);
|
|
3671
|
+
closePopup();
|
|
3672
|
+
triggerRef.current?.focus();
|
|
3673
|
+
};
|
|
3674
|
+
React52__namespace.useEffect(() => {
|
|
3675
|
+
if (!open) return;
|
|
3676
|
+
const onDown = (e) => {
|
|
3677
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) closePopup();
|
|
3678
|
+
};
|
|
3679
|
+
document.addEventListener("mousedown", onDown);
|
|
3680
|
+
return () => document.removeEventListener("mousedown", onDown);
|
|
3681
|
+
}, [open, closePopup]);
|
|
3682
|
+
const onTriggerKeyDown = (e) => {
|
|
3683
|
+
if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
|
|
3684
|
+
e.preventDefault();
|
|
3685
|
+
openPopup();
|
|
3686
|
+
} else if (e.key === "Escape" && open) {
|
|
3687
|
+
e.preventDefault();
|
|
3688
|
+
closePopup();
|
|
3689
|
+
triggerRef.current?.focus();
|
|
3690
|
+
}
|
|
3691
|
+
};
|
|
3692
|
+
const onPanelKeyDown = (e) => {
|
|
3693
|
+
if (e.key === "Escape") {
|
|
3694
|
+
e.preventDefault();
|
|
3695
|
+
closePopup();
|
|
3696
|
+
triggerRef.current?.focus();
|
|
3697
|
+
}
|
|
3698
|
+
};
|
|
3699
|
+
const label = formatRangeLabel(selected);
|
|
3700
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: cn("relative inline-block w-full", className), children: [
|
|
3701
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3702
|
+
"button",
|
|
3703
|
+
{
|
|
3704
|
+
ref: setTriggerRef,
|
|
3705
|
+
type: "button",
|
|
3706
|
+
id,
|
|
3707
|
+
disabled,
|
|
3708
|
+
"aria-haspopup": "dialog",
|
|
3709
|
+
"aria-expanded": open,
|
|
3710
|
+
"aria-invalid": error || void 0,
|
|
3711
|
+
"aria-required": required || void 0,
|
|
3712
|
+
"aria-describedby": describedBy,
|
|
3713
|
+
onClick: () => open ? closePopup() : openPopup(),
|
|
3714
|
+
onKeyDown: onTriggerKeyDown,
|
|
3715
|
+
className: cn(
|
|
3716
|
+
"w-full flex items-center justify-between gap-2 border rounded-kj-md bg-surface text-left text-sm",
|
|
3717
|
+
"pl-[0.85rem] pr-3 py-[calc(0.6rem*var(--kj-density,1))]",
|
|
3718
|
+
"transition-[border-color,box-shadow] duration-150",
|
|
3719
|
+
"focus:outline-none focus:border-ring focus:ring-[3px] focus:ring-ring/30",
|
|
3720
|
+
disabled && "bg-muted text-muted-foreground cursor-not-allowed",
|
|
3721
|
+
error ? "border-danger" : "border-input",
|
|
3722
|
+
!label && "text-muted-foreground"
|
|
3723
|
+
),
|
|
3724
|
+
children: [
|
|
3725
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: label ?? placeholder }),
|
|
3726
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3727
|
+
"svg",
|
|
3728
|
+
{
|
|
3729
|
+
viewBox: "0 0 24 24",
|
|
3730
|
+
className: "h-4 w-4 text-muted-foreground shrink-0",
|
|
3731
|
+
fill: "none",
|
|
3732
|
+
stroke: "currentColor",
|
|
3733
|
+
strokeWidth: "2",
|
|
3734
|
+
strokeLinecap: "round",
|
|
3735
|
+
strokeLinejoin: "round",
|
|
3736
|
+
children: [
|
|
3737
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2" }),
|
|
3738
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 10h18M8 2v4M16 2v4" })
|
|
3739
|
+
]
|
|
3740
|
+
}
|
|
3741
|
+
)
|
|
3742
|
+
]
|
|
3743
|
+
}
|
|
3744
|
+
),
|
|
3745
|
+
name && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3746
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name: `${name}Start`, value: selected.start ? toISODateString(selected.start) : "" }),
|
|
3747
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name: `${name}End`, value: selected.end ? toISODateString(selected.end) : "" })
|
|
3748
|
+
] }),
|
|
3749
|
+
open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3750
|
+
"div",
|
|
3751
|
+
{
|
|
3752
|
+
onKeyDown: onPanelKeyDown,
|
|
3753
|
+
className: "absolute z-40 top-[calc(100%+6px)] left-0 bg-surface border border-border rounded-kj-md shadow-kj-lg p-3 animate-[kjpop_.12s_ease]",
|
|
3754
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(RangeCalendar, { value: selected, onChange: handleRangeChange, min, max, disabledDates })
|
|
3755
|
+
}
|
|
3756
|
+
)
|
|
3757
|
+
] });
|
|
3758
|
+
}
|
|
3759
|
+
);
|
|
3760
|
+
DateRangePicker.displayName = "DateRangePicker";
|
|
3761
|
+
var DateRangePickerField = React52__namespace.forwardRef(
|
|
3762
|
+
function DateRangePickerField2({ label, hint, error, required, className, ...props }, ref) {
|
|
3763
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FormField, { label, hint, error, required, className, children: /* @__PURE__ */ jsxRuntime.jsx(DateRangePicker, { ref, error: !!error, ...props }) });
|
|
3764
|
+
}
|
|
3765
|
+
);
|
|
3766
|
+
DateRangePickerField.displayName = "DateRangePickerField";
|
|
3767
|
+
var Dropzone = React52__namespace.forwardRef(
|
|
3768
|
+
function Dropzone2({
|
|
3769
|
+
onFiles,
|
|
3770
|
+
accept,
|
|
3771
|
+
multiple = true,
|
|
3772
|
+
disabled = false,
|
|
3773
|
+
className,
|
|
3774
|
+
children,
|
|
3775
|
+
id,
|
|
3776
|
+
"aria-describedby": describedBy,
|
|
3777
|
+
"aria-invalid": ariaInvalid,
|
|
3778
|
+
"aria-required": ariaRequired
|
|
3779
|
+
}, ref) {
|
|
3780
|
+
const inputRef = React52__namespace.useRef(null);
|
|
3781
|
+
const [dragActive, setDragActive] = React52__namespace.useState(false);
|
|
3782
|
+
const dragCounter = React52__namespace.useRef(0);
|
|
3783
|
+
const invalid = ariaInvalid === true || ariaInvalid === "true";
|
|
3784
|
+
const openPicker = () => {
|
|
3785
|
+
if (!disabled) inputRef.current?.click();
|
|
3786
|
+
};
|
|
3787
|
+
const handleInputChange = (e) => {
|
|
3788
|
+
const files = e.target.files ? Array.from(e.target.files) : [];
|
|
3789
|
+
if (files.length > 0) onFiles(files);
|
|
3790
|
+
e.target.value = "";
|
|
3791
|
+
};
|
|
3792
|
+
const handleDragEnter = (e) => {
|
|
3793
|
+
e.preventDefault();
|
|
3794
|
+
if (disabled) return;
|
|
3795
|
+
dragCounter.current += 1;
|
|
3796
|
+
setDragActive(true);
|
|
3797
|
+
};
|
|
3798
|
+
const handleDragOver = (e) => {
|
|
3799
|
+
e.preventDefault();
|
|
3800
|
+
};
|
|
3801
|
+
const handleDragLeave = (e) => {
|
|
3802
|
+
e.preventDefault();
|
|
3803
|
+
if (disabled) return;
|
|
3804
|
+
dragCounter.current -= 1;
|
|
3805
|
+
if (dragCounter.current <= 0) {
|
|
3806
|
+
dragCounter.current = 0;
|
|
3807
|
+
setDragActive(false);
|
|
3808
|
+
}
|
|
3809
|
+
};
|
|
3810
|
+
const handleDrop = (e) => {
|
|
3811
|
+
e.preventDefault();
|
|
3812
|
+
dragCounter.current = 0;
|
|
3813
|
+
setDragActive(false);
|
|
3814
|
+
if (disabled) return;
|
|
3815
|
+
const files = e.dataTransfer?.files ? Array.from(e.dataTransfer.files) : [];
|
|
3816
|
+
if (files.length > 0) onFiles(files);
|
|
3817
|
+
};
|
|
3818
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full", className), children: [
|
|
3819
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3820
|
+
"button",
|
|
3821
|
+
{
|
|
3822
|
+
ref,
|
|
3823
|
+
type: "button",
|
|
3824
|
+
id,
|
|
3825
|
+
disabled,
|
|
3826
|
+
"aria-describedby": describedBy,
|
|
3827
|
+
"aria-invalid": ariaInvalid,
|
|
3828
|
+
"aria-required": ariaRequired,
|
|
3829
|
+
"data-drag-active": dragActive || void 0,
|
|
3830
|
+
onClick: openPicker,
|
|
3831
|
+
onDragEnter: handleDragEnter,
|
|
3832
|
+
onDragOver: handleDragOver,
|
|
3833
|
+
onDragLeave: handleDragLeave,
|
|
3834
|
+
onDrop: handleDrop,
|
|
3835
|
+
className: cn(
|
|
3836
|
+
"w-full flex flex-col items-center justify-center gap-2 rounded-kj-md border-2 border-dashed px-6 py-8 text-center text-sm transition-colors",
|
|
3837
|
+
"focus:outline-none focus:ring-[3px] focus:ring-ring/30",
|
|
3838
|
+
disabled ? "border-input bg-muted text-muted-foreground cursor-not-allowed" : dragActive ? "border-primary bg-primary/5 text-foreground cursor-pointer" : invalid ? "border-danger bg-surface text-muted-foreground hover:text-foreground cursor-pointer" : "border-input bg-surface text-muted-foreground hover:border-primary hover:text-foreground cursor-pointer"
|
|
3839
|
+
),
|
|
3840
|
+
children: children ?? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3841
|
+
/* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", className: "h-7 w-7", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
3842
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 16V4M7 9l5-5 5 5" }),
|
|
3843
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 16v3a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-3" })
|
|
3844
|
+
] }),
|
|
3845
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
3846
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-foreground", children: "Drag and drop files here" }),
|
|
3847
|
+
", or click to browse"
|
|
3848
|
+
] })
|
|
3849
|
+
] })
|
|
3850
|
+
}
|
|
3851
|
+
),
|
|
3852
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3853
|
+
"input",
|
|
3854
|
+
{
|
|
3855
|
+
ref: inputRef,
|
|
3856
|
+
type: "file",
|
|
3857
|
+
accept,
|
|
3858
|
+
multiple,
|
|
3859
|
+
disabled,
|
|
3860
|
+
onChange: handleInputChange,
|
|
3861
|
+
className: "sr-only",
|
|
3862
|
+
tabIndex: -1,
|
|
3863
|
+
"aria-hidden": "true"
|
|
3864
|
+
}
|
|
3865
|
+
)
|
|
3866
|
+
] });
|
|
3867
|
+
}
|
|
3868
|
+
);
|
|
3869
|
+
Dropzone.displayName = "Dropzone";
|
|
3870
|
+
|
|
3871
|
+
// src/components/file-upload-internals.ts
|
|
3872
|
+
var KB = 1024;
|
|
3873
|
+
function formatBytes(bytes) {
|
|
3874
|
+
if (bytes < KB) return `${bytes} B`;
|
|
3875
|
+
const units = ["KB", "MB", "GB", "TB"];
|
|
3876
|
+
let value = bytes / KB;
|
|
3877
|
+
let unitIndex = 0;
|
|
3878
|
+
while (value >= KB && unitIndex < units.length - 1) {
|
|
3879
|
+
value /= KB;
|
|
3880
|
+
unitIndex++;
|
|
3881
|
+
}
|
|
3882
|
+
return `${value.toFixed(1)} ${units[unitIndex]}`;
|
|
3883
|
+
}
|
|
3884
|
+
function matchesAccept(file, accept) {
|
|
3885
|
+
if (!accept || accept.trim() === "") return true;
|
|
3886
|
+
const tokens = accept.split(",").map((t) => t.trim()).filter(Boolean);
|
|
3887
|
+
if (tokens.length === 0) return true;
|
|
3888
|
+
const fileType = file.type.toLowerCase();
|
|
3889
|
+
const fileName = file.name.toLowerCase();
|
|
3890
|
+
return tokens.some((token) => {
|
|
3891
|
+
const t = token.toLowerCase();
|
|
3892
|
+
if (t.startsWith(".")) return fileName.endsWith(t);
|
|
3893
|
+
if (t.endsWith("/*")) return fileType.startsWith(t.slice(0, -1));
|
|
3894
|
+
return fileType === t;
|
|
3895
|
+
});
|
|
3896
|
+
}
|
|
3897
|
+
var idCounter = 0;
|
|
3898
|
+
function generateId() {
|
|
3899
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
3900
|
+
return crypto.randomUUID();
|
|
3901
|
+
}
|
|
3902
|
+
idCounter += 1;
|
|
3903
|
+
return `file-${Date.now().toString(36)}-${idCounter}-${Math.random().toString(36).slice(2, 8)}`;
|
|
3904
|
+
}
|
|
3905
|
+
function validateFiles(files, { accept, maxSize, maxFiles, existingCount = 0, multiple = true }) {
|
|
3906
|
+
const accepted = [];
|
|
3907
|
+
const rejected = [];
|
|
3908
|
+
const effectiveExisting = multiple ? existingCount : 0;
|
|
3909
|
+
for (const file of files) {
|
|
3910
|
+
if (!matchesAccept(file, accept)) {
|
|
3911
|
+
rejected.push({ file, reason: "type" });
|
|
3912
|
+
continue;
|
|
3913
|
+
}
|
|
3914
|
+
if (maxSize != null && file.size > maxSize) {
|
|
3915
|
+
rejected.push({ file, reason: "size" });
|
|
3916
|
+
continue;
|
|
3917
|
+
}
|
|
3918
|
+
if (!multiple) {
|
|
3919
|
+
if (accepted.length === 0) accepted.push(file);
|
|
3920
|
+
else rejected.push({ file, reason: "count" });
|
|
3921
|
+
continue;
|
|
3922
|
+
}
|
|
3923
|
+
const capacity = maxFiles != null ? maxFiles - effectiveExisting - accepted.length : Infinity;
|
|
3924
|
+
if (capacity <= 0) {
|
|
3925
|
+
rejected.push({ file, reason: "count" });
|
|
3926
|
+
continue;
|
|
3927
|
+
}
|
|
3928
|
+
accepted.push(file);
|
|
3929
|
+
}
|
|
3930
|
+
return { accepted, rejected };
|
|
3931
|
+
}
|
|
3932
|
+
function FileIcon({ className }) {
|
|
3933
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", className, fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
3934
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
|
|
3935
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M14 2v6h6" })
|
|
3936
|
+
] });
|
|
3937
|
+
}
|
|
3938
|
+
var FileUpload = React52__namespace.forwardRef(
|
|
3939
|
+
function FileUpload2({
|
|
3940
|
+
value,
|
|
3941
|
+
defaultValue,
|
|
3942
|
+
onChange,
|
|
3943
|
+
onReject,
|
|
3944
|
+
accept,
|
|
3945
|
+
maxSize,
|
|
3946
|
+
maxFiles,
|
|
3947
|
+
multiple = true,
|
|
3948
|
+
disabled = false,
|
|
3949
|
+
error = false,
|
|
3950
|
+
required = false,
|
|
3951
|
+
className,
|
|
3952
|
+
id,
|
|
3953
|
+
"aria-describedby": describedBy
|
|
3954
|
+
}, ref) {
|
|
3955
|
+
const controlled = value !== void 0;
|
|
3956
|
+
const [internalItems, setInternalItems] = React52__namespace.useState(defaultValue ?? []);
|
|
3957
|
+
const items = controlled ? value : internalItems;
|
|
3958
|
+
const commit = (next) => {
|
|
3959
|
+
if (!controlled) setInternalItems(next);
|
|
3960
|
+
onChange?.(next);
|
|
3961
|
+
};
|
|
3962
|
+
const handleFiles = (files) => {
|
|
3963
|
+
const { accepted, rejected } = validateFiles(files, {
|
|
3964
|
+
accept,
|
|
3965
|
+
maxSize,
|
|
3966
|
+
maxFiles,
|
|
3967
|
+
existingCount: items.length,
|
|
3968
|
+
multiple
|
|
3969
|
+
});
|
|
3970
|
+
if (rejected.length > 0) onReject?.(rejected);
|
|
3971
|
+
if (accepted.length === 0) return;
|
|
3972
|
+
const newItems = accepted.map((file) => ({
|
|
3973
|
+
id: generateId(),
|
|
3974
|
+
file,
|
|
3975
|
+
status: "pending"
|
|
3976
|
+
}));
|
|
3977
|
+
commit(multiple ? [...items, ...newItems] : newItems.slice(0, 1));
|
|
3978
|
+
};
|
|
3979
|
+
const removeItem = (itemId) => {
|
|
3980
|
+
commit(items.filter((it) => it.id !== itemId));
|
|
3981
|
+
};
|
|
3982
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full flex flex-col gap-3", className), children: [
|
|
3983
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3984
|
+
Dropzone,
|
|
3985
|
+
{
|
|
3986
|
+
ref,
|
|
3987
|
+
onFiles: handleFiles,
|
|
3988
|
+
accept,
|
|
3989
|
+
multiple,
|
|
3990
|
+
disabled,
|
|
3991
|
+
id,
|
|
3992
|
+
"aria-describedby": describedBy,
|
|
3993
|
+
"aria-invalid": error || void 0,
|
|
3994
|
+
"aria-required": required || void 0
|
|
3995
|
+
}
|
|
3996
|
+
),
|
|
3997
|
+
items.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col gap-2", children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3998
|
+
"li",
|
|
3999
|
+
{
|
|
4000
|
+
className: "flex items-center gap-3 rounded-kj-md border border-border bg-surface px-3 py-2",
|
|
4001
|
+
children: [
|
|
4002
|
+
/* @__PURE__ */ jsxRuntime.jsx(FileIcon, { className: "h-5 w-5 shrink-0 text-muted-foreground" }),
|
|
4003
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
4004
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
4005
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm text-foreground", children: item.file.name }),
|
|
4006
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-xs text-muted-foreground", children: formatBytes(item.file.size) })
|
|
4007
|
+
] }),
|
|
4008
|
+
item.status === "uploading" && item.progress != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1.5 flex items-center gap-2", children: [
|
|
4009
|
+
/* @__PURE__ */ jsxRuntime.jsx(Progress, { value: item.progress, className: "h-1.5" }),
|
|
4010
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
|
|
4011
|
+
Math.round(item.progress),
|
|
4012
|
+
"%"
|
|
4013
|
+
] })
|
|
4014
|
+
] }),
|
|
4015
|
+
item.status === "success" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5 block text-xs text-success", children: "Uploaded" }),
|
|
4016
|
+
item.status === "error" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5 block text-xs text-danger", children: item.error ?? "Upload failed" })
|
|
4017
|
+
] }),
|
|
4018
|
+
!disabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4019
|
+
"button",
|
|
4020
|
+
{
|
|
4021
|
+
type: "button",
|
|
4022
|
+
"aria-label": `Remove ${item.file.name}`,
|
|
4023
|
+
onClick: () => removeItem(item.id),
|
|
4024
|
+
className: "shrink-0 rounded-kj-sm p-1 text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
4025
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
|
|
4026
|
+
}
|
|
4027
|
+
)
|
|
4028
|
+
]
|
|
4029
|
+
},
|
|
4030
|
+
item.id
|
|
4031
|
+
)) })
|
|
4032
|
+
] });
|
|
4033
|
+
}
|
|
4034
|
+
);
|
|
4035
|
+
FileUpload.displayName = "FileUpload";
|
|
4036
|
+
var FileUploadField = React52__namespace.forwardRef(
|
|
4037
|
+
function FileUploadField2({ label, hint, error, required, className, ...props }, ref) {
|
|
4038
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FormField, { label, hint, error, required, className, children: /* @__PURE__ */ jsxRuntime.jsx(FileUpload, { ref, error: !!error, ...props }) });
|
|
4039
|
+
}
|
|
4040
|
+
);
|
|
4041
|
+
FileUploadField.displayName = "FileUploadField";
|
|
4042
|
+
var TimelineContext = React52__namespace.createContext(null);
|
|
4043
|
+
var TimelineItemContext = React52__namespace.createContext(null);
|
|
4044
|
+
var Timeline = React52__namespace.forwardRef(
|
|
4045
|
+
({ align = "left", className, children, ...props }, ref) => {
|
|
4046
|
+
const validChildren = React52__namespace.Children.toArray(children).filter(React52__namespace.isValidElement);
|
|
4047
|
+
const count = validChildren.length;
|
|
4048
|
+
const childrenWithIndex = validChildren.map((child, index) => {
|
|
4049
|
+
return React52__namespace.cloneElement(child, {
|
|
4050
|
+
index
|
|
4051
|
+
});
|
|
4052
|
+
});
|
|
4053
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TimelineContext.Provider, { value: { align, count }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4054
|
+
"div",
|
|
4055
|
+
{
|
|
4056
|
+
ref,
|
|
4057
|
+
role: "list",
|
|
4058
|
+
className: cn("flex flex-col gap-6 w-full", className),
|
|
4059
|
+
...props,
|
|
4060
|
+
children: childrenWithIndex
|
|
4061
|
+
}
|
|
4062
|
+
) });
|
|
4063
|
+
}
|
|
4064
|
+
);
|
|
4065
|
+
Timeline.displayName = "Timeline";
|
|
4066
|
+
var TimelineItem = React52__namespace.forwardRef(
|
|
4067
|
+
({ className, index = 0, children, ...props }, ref) => {
|
|
4068
|
+
const ctx = React52__namespace.useContext(TimelineContext);
|
|
4069
|
+
if (!ctx) throw new Error("TimelineItem must be used within a Timeline");
|
|
4070
|
+
const { align, count } = ctx;
|
|
4071
|
+
const isEven = index % 2 === 0;
|
|
4072
|
+
const isLast = index === count - 1;
|
|
4073
|
+
const gridClass = cn(
|
|
4074
|
+
"grid w-full gap-4 items-start group/timeline-item",
|
|
4075
|
+
align === "left" && "grid-cols-[auto_1fr]",
|
|
4076
|
+
align === "right" && "grid-cols-[1fr_auto] text-right",
|
|
4077
|
+
align === "alternate" && "md:grid-cols-[1fr_auto_1fr] grid-cols-[auto_1fr]"
|
|
4078
|
+
);
|
|
4079
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TimelineItemContext.Provider, { value: { isEven, align, isLast }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4080
|
+
"div",
|
|
4081
|
+
{
|
|
4082
|
+
ref,
|
|
4083
|
+
role: "listitem",
|
|
4084
|
+
className: cn(gridClass, className),
|
|
4085
|
+
...props,
|
|
4086
|
+
children
|
|
4087
|
+
}
|
|
4088
|
+
) });
|
|
4089
|
+
}
|
|
4090
|
+
);
|
|
4091
|
+
TimelineItem.displayName = "TimelineItem";
|
|
4092
|
+
var TimelineSeparator = React52__namespace.forwardRef(
|
|
4093
|
+
({ className, align: propAlign, ...props }, ref) => {
|
|
4094
|
+
const ctx = React52__namespace.useContext(TimelineItemContext);
|
|
4095
|
+
const align = propAlign ?? ctx?.align ?? "left";
|
|
4096
|
+
const separatorClass = cn(
|
|
4097
|
+
"flex flex-col items-center justify-self-center h-full min-h-[40px]",
|
|
4098
|
+
align === "alternate" && "md:col-start-2 col-start-1",
|
|
4099
|
+
align === "left" && "col-start-1",
|
|
4100
|
+
align === "right" && "col-start-2",
|
|
4101
|
+
className
|
|
4102
|
+
);
|
|
4103
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: separatorClass, ...props });
|
|
4104
|
+
}
|
|
4105
|
+
);
|
|
4106
|
+
TimelineSeparator.displayName = "TimelineSeparator";
|
|
4107
|
+
var TimelineConnector = React52__namespace.forwardRef(
|
|
4108
|
+
({ className, dashed, ...props }, ref) => {
|
|
4109
|
+
const ctx = React52__namespace.useContext(TimelineItemContext);
|
|
4110
|
+
const isLast = ctx?.isLast ?? false;
|
|
4111
|
+
const connectorClass = cn(
|
|
4112
|
+
"grow",
|
|
4113
|
+
isLast && "hidden",
|
|
4114
|
+
dashed ? "w-0 border-l border-dashed border-border" : "w-0.5 bg-border",
|
|
4115
|
+
className
|
|
4116
|
+
);
|
|
4117
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: connectorClass, ...props });
|
|
4118
|
+
}
|
|
4119
|
+
);
|
|
4120
|
+
TimelineConnector.displayName = "TimelineConnector";
|
|
4121
|
+
var TimelineDot = React52__namespace.forwardRef(
|
|
4122
|
+
({ className, variant = "default", size = "md", ...props }, ref) => {
|
|
4123
|
+
const sizeClasses2 = {
|
|
4124
|
+
sm: "w-2.5 h-2.5 rounded-full my-1.5",
|
|
4125
|
+
md: "w-4 h-4 rounded-full my-1 border-2 bg-background border-border",
|
|
4126
|
+
lg: "w-8 h-8 rounded-full border flex items-center justify-center bg-background text-[0.8rem]"
|
|
4127
|
+
};
|
|
4128
|
+
const variantClasses = {
|
|
4129
|
+
default: "border-border text-muted-foreground",
|
|
4130
|
+
primary: "border-primary bg-primary/5 text-primary",
|
|
4131
|
+
secondary: "border-secondary bg-secondary/5 text-secondary",
|
|
4132
|
+
success: "border-success bg-success-surface text-success",
|
|
4133
|
+
warning: "border-warning bg-warning-surface text-warning",
|
|
4134
|
+
danger: "border-danger bg-danger-surface text-danger"
|
|
4135
|
+
};
|
|
4136
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4137
|
+
"div",
|
|
4138
|
+
{
|
|
4139
|
+
ref,
|
|
4140
|
+
className: cn(
|
|
4141
|
+
"shrink-0 select-none",
|
|
4142
|
+
sizeClasses2[size],
|
|
4143
|
+
variantClasses[variant],
|
|
4144
|
+
className
|
|
4145
|
+
),
|
|
4146
|
+
...props
|
|
4147
|
+
}
|
|
4148
|
+
);
|
|
4149
|
+
}
|
|
4150
|
+
);
|
|
4151
|
+
TimelineDot.displayName = "TimelineDot";
|
|
4152
|
+
var TimelineContent = React52__namespace.forwardRef(
|
|
4153
|
+
({ className, isEven: propIsEven, align: propAlign, ...props }, ref) => {
|
|
4154
|
+
const ctx = React52__namespace.useContext(TimelineItemContext);
|
|
4155
|
+
const isEven = propIsEven ?? ctx?.isEven ?? false;
|
|
4156
|
+
const align = propAlign ?? ctx?.align ?? "left";
|
|
4157
|
+
const contentClass = cn(
|
|
4158
|
+
"pb-8 flex flex-col gap-1 w-full",
|
|
4159
|
+
align === "left" && "col-start-2 text-left",
|
|
4160
|
+
align === "right" && "col-start-1 text-right",
|
|
4161
|
+
align === "alternate" && (isEven ? "md:col-start-3 col-start-2 text-left" : "md:col-start-1 col-start-2 md:text-right text-left"),
|
|
4162
|
+
className
|
|
4163
|
+
);
|
|
4164
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: contentClass, ...props });
|
|
4165
|
+
}
|
|
4166
|
+
);
|
|
4167
|
+
TimelineContent.displayName = "TimelineContent";
|
|
4168
|
+
var TimelineTitle = React52__namespace.forwardRef(
|
|
4169
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4170
|
+
"h4",
|
|
4171
|
+
{
|
|
4172
|
+
ref,
|
|
4173
|
+
className: cn("m-0 text-sm font-semibold tracking-[-0.01em] text-foreground", className),
|
|
4174
|
+
...props,
|
|
4175
|
+
children
|
|
4176
|
+
}
|
|
4177
|
+
)
|
|
4178
|
+
);
|
|
4179
|
+
TimelineTitle.displayName = "TimelineTitle";
|
|
4180
|
+
var TimelineTime = React52__namespace.forwardRef(
|
|
4181
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4182
|
+
"time",
|
|
4183
|
+
{
|
|
4184
|
+
ref,
|
|
4185
|
+
className: cn("text-[0.75rem] text-muted-foreground font-normal", className),
|
|
4186
|
+
...props
|
|
4187
|
+
}
|
|
4188
|
+
)
|
|
4189
|
+
);
|
|
4190
|
+
TimelineTime.displayName = "TimelineTime";
|
|
4191
|
+
function useStepper({ initialStep = 0, stepsCount }) {
|
|
4192
|
+
const safeStepsCount = Math.max(1, stepsCount);
|
|
4193
|
+
const [activeStep, setActiveStep] = React52__namespace.useState(initialStep);
|
|
4194
|
+
const [completedSteps, setCompletedSteps] = React52__namespace.useState([]);
|
|
4195
|
+
const setStep = React52__namespace.useCallback((step) => {
|
|
4196
|
+
if (step >= 0 && step < safeStepsCount) {
|
|
4197
|
+
setActiveStep(step);
|
|
4198
|
+
}
|
|
4199
|
+
}, [safeStepsCount]);
|
|
4200
|
+
const nextStep = React52__namespace.useCallback(() => {
|
|
4201
|
+
setActiveStep((prev) => Math.min(prev + 1, safeStepsCount - 1));
|
|
4202
|
+
}, [safeStepsCount]);
|
|
4203
|
+
const prevStep = React52__namespace.useCallback(() => {
|
|
4204
|
+
setActiveStep((prev) => Math.max(prev - 1, 0));
|
|
4205
|
+
}, []);
|
|
4206
|
+
const completeStep = React52__namespace.useCallback((step) => {
|
|
4207
|
+
setCompletedSteps((prev) => {
|
|
4208
|
+
if (step < 0 || step >= safeStepsCount) return prev;
|
|
4209
|
+
if (prev.includes(step)) return prev;
|
|
4210
|
+
return [...prev, step].sort((a, b) => a - b);
|
|
4211
|
+
});
|
|
4212
|
+
}, [safeStepsCount]);
|
|
4213
|
+
const uncompleteStep = React52__namespace.useCallback((step) => {
|
|
4214
|
+
setCompletedSteps((prev) => prev.filter((s) => s !== step));
|
|
4215
|
+
}, []);
|
|
4216
|
+
const reset = React52__namespace.useCallback(() => {
|
|
4217
|
+
setActiveStep(initialStep);
|
|
4218
|
+
setCompletedSteps([]);
|
|
4219
|
+
}, [initialStep]);
|
|
4220
|
+
return {
|
|
4221
|
+
activeStep,
|
|
4222
|
+
completedSteps,
|
|
4223
|
+
setStep,
|
|
4224
|
+
nextStep,
|
|
4225
|
+
prevStep,
|
|
4226
|
+
completeStep,
|
|
4227
|
+
uncompleteStep,
|
|
4228
|
+
reset,
|
|
4229
|
+
isFirstStep: activeStep === 0,
|
|
4230
|
+
isLastStep: activeStep === safeStepsCount - 1
|
|
4231
|
+
};
|
|
4232
|
+
}
|
|
4233
|
+
var StepperContext = React52__namespace.createContext(null);
|
|
4234
|
+
var StepperItemContext = React52__namespace.createContext(null);
|
|
4235
|
+
var Stepper = React52__namespace.forwardRef(
|
|
4236
|
+
({ value, defaultValue, onValueChange, orientation = "horizontal", linear = true, children, className, ...props }, ref) => {
|
|
4237
|
+
const [localValue, setLocalValue] = React52__namespace.useState(defaultValue ?? 0);
|
|
4238
|
+
const isControlled = value !== void 0;
|
|
4239
|
+
const activeStep = isControlled ? value : localValue;
|
|
4240
|
+
const [steps, setSteps] = React52__namespace.useState([]);
|
|
4241
|
+
const [completedSteps, setCompletedSteps] = React52__namespace.useState([]);
|
|
4242
|
+
const registerStep = React52__namespace.useCallback((val) => {
|
|
4243
|
+
setSteps((prev) => prev.includes(val) ? prev : [...prev, val].sort((a, b) => a - b));
|
|
4244
|
+
}, []);
|
|
4245
|
+
const unregisterStep = React52__namespace.useCallback((val) => {
|
|
4246
|
+
setSteps((prev) => prev.filter((v) => v !== val));
|
|
4247
|
+
}, []);
|
|
4248
|
+
const setStep = React52__namespace.useCallback(
|
|
4249
|
+
(step) => {
|
|
4250
|
+
if (!isControlled) {
|
|
4251
|
+
setLocalValue(step);
|
|
4252
|
+
}
|
|
4253
|
+
onValueChange?.(step);
|
|
4254
|
+
if (linear) {
|
|
4255
|
+
setCompletedSteps((prev) => {
|
|
4256
|
+
const priorSteps = steps.filter((s) => s < step);
|
|
4257
|
+
const nextCompleted = Array.from(/* @__PURE__ */ new Set([...prev, ...priorSteps])).sort((a, b) => a - b);
|
|
4258
|
+
return nextCompleted;
|
|
4259
|
+
});
|
|
4260
|
+
}
|
|
4261
|
+
},
|
|
4262
|
+
[isControlled, onValueChange, linear, steps]
|
|
4263
|
+
);
|
|
4264
|
+
const contextValue = React52__namespace.useMemo(
|
|
4265
|
+
() => ({
|
|
4266
|
+
activeStep,
|
|
4267
|
+
orientation,
|
|
4268
|
+
linear,
|
|
4269
|
+
setStep,
|
|
4270
|
+
completedSteps,
|
|
4271
|
+
registerStep,
|
|
4272
|
+
unregisterStep,
|
|
4273
|
+
steps
|
|
4274
|
+
}),
|
|
4275
|
+
[activeStep, orientation, linear, setStep, completedSteps, registerStep, unregisterStep, steps]
|
|
4276
|
+
);
|
|
4277
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StepperContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4278
|
+
"div",
|
|
4279
|
+
{
|
|
4280
|
+
ref,
|
|
4281
|
+
className: cn(
|
|
4282
|
+
"w-full",
|
|
4283
|
+
orientation === "vertical" ? "flex flex-col gap-6" : "space-y-6",
|
|
4284
|
+
className
|
|
4285
|
+
),
|
|
4286
|
+
...props,
|
|
4287
|
+
children
|
|
4288
|
+
}
|
|
4289
|
+
) });
|
|
4290
|
+
}
|
|
4291
|
+
);
|
|
4292
|
+
Stepper.displayName = "Stepper";
|
|
4293
|
+
var StepperContent = React52__namespace.forwardRef(
|
|
4294
|
+
({ value, className, children, ...props }, ref) => {
|
|
4295
|
+
const ctx = React52__namespace.useContext(StepperContext);
|
|
4296
|
+
if (!ctx) throw new Error("StepperContent must be used within a Stepper");
|
|
4297
|
+
const isActive = ctx.activeStep === value;
|
|
4298
|
+
if (!isActive) return null;
|
|
4299
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4300
|
+
"div",
|
|
4301
|
+
{
|
|
4302
|
+
ref,
|
|
4303
|
+
role: "tabpanel",
|
|
4304
|
+
tabIndex: 0,
|
|
4305
|
+
className: cn("focus-visible:outline-none w-full", className),
|
|
4306
|
+
...props,
|
|
4307
|
+
children
|
|
4308
|
+
}
|
|
4309
|
+
);
|
|
4310
|
+
}
|
|
4311
|
+
);
|
|
4312
|
+
StepperContent.displayName = "StepperContent";
|
|
4313
|
+
var StepperList = React52__namespace.forwardRef(
|
|
4314
|
+
({ className, children, ...props }, ref) => {
|
|
4315
|
+
const ctx = React52__namespace.useContext(StepperContext);
|
|
4316
|
+
if (!ctx) throw new Error("StepperList must be used within a Stepper");
|
|
4317
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4318
|
+
"div",
|
|
4319
|
+
{
|
|
4320
|
+
ref,
|
|
4321
|
+
role: "tablist",
|
|
4322
|
+
"aria-orientation": ctx.orientation,
|
|
4323
|
+
className: cn(
|
|
4324
|
+
ctx.orientation === "horizontal" ? "flex items-center justify-between w-full relative gap-4" : "flex flex-col items-start gap-6 relative w-full",
|
|
4325
|
+
className
|
|
4326
|
+
),
|
|
4327
|
+
...props,
|
|
4328
|
+
children
|
|
4329
|
+
}
|
|
4330
|
+
);
|
|
4331
|
+
}
|
|
4332
|
+
);
|
|
4333
|
+
StepperList.displayName = "StepperList";
|
|
4334
|
+
var StepperItem = React52__namespace.forwardRef(
|
|
4335
|
+
({ value, disabled = false, className, children, ...props }, ref) => {
|
|
4336
|
+
const ctx = React52__namespace.useContext(StepperContext);
|
|
4337
|
+
if (!ctx) throw new Error("StepperItem must be used within a Stepper");
|
|
4338
|
+
const { registerStep, unregisterStep } = ctx;
|
|
4339
|
+
React52__namespace.useEffect(() => {
|
|
4340
|
+
registerStep(value);
|
|
4341
|
+
return () => unregisterStep(value);
|
|
4342
|
+
}, [value, registerStep, unregisterStep]);
|
|
4343
|
+
const isLast = ctx.steps[ctx.steps.length - 1] === value;
|
|
4344
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StepperItemContext.Provider, { value: { value, disabled, isLast }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4345
|
+
"div",
|
|
4346
|
+
{
|
|
4347
|
+
ref,
|
|
4348
|
+
className: cn(
|
|
4349
|
+
"group relative flex items-center gap-3 z-10",
|
|
4350
|
+
ctx.orientation === "vertical" ? "flex items-start w-full" : "",
|
|
4351
|
+
className
|
|
4352
|
+
),
|
|
4353
|
+
...props,
|
|
4354
|
+
children
|
|
4355
|
+
}
|
|
4356
|
+
) });
|
|
4357
|
+
}
|
|
4358
|
+
);
|
|
4359
|
+
StepperItem.displayName = "StepperItem";
|
|
4360
|
+
var StepperSeparator = React52__namespace.forwardRef(
|
|
4361
|
+
({ className, ...props }, ref) => {
|
|
4362
|
+
const ctx = React52__namespace.useContext(StepperContext);
|
|
4363
|
+
if (!ctx) throw new Error("StepperSeparator must be used within a Stepper");
|
|
4364
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4365
|
+
"div",
|
|
4366
|
+
{
|
|
4367
|
+
ref,
|
|
4368
|
+
className: cn(
|
|
4369
|
+
ctx.orientation === "horizontal" ? "flex-1 h-[2px] bg-border transition-all duration-300" : "w-[2px] bg-border absolute left-[17px] top-8 bottom-0 -ml-px z-0",
|
|
4370
|
+
className
|
|
4371
|
+
),
|
|
4372
|
+
...props
|
|
4373
|
+
}
|
|
4374
|
+
);
|
|
4375
|
+
}
|
|
4376
|
+
);
|
|
4377
|
+
StepperSeparator.displayName = "StepperSeparator";
|
|
4378
|
+
var StepperTrigger = React52__namespace.forwardRef(
|
|
4379
|
+
({ className, children, onClick, onKeyDown, ...props }, ref) => {
|
|
4380
|
+
const ctx = React52__namespace.useContext(StepperContext);
|
|
4381
|
+
const itemCtx = React52__namespace.useContext(StepperItemContext);
|
|
4382
|
+
if (!ctx || !itemCtx) {
|
|
4383
|
+
throw new Error("StepperTrigger must be used within a StepperItem inside a Stepper");
|
|
4384
|
+
}
|
|
4385
|
+
const isCompleted = ctx.completedSteps.includes(itemCtx.value) || itemCtx.value < ctx.activeStep;
|
|
4386
|
+
const isActive = ctx.activeStep === itemCtx.value;
|
|
4387
|
+
const isClickable = !ctx.linear || isCompleted || isActive;
|
|
4388
|
+
const disabled = itemCtx.disabled || !isClickable;
|
|
4389
|
+
const handleClick = (e) => {
|
|
4390
|
+
if (disabled) {
|
|
4391
|
+
e.preventDefault();
|
|
4392
|
+
return;
|
|
4393
|
+
}
|
|
4394
|
+
ctx.setStep(itemCtx.value);
|
|
4395
|
+
onClick?.(e);
|
|
4396
|
+
};
|
|
4397
|
+
const handleKeyDown = (e) => {
|
|
4398
|
+
onKeyDown?.(e);
|
|
4399
|
+
const triggers = Array.from(
|
|
4400
|
+
e.currentTarget.closest('[role="tablist"]')?.querySelectorAll('[role="tab"]') || []
|
|
4401
|
+
);
|
|
4402
|
+
const currentIndex = triggers.indexOf(e.currentTarget);
|
|
4403
|
+
if (currentIndex === -1) return;
|
|
4404
|
+
let targetIndex = -1;
|
|
4405
|
+
if (e.key === "ArrowRight" || e.key === "ArrowDown") {
|
|
4406
|
+
targetIndex = Math.min(currentIndex + 1, triggers.length - 1);
|
|
4407
|
+
} else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
|
|
4408
|
+
targetIndex = Math.max(currentIndex - 1, 0);
|
|
4409
|
+
}
|
|
4410
|
+
if (targetIndex !== -1 && triggers[targetIndex]) {
|
|
4411
|
+
e.preventDefault();
|
|
4412
|
+
triggers[targetIndex].focus();
|
|
4413
|
+
}
|
|
4414
|
+
};
|
|
4415
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4416
|
+
"button",
|
|
4417
|
+
{
|
|
4418
|
+
ref,
|
|
4419
|
+
type: "button",
|
|
4420
|
+
role: "tab",
|
|
4421
|
+
"aria-selected": isActive,
|
|
4422
|
+
"aria-disabled": disabled,
|
|
4423
|
+
tabIndex: isActive ? 0 : -1,
|
|
4424
|
+
onClick: handleClick,
|
|
4425
|
+
onKeyDown: handleKeyDown,
|
|
4426
|
+
className: cn(
|
|
4427
|
+
"flex items-center gap-3 bg-transparent border-0 p-0 text-left cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary rounded-md disabled:cursor-not-allowed disabled:opacity-50",
|
|
4428
|
+
ctx.orientation === "vertical" ? "w-full" : "",
|
|
4429
|
+
className
|
|
4430
|
+
),
|
|
4431
|
+
...props,
|
|
4432
|
+
children
|
|
4433
|
+
}
|
|
4434
|
+
);
|
|
4435
|
+
}
|
|
4436
|
+
);
|
|
4437
|
+
StepperTrigger.displayName = "StepperTrigger";
|
|
4438
|
+
var StepperIndicator = React52__namespace.forwardRef(
|
|
4439
|
+
({ className, children, ...props }, ref) => {
|
|
4440
|
+
const ctx = React52__namespace.useContext(StepperContext);
|
|
4441
|
+
const itemCtx = React52__namespace.useContext(StepperItemContext);
|
|
4442
|
+
if (!ctx || !itemCtx) {
|
|
4443
|
+
throw new Error("StepperIndicator must be used within a StepperItem inside a Stepper");
|
|
4444
|
+
}
|
|
4445
|
+
const isCompleted = ctx.completedSteps.includes(itemCtx.value) || itemCtx.value < ctx.activeStep;
|
|
4446
|
+
const isActive = ctx.activeStep === itemCtx.value;
|
|
4447
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4448
|
+
"span",
|
|
4449
|
+
{
|
|
4450
|
+
ref,
|
|
4451
|
+
className: cn(
|
|
4452
|
+
"flex h-9 w-9 shrink-0 items-center justify-center rounded-full border text-sm font-semibold transition-all duration-200",
|
|
4453
|
+
isCompleted ? "bg-primary border-primary text-primary-foreground" : isActive ? "border-primary text-primary bg-primary/10 ring-2 ring-primary/20" : "border-border text-muted-foreground bg-muted/40",
|
|
4454
|
+
className
|
|
4455
|
+
),
|
|
4456
|
+
...props,
|
|
4457
|
+
children: children ?? (isCompleted ? "\u2713" : itemCtx.value + 1)
|
|
4458
|
+
}
|
|
4459
|
+
);
|
|
4460
|
+
}
|
|
4461
|
+
);
|
|
4462
|
+
StepperIndicator.displayName = "StepperIndicator";
|
|
4463
|
+
var StepperTitle = React52__namespace.forwardRef(
|
|
4464
|
+
({ className, ...props }, ref) => {
|
|
4465
|
+
const ctx = React52__namespace.useContext(StepperContext);
|
|
4466
|
+
const itemCtx = React52__namespace.useContext(StepperItemContext);
|
|
4467
|
+
if (!ctx || !itemCtx) {
|
|
4468
|
+
throw new Error("StepperTitle must be used within a StepperItem inside a Stepper");
|
|
4469
|
+
}
|
|
4470
|
+
const isActive = ctx.activeStep === itemCtx.value;
|
|
4471
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4472
|
+
"span",
|
|
4473
|
+
{
|
|
4474
|
+
ref,
|
|
4475
|
+
className: cn(
|
|
4476
|
+
"text-sm font-medium transition-colors duration-200",
|
|
4477
|
+
isActive ? "text-foreground font-semibold" : "text-muted-foreground",
|
|
4478
|
+
className
|
|
4479
|
+
),
|
|
4480
|
+
...props
|
|
4481
|
+
}
|
|
4482
|
+
);
|
|
4483
|
+
}
|
|
4484
|
+
);
|
|
4485
|
+
StepperTitle.displayName = "StepperTitle";
|
|
4486
|
+
var StepperDescription = React52__namespace.forwardRef(
|
|
4487
|
+
({ className, ...props }, ref) => {
|
|
4488
|
+
const itemCtx = React52__namespace.useContext(StepperItemContext);
|
|
4489
|
+
if (!itemCtx) throw new Error("StepperDescription must be used within a StepperItem");
|
|
4490
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4491
|
+
"span",
|
|
4492
|
+
{
|
|
4493
|
+
ref,
|
|
4494
|
+
className: cn("text-xs text-muted-foreground text-left block", className),
|
|
4495
|
+
...props
|
|
4496
|
+
}
|
|
4497
|
+
);
|
|
4498
|
+
}
|
|
4499
|
+
);
|
|
4500
|
+
StepperDescription.displayName = "StepperDescription";
|
|
4501
|
+
var AppShellBanner = React52__namespace.forwardRef(
|
|
4502
|
+
({ className, variant = "primary", closable, onClose, children, ...props }, ref) => {
|
|
4503
|
+
const variantClass = {
|
|
4504
|
+
primary: "bg-primary text-primary-foreground",
|
|
4505
|
+
accent: "bg-secondary text-secondary-foreground",
|
|
4506
|
+
muted: "bg-surface border-b border-border text-muted-foreground"
|
|
4507
|
+
}[variant];
|
|
4508
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4509
|
+
"div",
|
|
4510
|
+
{
|
|
4511
|
+
ref,
|
|
4512
|
+
className: cn("px-4 py-2 text-sm font-medium text-center flex items-center justify-center relative z-30", variantClass, className),
|
|
4513
|
+
...props,
|
|
4514
|
+
children: [
|
|
4515
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children }),
|
|
4516
|
+
closable && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4517
|
+
"button",
|
|
4518
|
+
{
|
|
4519
|
+
type: "button",
|
|
4520
|
+
onClick: onClose,
|
|
4521
|
+
className: "p-1 rounded opacity-80 hover:opacity-100 transition-opacity ml-2 cursor-pointer",
|
|
4522
|
+
"aria-label": "Close banner",
|
|
4523
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: 14, height: 14, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
|
|
4524
|
+
}
|
|
4525
|
+
)
|
|
4526
|
+
]
|
|
4527
|
+
}
|
|
4528
|
+
);
|
|
4529
|
+
}
|
|
4530
|
+
);
|
|
4531
|
+
AppShellBanner.displayName = "AppShellBanner";
|
|
4532
|
+
var AppShellHeader = React52__namespace.forwardRef(
|
|
4533
|
+
({
|
|
4534
|
+
className,
|
|
4535
|
+
variant = "glass",
|
|
4536
|
+
position = "sticky",
|
|
4537
|
+
bordered = true,
|
|
4538
|
+
children,
|
|
4539
|
+
mobileNav,
|
|
4540
|
+
...props
|
|
4541
|
+
}, ref) => {
|
|
4542
|
+
const [mobileOpen, setMobileOpen] = React52__namespace.useState(false);
|
|
4543
|
+
React52__namespace.useEffect(() => {
|
|
4544
|
+
const handleKeyDown = (e) => {
|
|
4545
|
+
if (e.key === "Escape" && mobileOpen) {
|
|
4546
|
+
setMobileOpen(false);
|
|
4547
|
+
}
|
|
4548
|
+
};
|
|
4549
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4550
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4551
|
+
}, [mobileOpen]);
|
|
4552
|
+
const positionClass = {
|
|
4553
|
+
sticky: "sticky top-0 z-40",
|
|
4554
|
+
fixed: "fixed top-0 left-0 right-0 z-40",
|
|
4555
|
+
static: "relative z-40"
|
|
4556
|
+
}[position];
|
|
4557
|
+
const variantClass = {
|
|
4558
|
+
glass: "bg-surface/80 backdrop-blur-md text-foreground",
|
|
4559
|
+
solid: "bg-surface text-foreground",
|
|
4560
|
+
transparent: "bg-transparent text-foreground"
|
|
4561
|
+
}[variant];
|
|
4562
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4563
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4564
|
+
"header",
|
|
4565
|
+
{
|
|
4566
|
+
ref,
|
|
4567
|
+
className: cn(
|
|
4568
|
+
"w-full transition-colors",
|
|
4569
|
+
positionClass,
|
|
4570
|
+
variantClass,
|
|
4571
|
+
bordered && "border-b border-border/60",
|
|
4572
|
+
className
|
|
4573
|
+
),
|
|
4574
|
+
...props,
|
|
4575
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between gap-4", children: [
|
|
4576
|
+
mobileNav && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4577
|
+
"button",
|
|
4578
|
+
{
|
|
4579
|
+
type: "button",
|
|
4580
|
+
onClick: () => setMobileOpen(true),
|
|
4581
|
+
className: "md:hidden p-2 -ml-2 rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted transition-colors cursor-pointer",
|
|
4582
|
+
"aria-label": "Open navigation",
|
|
4583
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: 20, height: 20, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
4584
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "12", x2: "21", y2: "12" }),
|
|
4585
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "6", x2: "21", y2: "6" }),
|
|
4586
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "18", x2: "21", y2: "18" })
|
|
4587
|
+
] })
|
|
4588
|
+
}
|
|
4589
|
+
),
|
|
4590
|
+
children
|
|
4591
|
+
] })
|
|
4592
|
+
}
|
|
4593
|
+
),
|
|
4594
|
+
mobileNav && mobileOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50 md:hidden flex", children: [
|
|
4595
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4596
|
+
"div",
|
|
4597
|
+
{
|
|
4598
|
+
"aria-hidden": "true",
|
|
4599
|
+
onClick: () => setMobileOpen(false),
|
|
4600
|
+
className: "fixed inset-0 bg-overlay backdrop-blur-[2px] transition-opacity duration-300"
|
|
4601
|
+
}
|
|
4602
|
+
),
|
|
4603
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4604
|
+
"aside",
|
|
4605
|
+
{
|
|
4606
|
+
role: "dialog",
|
|
4607
|
+
"aria-modal": "true",
|
|
4608
|
+
"aria-label": "Mobile Navigation",
|
|
4609
|
+
className: "relative z-10 w-72 h-full bg-surface border-r border-border flex flex-col shadow-kj-lg",
|
|
4610
|
+
children: [
|
|
4611
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-4 border-b border-border", children: [
|
|
4612
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-bold uppercase tracking-wider text-muted-foreground", children: "Navigation" }),
|
|
4613
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4614
|
+
"button",
|
|
4615
|
+
{
|
|
4616
|
+
type: "button",
|
|
4617
|
+
onClick: () => setMobileOpen(false),
|
|
4618
|
+
className: "p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted transition-colors cursor-pointer",
|
|
4619
|
+
"aria-label": "Close navigation",
|
|
4620
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
|
|
4621
|
+
}
|
|
4622
|
+
)
|
|
4623
|
+
] }),
|
|
4624
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto p-4", children: mobileNav })
|
|
4625
|
+
]
|
|
4626
|
+
}
|
|
4627
|
+
)
|
|
4628
|
+
] })
|
|
4629
|
+
] });
|
|
4630
|
+
}
|
|
4631
|
+
);
|
|
4632
|
+
AppShellHeader.displayName = "AppShellHeader";
|
|
4633
|
+
var AppShellMain = React52__namespace.forwardRef(
|
|
4634
|
+
({ className, width = "default", padded = true, children, ...props }, ref) => {
|
|
4635
|
+
const widthClass = {
|
|
4636
|
+
default: "max-w-7xl mx-auto w-full",
|
|
4637
|
+
narrow: "max-w-5xl mx-auto w-full",
|
|
4638
|
+
wide: "max-w-screen-2xl mx-auto w-full",
|
|
4639
|
+
full: "max-w-none w-full"
|
|
4640
|
+
}[width];
|
|
4641
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4642
|
+
"main",
|
|
4643
|
+
{
|
|
4644
|
+
ref,
|
|
4645
|
+
className: cn("flex-1", padded && "px-4 sm:px-6 lg:px-8 py-8 md:py-12", widthClass, className),
|
|
4646
|
+
...props,
|
|
4647
|
+
children
|
|
4648
|
+
}
|
|
4649
|
+
);
|
|
4650
|
+
}
|
|
4651
|
+
);
|
|
4652
|
+
AppShellMain.displayName = "AppShellMain";
|
|
4653
|
+
var AppShellFooter = React52__namespace.forwardRef(
|
|
4654
|
+
({ className, bordered = true, children, ...props }, ref) => {
|
|
4655
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4656
|
+
"footer",
|
|
4657
|
+
{
|
|
4658
|
+
ref,
|
|
4659
|
+
className: cn(
|
|
4660
|
+
"w-full bg-surface text-foreground py-12 mt-auto",
|
|
4661
|
+
bordered && "border-t border-border",
|
|
4662
|
+
className
|
|
4663
|
+
),
|
|
4664
|
+
...props,
|
|
4665
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children })
|
|
4666
|
+
}
|
|
4667
|
+
);
|
|
4668
|
+
}
|
|
4669
|
+
);
|
|
4670
|
+
AppShellFooter.displayName = "AppShellFooter";
|
|
4671
|
+
var AppShell = React52__namespace.forwardRef(
|
|
4672
|
+
({
|
|
4673
|
+
className,
|
|
4674
|
+
banner,
|
|
4675
|
+
header,
|
|
4676
|
+
children,
|
|
4677
|
+
footer,
|
|
4678
|
+
contentWidth = "default",
|
|
4679
|
+
headerPosition = "sticky",
|
|
4680
|
+
headerVariant = "glass",
|
|
4681
|
+
paddedContent = true,
|
|
4682
|
+
mobileNav,
|
|
4683
|
+
...props
|
|
4684
|
+
}, ref) => {
|
|
4685
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4686
|
+
"div",
|
|
4687
|
+
{
|
|
4688
|
+
ref,
|
|
4689
|
+
className: cn("min-h-screen bg-canvas text-foreground flex flex-col antialiased", className),
|
|
4690
|
+
...props,
|
|
4691
|
+
children: [
|
|
4692
|
+
banner && /* @__PURE__ */ jsxRuntime.jsx(AppShellBanner, { children: banner }),
|
|
4693
|
+
header && /* @__PURE__ */ jsxRuntime.jsx(AppShellHeader, { variant: headerVariant, position: headerPosition, mobileNav, children: header }),
|
|
4694
|
+
/* @__PURE__ */ jsxRuntime.jsx(AppShellMain, { width: contentWidth, padded: paddedContent, children }),
|
|
4695
|
+
footer && /* @__PURE__ */ jsxRuntime.jsx(AppShellFooter, { children: footer })
|
|
4696
|
+
]
|
|
4697
|
+
}
|
|
4698
|
+
);
|
|
4699
|
+
}
|
|
4700
|
+
);
|
|
4701
|
+
AppShell.displayName = "AppShell";
|
|
4702
|
+
AppShell.Banner = AppShellBanner;
|
|
4703
|
+
AppShell.Header = AppShellHeader;
|
|
4704
|
+
AppShell.Main = AppShellMain;
|
|
4705
|
+
AppShell.Footer = AppShellFooter;
|
|
4706
|
+
var sizeClasses = {
|
|
4707
|
+
sm: { wrapper: "kj-rating-sm gap-1", star: "w-4 h-4", text: "text-xs" },
|
|
4708
|
+
md: { wrapper: "kj-rating-md gap-1.5", star: "w-5 h-5", text: "text-sm" },
|
|
4709
|
+
lg: { wrapper: "kj-rating-lg gap-2", star: "w-6 h-6", text: "text-base" },
|
|
4710
|
+
xl: { wrapper: "kj-rating-xl gap-2.5", star: "w-8 h-8", text: "text-lg" }
|
|
4711
|
+
};
|
|
4712
|
+
var iconPaths = {
|
|
4713
|
+
star: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",
|
|
4714
|
+
heart: "M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z",
|
|
4715
|
+
flame: "M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z",
|
|
4716
|
+
shield: "M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67 0C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",
|
|
4717
|
+
thumb: "M7 10v12M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z"
|
|
4718
|
+
};
|
|
4719
|
+
function roundToPrecision(value, precision) {
|
|
4720
|
+
const inv = 1 / precision;
|
|
4721
|
+
return Math.round(value * inv) / inv;
|
|
4722
|
+
}
|
|
4723
|
+
function isCssColor(str) {
|
|
4724
|
+
return str.startsWith("#") || str.startsWith("rgb") || str.startsWith("hsl");
|
|
4725
|
+
}
|
|
4726
|
+
var Rating = React52__namespace.forwardRef(
|
|
4727
|
+
({
|
|
4728
|
+
value: controlledValue,
|
|
4729
|
+
defaultValue = 0,
|
|
4730
|
+
max = 5,
|
|
4731
|
+
precision = 1,
|
|
4732
|
+
size = "md",
|
|
4733
|
+
icon = "star",
|
|
4734
|
+
color = "#f59e0b",
|
|
4735
|
+
emptyColor = "#e5e7eb",
|
|
4736
|
+
allowClear = true,
|
|
4737
|
+
disabled = false,
|
|
4738
|
+
readOnly = false,
|
|
4739
|
+
hoverPreview = true,
|
|
4740
|
+
showValue = false,
|
|
4741
|
+
showCount = false,
|
|
4742
|
+
count,
|
|
4743
|
+
name,
|
|
4744
|
+
onChange,
|
|
4745
|
+
onHoverChange,
|
|
4746
|
+
className,
|
|
4747
|
+
onKeyDown,
|
|
4748
|
+
onMouseLeave,
|
|
4749
|
+
"aria-label": ariaLabel,
|
|
4750
|
+
...props
|
|
4751
|
+
}, ref) => {
|
|
4752
|
+
const isControlled = controlledValue !== void 0;
|
|
4753
|
+
const [internalValue, setInternalValue] = React52__namespace.useState(
|
|
4754
|
+
controlledValue ?? defaultValue
|
|
4755
|
+
);
|
|
4756
|
+
const [hoverValue, setHoverValue] = React52__namespace.useState(null);
|
|
4757
|
+
const instanceId = React52__namespace.useId();
|
|
4758
|
+
React52__namespace.useEffect(() => {
|
|
4759
|
+
if (isControlled) {
|
|
4760
|
+
setInternalValue(controlledValue);
|
|
4761
|
+
}
|
|
4762
|
+
}, [isControlled, controlledValue]);
|
|
4763
|
+
const currentValue = isControlled ? controlledValue : internalValue;
|
|
4764
|
+
const displayValue = hoverPreview && hoverValue !== null ? hoverValue : currentValue;
|
|
4765
|
+
const handleValueChange = (newValue) => {
|
|
4766
|
+
if (disabled || readOnly) return;
|
|
4767
|
+
const clamped = Math.max(0, Math.min(max, roundToPrecision(newValue, precision)));
|
|
4768
|
+
if (!isControlled) {
|
|
4769
|
+
setInternalValue(clamped);
|
|
4770
|
+
}
|
|
4771
|
+
onChange?.(clamped);
|
|
4772
|
+
};
|
|
4773
|
+
const getEventValue = (e, starIndex) => {
|
|
4774
|
+
const target = e.currentTarget;
|
|
4775
|
+
const width = target.offsetWidth;
|
|
4776
|
+
const nativeEv = e.nativeEvent;
|
|
4777
|
+
const offsetX = nativeEv?.offsetX ?? nativeEv?.nativeEvent?.offsetX ?? e.offsetX;
|
|
4778
|
+
if (width > 0 && offsetX !== void 0 && offsetX !== null) {
|
|
4779
|
+
const ratio = Math.max(1e-3, Math.min(1, offsetX / width));
|
|
4780
|
+
const stepInStar = Math.ceil(ratio / precision) * precision;
|
|
4781
|
+
return Math.min(max, Math.max(precision, starIndex - 1 + stepInStar));
|
|
4782
|
+
}
|
|
4783
|
+
return starIndex;
|
|
4784
|
+
};
|
|
4785
|
+
const handleStarClick = (e, starIndex) => {
|
|
4786
|
+
if (disabled || readOnly) return;
|
|
4787
|
+
const targetValue = getEventValue(e, starIndex);
|
|
4788
|
+
let nextValue = targetValue;
|
|
4789
|
+
if (allowClear && targetValue === currentValue) {
|
|
4790
|
+
nextValue = 0;
|
|
4791
|
+
}
|
|
4792
|
+
handleValueChange(nextValue);
|
|
4793
|
+
};
|
|
4794
|
+
const handleStarMouseMove = (e, starIndex) => {
|
|
4795
|
+
if (disabled || readOnly) return;
|
|
4796
|
+
if (hoverPreview) {
|
|
4797
|
+
const hoveredVal = getEventValue(e, starIndex);
|
|
4798
|
+
setHoverValue(hoveredVal);
|
|
4799
|
+
onHoverChange?.(hoveredVal);
|
|
4800
|
+
}
|
|
4801
|
+
};
|
|
4802
|
+
const handleKeyDown = (e) => {
|
|
4803
|
+
if (disabled || readOnly) {
|
|
4804
|
+
onKeyDown?.(e);
|
|
4805
|
+
return;
|
|
4806
|
+
}
|
|
4807
|
+
let nextVal = null;
|
|
4808
|
+
switch (e.key) {
|
|
4809
|
+
case "ArrowRight":
|
|
4810
|
+
case "ArrowUp":
|
|
4811
|
+
nextVal = Math.min(max, currentValue + precision);
|
|
4812
|
+
break;
|
|
4813
|
+
case "ArrowLeft":
|
|
4814
|
+
case "ArrowDown":
|
|
4815
|
+
nextVal = Math.max(0, currentValue - precision);
|
|
4816
|
+
break;
|
|
4817
|
+
case "Home":
|
|
4818
|
+
nextVal = 0;
|
|
4819
|
+
break;
|
|
4820
|
+
case "End":
|
|
4821
|
+
nextVal = max;
|
|
4822
|
+
break;
|
|
4823
|
+
}
|
|
4824
|
+
if (nextVal !== null) {
|
|
4825
|
+
e.preventDefault();
|
|
4826
|
+
handleValueChange(nextVal);
|
|
4827
|
+
}
|
|
4828
|
+
onKeyDown?.(e);
|
|
4829
|
+
};
|
|
4830
|
+
const handleContainerMouseLeave = (e) => {
|
|
4831
|
+
if (hoverPreview) {
|
|
4832
|
+
setHoverValue(null);
|
|
4833
|
+
onHoverChange?.(null);
|
|
4834
|
+
}
|
|
4835
|
+
onMouseLeave?.(e);
|
|
4836
|
+
};
|
|
4837
|
+
const sizing = sizeClasses[size] || sizeClasses.md;
|
|
4838
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4839
|
+
"div",
|
|
4840
|
+
{
|
|
4841
|
+
ref,
|
|
4842
|
+
role: readOnly ? "img" : "radiogroup",
|
|
4843
|
+
tabIndex: disabled || readOnly ? -1 : 0,
|
|
4844
|
+
"aria-valuenow": displayValue,
|
|
4845
|
+
"aria-valuemin": 0,
|
|
4846
|
+
"aria-valuemax": max,
|
|
4847
|
+
"aria-disabled": disabled || void 0,
|
|
4848
|
+
"aria-readonly": readOnly || void 0,
|
|
4849
|
+
"aria-label": ariaLabel || (readOnly ? `Rated ${displayValue} out of ${max}` : "Rating"),
|
|
4850
|
+
onKeyDown: handleKeyDown,
|
|
4851
|
+
onMouseLeave: handleContainerMouseLeave,
|
|
4852
|
+
className: cn(
|
|
4853
|
+
"inline-flex items-center select-none focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-md",
|
|
4854
|
+
disabled && "opacity-50 cursor-not-allowed",
|
|
4855
|
+
readOnly && "cursor-default",
|
|
4856
|
+
!disabled && !readOnly && "cursor-pointer",
|
|
4857
|
+
sizing.wrapper,
|
|
4858
|
+
className
|
|
4859
|
+
),
|
|
4860
|
+
...props,
|
|
4861
|
+
children: [
|
|
4862
|
+
name && /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: currentValue }),
|
|
4863
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center gap-0.5", children: Array.from({ length: max }, (_, index) => {
|
|
4864
|
+
const starIndex = index + 1;
|
|
4865
|
+
const fillFraction = Math.max(
|
|
4866
|
+
0,
|
|
4867
|
+
Math.min(1, displayValue - index)
|
|
4868
|
+
);
|
|
4869
|
+
const gradientId = `rating-grad-${instanceId}-${index}-${Math.round(
|
|
4870
|
+
fillFraction * 100
|
|
4871
|
+
)}`;
|
|
4872
|
+
const CustomIconComponent = typeof icon === "function" || typeof icon === "object" ? icon : null;
|
|
4873
|
+
const builtInIconType = typeof icon === "string" ? icon : "star";
|
|
4874
|
+
const pathD = iconPaths[builtInIconType] || iconPaths.star;
|
|
4875
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4876
|
+
"button",
|
|
4877
|
+
{
|
|
4878
|
+
type: "button",
|
|
4879
|
+
tabIndex: -1,
|
|
4880
|
+
"data-testid": "rating-star",
|
|
4881
|
+
role: readOnly ? void 0 : "radio",
|
|
4882
|
+
"aria-checked": readOnly ? void 0 : displayValue >= starIndex,
|
|
4883
|
+
"aria-label": `${starIndex} of ${max} stars`,
|
|
4884
|
+
disabled,
|
|
4885
|
+
onClick: (e) => handleStarClick(e, starIndex),
|
|
4886
|
+
onMouseMove: (e) => handleStarMouseMove(e, starIndex),
|
|
4887
|
+
onMouseEnter: (e) => handleStarMouseMove(e, starIndex),
|
|
4888
|
+
className: cn(
|
|
4889
|
+
"p-0.5 focus:outline-none transition-transform active:scale-95 disabled:scale-100",
|
|
4890
|
+
sizing.star
|
|
4891
|
+
),
|
|
4892
|
+
children: CustomIconComponent ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4893
|
+
CustomIconComponent,
|
|
4894
|
+
{
|
|
4895
|
+
className: cn(
|
|
4896
|
+
"w-full h-full",
|
|
4897
|
+
fillFraction >= 0.5 ? !isCssColor(color) && color : !isCssColor(emptyColor) && emptyColor
|
|
4898
|
+
)
|
|
4899
|
+
}
|
|
4900
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4901
|
+
"svg",
|
|
4902
|
+
{
|
|
4903
|
+
viewBox: "0 0 24 24",
|
|
4904
|
+
className: "w-full h-full",
|
|
4905
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4906
|
+
children: [
|
|
4907
|
+
fillFraction > 0 && fillFraction < 1 && /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4908
|
+
"linearGradient",
|
|
4909
|
+
{
|
|
4910
|
+
id: gradientId,
|
|
4911
|
+
x1: "0%",
|
|
4912
|
+
y1: "0%",
|
|
4913
|
+
x2: "100%",
|
|
4914
|
+
y2: "0%",
|
|
4915
|
+
children: [
|
|
4916
|
+
isCssColor(color) ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4917
|
+
"stop",
|
|
4918
|
+
{
|
|
4919
|
+
offset: `${fillFraction * 100}%`,
|
|
4920
|
+
stopColor: color
|
|
4921
|
+
}
|
|
4922
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4923
|
+
"stop",
|
|
4924
|
+
{
|
|
4925
|
+
offset: `${fillFraction * 100}%`,
|
|
4926
|
+
stopColor: "currentColor",
|
|
4927
|
+
className: color
|
|
4928
|
+
}
|
|
4929
|
+
),
|
|
4930
|
+
isCssColor(emptyColor) ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4931
|
+
"stop",
|
|
4932
|
+
{
|
|
4933
|
+
offset: `${fillFraction * 100}%`,
|
|
4934
|
+
stopColor: emptyColor
|
|
4935
|
+
}
|
|
4936
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4937
|
+
"stop",
|
|
4938
|
+
{
|
|
4939
|
+
offset: `${fillFraction * 100}%`,
|
|
4940
|
+
stopColor: "currentColor",
|
|
4941
|
+
className: emptyColor
|
|
4942
|
+
}
|
|
4943
|
+
)
|
|
4944
|
+
]
|
|
4945
|
+
}
|
|
4946
|
+
) }),
|
|
4947
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4948
|
+
"path",
|
|
4949
|
+
{
|
|
4950
|
+
d: pathD,
|
|
4951
|
+
fill: fillFraction === 1 ? isCssColor(color) ? color : void 0 : fillFraction === 0 ? isCssColor(emptyColor) ? emptyColor : void 0 : `url(#${gradientId})`,
|
|
4952
|
+
className: fillFraction === 1 ? !isCssColor(color) ? color : void 0 : fillFraction === 0 ? !isCssColor(emptyColor) ? emptyColor : void 0 : void 0,
|
|
4953
|
+
stroke: "none"
|
|
4954
|
+
}
|
|
4955
|
+
)
|
|
4956
|
+
]
|
|
4957
|
+
}
|
|
4958
|
+
)
|
|
4959
|
+
},
|
|
4960
|
+
index
|
|
4961
|
+
);
|
|
4962
|
+
}) }),
|
|
4963
|
+
showValue && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-medium text-foreground ml-1.5", sizing.text), children: displayValue }),
|
|
4964
|
+
showCount && count !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-muted-foreground ml-1", sizing.text), children: [
|
|
4965
|
+
"(",
|
|
4966
|
+
count,
|
|
4967
|
+
")"
|
|
4968
|
+
] })
|
|
4969
|
+
]
|
|
4970
|
+
}
|
|
4971
|
+
);
|
|
4972
|
+
}
|
|
4973
|
+
);
|
|
4974
|
+
Rating.displayName = "Rating";
|
|
4975
|
+
var RatingField = React52__namespace.forwardRef(
|
|
4976
|
+
({
|
|
4977
|
+
id: customId,
|
|
4978
|
+
label,
|
|
4979
|
+
helperText,
|
|
4980
|
+
errorMessage,
|
|
4981
|
+
required,
|
|
4982
|
+
className,
|
|
4983
|
+
containerClassName,
|
|
4984
|
+
"aria-describedby": ariaDescribedBy,
|
|
4985
|
+
...ratingProps
|
|
4986
|
+
}, ref) => {
|
|
4987
|
+
const generatedId = React52__namespace.useId();
|
|
4988
|
+
const id = customId || generatedId;
|
|
4989
|
+
const helperId = helperText ? `${id}-helper` : void 0;
|
|
4990
|
+
const errorId = errorMessage ? `${id}-error` : void 0;
|
|
4991
|
+
const describedBy = [ariaDescribedBy, helperId, errorId].filter(Boolean).join(" ") || void 0;
|
|
4992
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-1.5", containerClassName), children: [
|
|
4993
|
+
label && /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: id, required, children: label }),
|
|
4994
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4995
|
+
Rating,
|
|
4996
|
+
{
|
|
4997
|
+
ref,
|
|
4998
|
+
id,
|
|
4999
|
+
className,
|
|
5000
|
+
"aria-describedby": describedBy,
|
|
5001
|
+
...ratingProps
|
|
5002
|
+
}
|
|
5003
|
+
),
|
|
5004
|
+
helperText && /* @__PURE__ */ jsxRuntime.jsx(Hint, { id: helperId, children: helperText }),
|
|
5005
|
+
errorMessage && /* @__PURE__ */ jsxRuntime.jsx(Hint, { id: errorId, error: true, children: errorMessage })
|
|
5006
|
+
] });
|
|
5007
|
+
}
|
|
5008
|
+
);
|
|
5009
|
+
RatingField.displayName = "RatingField";
|
|
5010
|
+
var RatingSummary = React52__namespace.forwardRef(
|
|
5011
|
+
({
|
|
5012
|
+
average,
|
|
5013
|
+
totalCount,
|
|
5014
|
+
distribution,
|
|
5015
|
+
max = 5,
|
|
5016
|
+
size = "md",
|
|
5017
|
+
icon = "star",
|
|
5018
|
+
className,
|
|
5019
|
+
...props
|
|
5020
|
+
}, ref) => {
|
|
5021
|
+
const formattedAverage = Number.isInteger(average) ? average.toString() : average.toFixed(1);
|
|
5022
|
+
const formattedTotalCount = totalCount.toLocaleString();
|
|
5023
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5024
|
+
"div",
|
|
5025
|
+
{
|
|
5026
|
+
ref,
|
|
5027
|
+
className: cn(
|
|
5028
|
+
"flex flex-col gap-6 sm:flex-row sm:items-center sm:gap-8 p-4 rounded-xl border bg-card text-card-foreground shadow-sm",
|
|
5029
|
+
className
|
|
5030
|
+
),
|
|
5031
|
+
...props,
|
|
5032
|
+
children: [
|
|
5033
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center p-4 rounded-lg bg-muted/40 text-center min-w-[140px]", children: [
|
|
5034
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-4xl font-bold tracking-tight text-foreground", children: formattedAverage }),
|
|
5035
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-1.5", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5036
|
+
Rating,
|
|
5037
|
+
{
|
|
5038
|
+
value: average,
|
|
5039
|
+
max,
|
|
5040
|
+
size,
|
|
5041
|
+
icon,
|
|
5042
|
+
readOnly: true,
|
|
5043
|
+
allowClear: false,
|
|
5044
|
+
hoverPreview: false
|
|
5045
|
+
}
|
|
5046
|
+
) }),
|
|
5047
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-muted-foreground", children: [
|
|
5048
|
+
formattedTotalCount,
|
|
5049
|
+
" total ratings"
|
|
5050
|
+
] })
|
|
5051
|
+
] }),
|
|
5052
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex flex-col gap-2.5", children: distribution.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-sm", children: [
|
|
5053
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "w-12 text-right font-medium text-foreground whitespace-nowrap", children: [
|
|
5054
|
+
item.stars,
|
|
5055
|
+
" star"
|
|
5056
|
+
] }),
|
|
5057
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5058
|
+
Progress,
|
|
5059
|
+
{
|
|
5060
|
+
value: item.percentage,
|
|
5061
|
+
"aria-label": `${item.stars} star ratings: ${item.percentage}%`,
|
|
5062
|
+
className: "h-2.5 flex-1"
|
|
5063
|
+
}
|
|
5064
|
+
),
|
|
5065
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "w-12 text-right text-xs text-muted-foreground font-mono", children: [
|
|
5066
|
+
item.percentage,
|
|
5067
|
+
"%"
|
|
5068
|
+
] })
|
|
5069
|
+
] }, item.stars)) })
|
|
5070
|
+
]
|
|
5071
|
+
}
|
|
5072
|
+
);
|
|
5073
|
+
}
|
|
5074
|
+
);
|
|
5075
|
+
RatingSummary.displayName = "RatingSummary";
|
|
5076
|
+
var PricingCard = React52__namespace.forwardRef(
|
|
5077
|
+
({
|
|
5078
|
+
className,
|
|
5079
|
+
name,
|
|
5080
|
+
price,
|
|
5081
|
+
period,
|
|
5082
|
+
description,
|
|
5083
|
+
features = [],
|
|
5084
|
+
variant,
|
|
5085
|
+
badge,
|
|
5086
|
+
popular = false,
|
|
5087
|
+
ctaText = "Get Started",
|
|
5088
|
+
onCtaClick,
|
|
5089
|
+
ctaHref,
|
|
5090
|
+
cta,
|
|
5091
|
+
disabled = false,
|
|
5092
|
+
...props
|
|
5093
|
+
}, ref) => {
|
|
5094
|
+
const resolvedVariant = variant || (popular ? "featured" : "default");
|
|
5095
|
+
const displayBadge = badge || (popular ? "Most Popular" : void 0);
|
|
5096
|
+
const isFeatured = resolvedVariant === "featured";
|
|
5097
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5098
|
+
Card,
|
|
5099
|
+
{
|
|
5100
|
+
ref,
|
|
5101
|
+
className: cn(
|
|
5102
|
+
"relative flex flex-col p-6 transition-all duration-300",
|
|
5103
|
+
isFeatured ? "border-amber-500/80 shadow-kj-lg ring-1 ring-amber-500/30" : resolvedVariant === "outline" ? "border-border/80 bg-transparent shadow-none" : "border-border shadow-kj-sm",
|
|
5104
|
+
className
|
|
5105
|
+
),
|
|
5106
|
+
...props,
|
|
5107
|
+
children: [
|
|
5108
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 flex items-start justify-between gap-3", children: [
|
|
5109
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
5110
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-xl font-bold tracking-tight text-foreground", children: name }),
|
|
5111
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: description })
|
|
5112
|
+
] }),
|
|
5113
|
+
displayBadge && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full bg-amber-500 px-3 py-0.5 text-[0.7rem] font-bold uppercase tracking-wider text-black shadow-sm shrink-0 mt-0.5", children: displayBadge })
|
|
5114
|
+
] }),
|
|
5115
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6 flex items-baseline gap-1", children: [
|
|
5116
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-3xl font-extrabold tracking-tight text-foreground", children: price }),
|
|
5117
|
+
period && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-muted-foreground", children: period })
|
|
5118
|
+
] }),
|
|
5119
|
+
features.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "mb-6 flex flex-1 flex-col gap-2.5 p-0 text-xs list-none", children: features.map((feature, idx) => {
|
|
5120
|
+
const text = typeof feature === "string" ? feature : feature.text;
|
|
5121
|
+
const included = typeof feature === "string" ? true : feature.included ?? true;
|
|
5122
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-center gap-2.5", children: [
|
|
5123
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5124
|
+
"span",
|
|
5125
|
+
{
|
|
5126
|
+
className: cn(
|
|
5127
|
+
"flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[0.65rem] font-bold",
|
|
5128
|
+
included ? "bg-amber-500/15 text-amber-600 dark:text-amber-400" : "bg-muted text-muted-foreground/60"
|
|
5129
|
+
),
|
|
5130
|
+
children: included ? "\u2713" : "\u2715"
|
|
5131
|
+
}
|
|
5132
|
+
),
|
|
5133
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(included ? "text-foreground" : "text-muted-foreground line-through opacity-70"), children: text })
|
|
5134
|
+
] }, idx);
|
|
5135
|
+
}) }),
|
|
5136
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto pt-2", children: cta ? cta : ctaHref ? (
|
|
5137
|
+
/* eslint-disable-next-line jsx-a11y/anchor-is-valid */
|
|
5138
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5139
|
+
"a",
|
|
5140
|
+
{
|
|
5141
|
+
href: disabled ? void 0 : ctaHref,
|
|
5142
|
+
"aria-disabled": disabled || void 0,
|
|
5143
|
+
tabIndex: disabled ? -1 : void 0,
|
|
5144
|
+
className: cn(
|
|
5145
|
+
buttonVariants({ variant: isFeatured ? "primary" : "outline" }),
|
|
5146
|
+
"w-full justify-center",
|
|
5147
|
+
disabled && "pointer-events-none opacity-50"
|
|
5148
|
+
),
|
|
5149
|
+
children: ctaText
|
|
5150
|
+
}
|
|
5151
|
+
)
|
|
5152
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
5153
|
+
Button,
|
|
5154
|
+
{
|
|
5155
|
+
variant: isFeatured ? "primary" : "outline",
|
|
5156
|
+
className: "w-full justify-center",
|
|
5157
|
+
onClick: onCtaClick,
|
|
5158
|
+
disabled,
|
|
5159
|
+
children: ctaText
|
|
5160
|
+
}
|
|
5161
|
+
) })
|
|
5162
|
+
]
|
|
5163
|
+
}
|
|
5164
|
+
);
|
|
5165
|
+
}
|
|
5166
|
+
);
|
|
5167
|
+
PricingCard.displayName = "PricingCard";
|
|
5168
|
+
var BlogCard = React52__namespace.forwardRef(
|
|
5169
|
+
({
|
|
5170
|
+
className,
|
|
5171
|
+
title,
|
|
5172
|
+
description,
|
|
5173
|
+
coverUrl,
|
|
5174
|
+
coverAlt,
|
|
5175
|
+
category,
|
|
5176
|
+
readTime,
|
|
5177
|
+
publishedAt,
|
|
5178
|
+
author,
|
|
5179
|
+
orientation = "vertical",
|
|
5180
|
+
href,
|
|
5181
|
+
...props
|
|
5182
|
+
}, ref) => {
|
|
5183
|
+
const isHorizontal = orientation === "horizontal";
|
|
5184
|
+
const isInteractive = Boolean(href || props.onClick);
|
|
5185
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5186
|
+
Card,
|
|
5187
|
+
{
|
|
5188
|
+
ref,
|
|
5189
|
+
as: href ? "a" : "div",
|
|
5190
|
+
href,
|
|
5191
|
+
interactive: isInteractive,
|
|
5192
|
+
className: cn(
|
|
5193
|
+
"group flex overflow-hidden transition-all duration-300",
|
|
5194
|
+
isHorizontal ? "flex-col sm:flex-row" : "flex-col",
|
|
5195
|
+
className
|
|
5196
|
+
),
|
|
5197
|
+
...props,
|
|
5198
|
+
children: [
|
|
5199
|
+
coverUrl && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5200
|
+
"div",
|
|
5201
|
+
{
|
|
5202
|
+
className: cn(
|
|
5203
|
+
"relative overflow-hidden bg-muted shrink-0",
|
|
5204
|
+
isHorizontal ? "w-full sm:w-2/5 min-h-[160px]" : "w-full aspect-[16/9]"
|
|
5205
|
+
),
|
|
5206
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5207
|
+
"img",
|
|
5208
|
+
{
|
|
5209
|
+
src: coverUrl,
|
|
5210
|
+
alt: coverAlt || title,
|
|
5211
|
+
className: "h-full w-full object-cover transition-transform duration-300 group-hover:scale-105"
|
|
5212
|
+
}
|
|
5213
|
+
)
|
|
5214
|
+
}
|
|
5215
|
+
),
|
|
5216
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col justify-between p-5", children: [
|
|
5217
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
5218
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 flex items-center gap-2 text-[0.75rem] text-muted-foreground", children: [
|
|
5219
|
+
category && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "secondary", children: category }),
|
|
5220
|
+
(readTime || publishedAt) && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
5221
|
+
publishedAt,
|
|
5222
|
+
" ",
|
|
5223
|
+
publishedAt && readTime && "\u2022",
|
|
5224
|
+
" ",
|
|
5225
|
+
readTime
|
|
5226
|
+
] })
|
|
5227
|
+
] }),
|
|
5228
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-bold tracking-tight text-foreground transition-colors group-hover:text-primary", children: title }),
|
|
5229
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1.5 text-xs text-muted-foreground line-clamp-2", children: description })
|
|
5230
|
+
] }),
|
|
5231
|
+
author && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex items-center gap-2.5 border-t border-border/60 pt-3", children: [
|
|
5232
|
+
/* @__PURE__ */ jsxRuntime.jsx(Avatar, { src: author.avatarUrl, alt: author.name, size: "sm", children: author.name.charAt(0) }),
|
|
5233
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col text-xs", children: [
|
|
5234
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-foreground", children: author.name }),
|
|
5235
|
+
author.role && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.7rem] text-muted-foreground", children: author.role })
|
|
5236
|
+
] })
|
|
5237
|
+
] })
|
|
5238
|
+
] })
|
|
5239
|
+
]
|
|
5240
|
+
}
|
|
5241
|
+
);
|
|
5242
|
+
}
|
|
5243
|
+
);
|
|
5244
|
+
BlogCard.displayName = "BlogCard";
|
|
5245
|
+
var ProjectCard = React52__namespace.forwardRef(
|
|
5246
|
+
({
|
|
5247
|
+
className,
|
|
5248
|
+
title,
|
|
5249
|
+
description,
|
|
5250
|
+
status,
|
|
5251
|
+
techStack = [],
|
|
5252
|
+
metrics = [],
|
|
5253
|
+
updatedAt,
|
|
5254
|
+
actions,
|
|
5255
|
+
href,
|
|
5256
|
+
...props
|
|
5257
|
+
}, ref) => {
|
|
5258
|
+
const isInteractive = Boolean(href || props.onClick);
|
|
5259
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5260
|
+
Card,
|
|
5261
|
+
{
|
|
5262
|
+
ref,
|
|
5263
|
+
as: href ? "a" : "div",
|
|
5264
|
+
href,
|
|
5265
|
+
interactive: isInteractive,
|
|
5266
|
+
className: cn(
|
|
5267
|
+
"group flex flex-col justify-between p-5 transition-all duration-300",
|
|
5268
|
+
className
|
|
5269
|
+
),
|
|
5270
|
+
...props,
|
|
5271
|
+
children: [
|
|
5272
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
5273
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
5274
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-bold tracking-tight text-foreground transition-colors group-hover:text-primary", children: title }),
|
|
5275
|
+
status && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: status.variant || "neutral", className: "shrink-0 text-[0.65rem]", children: status.label })
|
|
5276
|
+
] }),
|
|
5277
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1.5 text-xs text-muted-foreground line-clamp-2", children: description }),
|
|
5278
|
+
techStack.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3.5 flex flex-wrap gap-1.5", children: techStack.map((tech) => /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "neutral", className: "text-[0.65rem] py-0 px-2 font-mono", children: tech }, tech)) })
|
|
5279
|
+
] }),
|
|
5280
|
+
(metrics.length > 0 || updatedAt || actions) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex items-center justify-between border-t border-border/60 pt-3 text-[0.75rem] text-muted-foreground", children: [
|
|
5281
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
5282
|
+
metrics.map((metric, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5283
|
+
"span",
|
|
5284
|
+
{
|
|
5285
|
+
className: "flex items-center gap-1 font-mono font-medium",
|
|
5286
|
+
children: [
|
|
5287
|
+
metric.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: metric.icon }),
|
|
5288
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: metric.value }),
|
|
5289
|
+
metric.label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/70", children: metric.label })
|
|
5290
|
+
]
|
|
5291
|
+
},
|
|
5292
|
+
metric.label ? `${metric.label}-${idx}` : idx
|
|
5293
|
+
)),
|
|
5294
|
+
updatedAt && /* @__PURE__ */ jsxRuntime.jsx("span", { children: updatedAt })
|
|
5295
|
+
] }),
|
|
5296
|
+
actions && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5297
|
+
"div",
|
|
5298
|
+
{
|
|
5299
|
+
onClick: (e) => e.stopPropagation(),
|
|
5300
|
+
className: "flex items-center gap-1 shrink-0",
|
|
5301
|
+
children: actions
|
|
5302
|
+
}
|
|
5303
|
+
)
|
|
5304
|
+
] })
|
|
5305
|
+
]
|
|
5306
|
+
}
|
|
5307
|
+
);
|
|
5308
|
+
}
|
|
5309
|
+
);
|
|
5310
|
+
ProjectCard.displayName = "ProjectCard";
|
|
5311
|
+
function formatRelativeTime(date) {
|
|
5312
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
5313
|
+
if (isNaN(d.getTime())) return "";
|
|
5314
|
+
const diffMs = Date.now() - d.getTime();
|
|
5315
|
+
const diffMin = Math.floor(diffMs / 6e4);
|
|
5316
|
+
const diffH = Math.floor(diffMs / 36e5);
|
|
5317
|
+
const diffD = Math.floor(diffMs / 864e5);
|
|
5318
|
+
if (diffMin < 1) return "Just now";
|
|
5319
|
+
if (diffMin < 60) return `${diffMin} min ago`;
|
|
5320
|
+
if (diffH < 24) return diffH === 1 ? "1 hour ago" : `${diffH} hours ago`;
|
|
5321
|
+
if (diffD === 1) return "Yesterday";
|
|
5322
|
+
if (diffD < 7) return `${diffD} days ago`;
|
|
5323
|
+
return d.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
5324
|
+
}
|
|
5325
|
+
function useInboxState(initial) {
|
|
5326
|
+
const [items, setItems] = React52__namespace.useState(initial);
|
|
5327
|
+
const unreadCount = items.filter((i) => !i.read).length;
|
|
5328
|
+
const markRead = React52__namespace.useCallback((id) => {
|
|
5329
|
+
setItems(
|
|
5330
|
+
(prev) => prev.map((item) => item.id === id ? { ...item, read: true } : item)
|
|
5331
|
+
);
|
|
5332
|
+
}, []);
|
|
5333
|
+
const markAllRead = React52__namespace.useCallback(() => {
|
|
5334
|
+
setItems((prev) => prev.map((item) => ({ ...item, read: true })));
|
|
5335
|
+
}, []);
|
|
5336
|
+
const dismiss = React52__namespace.useCallback((id) => {
|
|
5337
|
+
setItems((prev) => prev.filter((item) => item.id !== id));
|
|
5338
|
+
}, []);
|
|
5339
|
+
return { items, unreadCount, markRead, markAllRead, dismiss };
|
|
5340
|
+
}
|
|
5341
|
+
var InboxContext = React52__namespace.createContext(null);
|
|
5342
|
+
function useInboxContext(part) {
|
|
5343
|
+
const ctx = React52__namespace.useContext(InboxContext);
|
|
5344
|
+
if (!ctx) throw new Error(`${part} must be used inside <InboxPopover>`);
|
|
5345
|
+
return ctx;
|
|
5346
|
+
}
|
|
5347
|
+
function InboxPopover({
|
|
5348
|
+
children,
|
|
5349
|
+
className,
|
|
5350
|
+
open: openProp,
|
|
5351
|
+
onOpenChange
|
|
5352
|
+
}) {
|
|
5353
|
+
const [openState, setOpenState] = React52__namespace.useState(false);
|
|
5354
|
+
const controlled = openProp !== void 0;
|
|
5355
|
+
const open = controlled ? openProp : openState;
|
|
5356
|
+
const triggerRef = React52__namespace.useRef(null);
|
|
5357
|
+
const ref = React52__namespace.useRef(null);
|
|
5358
|
+
const setOpen = React52__namespace.useCallback(
|
|
5359
|
+
(v) => {
|
|
5360
|
+
if (!controlled) setOpenState(v);
|
|
5361
|
+
onOpenChange?.(v);
|
|
5362
|
+
},
|
|
5363
|
+
[controlled, onOpenChange]
|
|
5364
|
+
);
|
|
5365
|
+
React52__namespace.useEffect(() => {
|
|
5366
|
+
if (!open) return;
|
|
5367
|
+
const onDoc = (e) => {
|
|
5368
|
+
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
5369
|
+
};
|
|
5370
|
+
const onEsc = (e) => {
|
|
5371
|
+
if (e.key === "Escape") {
|
|
5372
|
+
setOpen(false);
|
|
5373
|
+
triggerRef.current?.focus();
|
|
5374
|
+
}
|
|
5375
|
+
};
|
|
5376
|
+
document.addEventListener("mousedown", onDoc);
|
|
5377
|
+
document.addEventListener("keydown", onEsc);
|
|
5378
|
+
return () => {
|
|
5379
|
+
document.removeEventListener("mousedown", onDoc);
|
|
5380
|
+
document.removeEventListener("keydown", onEsc);
|
|
5381
|
+
};
|
|
5382
|
+
}, [open, setOpen]);
|
|
5383
|
+
const ctxValue = React52__namespace.useMemo(() => ({ open, setOpen, triggerRef }), [open, setOpen]);
|
|
5384
|
+
return /* @__PURE__ */ jsxRuntime.jsx(InboxContext.Provider, { value: ctxValue, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("relative inline-block", className), children }) });
|
|
5385
|
+
}
|
|
5386
|
+
function InboxTrigger({
|
|
5387
|
+
unreadCount,
|
|
5388
|
+
label = "Notifications",
|
|
5389
|
+
className,
|
|
5390
|
+
onClick,
|
|
5391
|
+
...props
|
|
5392
|
+
}) {
|
|
5393
|
+
const ctx = useInboxContext("InboxTrigger");
|
|
5394
|
+
const setRef = (node) => {
|
|
5395
|
+
ctx.triggerRef.current = node;
|
|
5396
|
+
};
|
|
5397
|
+
const displayCount = unreadCount == null || unreadCount <= 0 ? null : unreadCount > 99 ? "99+" : String(unreadCount);
|
|
5398
|
+
const defaultLabel = displayCount ? `${label} (${displayCount} unread)` : label;
|
|
5399
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5400
|
+
"button",
|
|
5401
|
+
{
|
|
5402
|
+
ref: setRef,
|
|
5403
|
+
type: "button",
|
|
5404
|
+
"aria-label": defaultLabel,
|
|
5405
|
+
"aria-haspopup": "dialog",
|
|
5406
|
+
"aria-expanded": ctx.open,
|
|
5407
|
+
className: cn(
|
|
5408
|
+
"relative inline-flex items-center justify-center w-9 h-9 rounded-full",
|
|
5409
|
+
"bg-surface border border-border text-muted-foreground",
|
|
5410
|
+
"hover:bg-muted hover:text-foreground transition-colors",
|
|
5411
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",
|
|
5412
|
+
className
|
|
5413
|
+
),
|
|
5414
|
+
onClick: (e) => {
|
|
5415
|
+
ctx.setOpen(!ctx.open);
|
|
5416
|
+
onClick?.(e);
|
|
5417
|
+
},
|
|
5418
|
+
...props,
|
|
5419
|
+
children: [
|
|
5420
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5421
|
+
"svg",
|
|
5422
|
+
{
|
|
5423
|
+
width: 16,
|
|
5424
|
+
height: 16,
|
|
5425
|
+
viewBox: "0 0 24 24",
|
|
5426
|
+
fill: "none",
|
|
5427
|
+
stroke: "currentColor",
|
|
5428
|
+
strokeWidth: 2,
|
|
5429
|
+
strokeLinecap: "round",
|
|
5430
|
+
strokeLinejoin: "round",
|
|
5431
|
+
"aria-hidden": "true",
|
|
5432
|
+
children: [
|
|
5433
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" }),
|
|
5434
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M13.73 21a2 2 0 0 1-3.46 0" })
|
|
5435
|
+
]
|
|
5436
|
+
}
|
|
5437
|
+
),
|
|
5438
|
+
displayCount != null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5439
|
+
"span",
|
|
5440
|
+
{
|
|
5441
|
+
"aria-hidden": "true",
|
|
5442
|
+
className: cn(
|
|
5443
|
+
"absolute -top-0.5 -right-0.5 min-w-[16px] h-4 px-1",
|
|
5444
|
+
"rounded-full bg-primary text-primary-foreground",
|
|
5445
|
+
"text-[9px] font-bold leading-4 flex items-center justify-center"
|
|
5446
|
+
),
|
|
5447
|
+
children: displayCount
|
|
5448
|
+
}
|
|
5449
|
+
)
|
|
5450
|
+
]
|
|
5451
|
+
}
|
|
5452
|
+
);
|
|
5453
|
+
}
|
|
5454
|
+
function NotificationItem({ item, onDismiss, className }) {
|
|
5455
|
+
const leadingSlot = item.avatarSrc ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5456
|
+
"img",
|
|
5457
|
+
{
|
|
5458
|
+
src: item.avatarSrc,
|
|
5459
|
+
alt: item.avatarFallback ?? "",
|
|
5460
|
+
className: "w-7 h-7 rounded-full object-cover flex-shrink-0"
|
|
5461
|
+
}
|
|
5462
|
+
) : item.avatarFallback ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-7 h-7 rounded-full bg-primary/20 text-primary text-[10px] font-bold flex items-center justify-center flex-shrink-0 select-none", children: item.avatarFallback }) : item.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-7 h-7 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0 text-primary", children: item.icon }) : null;
|
|
5463
|
+
const textBlock = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
5464
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-sm leading-snug", item.read ? "text-muted-foreground" : "text-foreground"), children: item.title }),
|
|
5465
|
+
item.body && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-0.5 truncate", children: item.body }),
|
|
5466
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-1", children: formatRelativeTime(item.timestamp) })
|
|
5467
|
+
] });
|
|
5468
|
+
const sharedClass = cn(
|
|
5469
|
+
"group relative flex items-start gap-2.5 px-3.5 py-2.5 w-full text-left",
|
|
5470
|
+
"border-b border-border last:border-0",
|
|
5471
|
+
!item.read && "bg-primary/[0.04]",
|
|
5472
|
+
"hover:bg-muted/50 transition-colors",
|
|
5473
|
+
className
|
|
5474
|
+
);
|
|
5475
|
+
const mainContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5476
|
+
leadingSlot,
|
|
5477
|
+
textBlock
|
|
5478
|
+
] });
|
|
5479
|
+
const mainAction = item.href ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5480
|
+
"a",
|
|
5481
|
+
{
|
|
5482
|
+
href: item.href,
|
|
5483
|
+
onClick: () => item.onClick?.(item.id),
|
|
5484
|
+
className: "flex-1 flex items-start gap-2.5 min-w-0 text-left outline-none",
|
|
5485
|
+
children: mainContent
|
|
5486
|
+
}
|
|
5487
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
5488
|
+
"button",
|
|
5489
|
+
{
|
|
5490
|
+
type: "button",
|
|
5491
|
+
onClick: () => item.onClick?.(item.id),
|
|
5492
|
+
className: "flex-1 flex items-start gap-2.5 min-w-0 text-left outline-none",
|
|
5493
|
+
children: mainContent
|
|
5494
|
+
}
|
|
5495
|
+
);
|
|
5496
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: sharedClass, children: [
|
|
5497
|
+
mainAction,
|
|
5498
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 flex-shrink-0 mt-0.5", children: [
|
|
5499
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5500
|
+
"button",
|
|
5501
|
+
{
|
|
5502
|
+
type: "button",
|
|
5503
|
+
"aria-label": "Dismiss",
|
|
5504
|
+
onClick: (e) => {
|
|
5505
|
+
e.preventDefault();
|
|
5506
|
+
e.stopPropagation();
|
|
5507
|
+
onDismiss?.(item.id);
|
|
5508
|
+
},
|
|
5509
|
+
className: cn(
|
|
5510
|
+
"text-muted-foreground hover:text-foreground transition-colors",
|
|
5511
|
+
"opacity-0 group-hover:opacity-100 focus:opacity-100",
|
|
5512
|
+
"text-base leading-none p-0.5 rounded"
|
|
5513
|
+
),
|
|
5514
|
+
children: "\xD7"
|
|
5515
|
+
}
|
|
5516
|
+
),
|
|
5517
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5518
|
+
"span",
|
|
5519
|
+
{
|
|
5520
|
+
"aria-label": item.read ? void 0 : "Unread",
|
|
5521
|
+
"aria-hidden": item.read ? true : void 0,
|
|
5522
|
+
className: cn(
|
|
5523
|
+
"w-[7px] h-[7px] rounded-full flex-shrink-0 mt-1",
|
|
5524
|
+
item.read ? "border border-border" : "bg-primary"
|
|
5525
|
+
)
|
|
5526
|
+
}
|
|
5527
|
+
)
|
|
5528
|
+
] })
|
|
5529
|
+
] });
|
|
5530
|
+
}
|
|
5531
|
+
function InboxContent({
|
|
5532
|
+
items,
|
|
5533
|
+
onMarkAllRead,
|
|
5534
|
+
onDismiss,
|
|
5535
|
+
viewAllHref,
|
|
5536
|
+
viewAllLabel = "View all notifications",
|
|
5537
|
+
emptyState,
|
|
5538
|
+
width = 360,
|
|
5539
|
+
maxHeight = 320,
|
|
5540
|
+
className
|
|
5541
|
+
}) {
|
|
5542
|
+
const ctx = useInboxContext("InboxContent");
|
|
5543
|
+
const ref = React52__namespace.useRef(null);
|
|
5544
|
+
React52__namespace.useEffect(() => {
|
|
5545
|
+
if (ctx.open) ref.current?.focus();
|
|
5546
|
+
}, [ctx.open]);
|
|
5547
|
+
if (!ctx.open) return null;
|
|
5548
|
+
const allRead = items.length === 0 || items.every((i) => i.read);
|
|
5549
|
+
const defaultEmptyState = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-10 px-5 text-center", children: [
|
|
5550
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-10 h-10 rounded-full bg-muted flex items-center justify-center mb-3 text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
5551
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" }),
|
|
5552
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M13.73 21a2 2 0 0 1-3.46 0" })
|
|
5553
|
+
] }) }),
|
|
5554
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-foreground", children: "All caught up" }),
|
|
5555
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: "No new notifications" })
|
|
5556
|
+
] });
|
|
5557
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5558
|
+
"div",
|
|
5559
|
+
{
|
|
5560
|
+
ref,
|
|
5561
|
+
role: "dialog",
|
|
5562
|
+
"aria-label": "Notifications",
|
|
5563
|
+
tabIndex: -1,
|
|
5564
|
+
style: { width },
|
|
5565
|
+
className: cn(
|
|
5566
|
+
"absolute right-0 top-[calc(100%+6px)] z-40",
|
|
5567
|
+
"bg-surface border border-border rounded-kj-md shadow-kj-lg outline-none",
|
|
5568
|
+
"animate-[kjpop_.12s_ease]",
|
|
5569
|
+
className
|
|
5570
|
+
),
|
|
5571
|
+
children: [
|
|
5572
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-3.5 py-2.5 border-b border-border", children: [
|
|
5573
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-foreground", children: "Notifications" }),
|
|
5574
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5575
|
+
"button",
|
|
5576
|
+
{
|
|
5577
|
+
type: "button",
|
|
5578
|
+
disabled: allRead,
|
|
5579
|
+
"aria-disabled": allRead,
|
|
5580
|
+
onClick: allRead ? void 0 : onMarkAllRead,
|
|
5581
|
+
className: cn(
|
|
5582
|
+
"text-xs font-medium transition-colors",
|
|
5583
|
+
allRead ? "text-muted-foreground cursor-not-allowed" : "text-primary hover:text-primary/80"
|
|
5584
|
+
),
|
|
5585
|
+
children: "Mark all read"
|
|
5586
|
+
}
|
|
5587
|
+
)
|
|
5588
|
+
] }),
|
|
5589
|
+
items.length === 0 ? emptyState ?? defaultEmptyState : /* @__PURE__ */ jsxRuntime.jsx(
|
|
5590
|
+
"div",
|
|
5591
|
+
{
|
|
5592
|
+
className: "overflow-y-auto",
|
|
5593
|
+
style: { maxHeight },
|
|
5594
|
+
children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5595
|
+
NotificationItem,
|
|
5596
|
+
{
|
|
5597
|
+
item,
|
|
5598
|
+
onDismiss
|
|
5599
|
+
},
|
|
5600
|
+
item.id
|
|
5601
|
+
))
|
|
5602
|
+
}
|
|
5603
|
+
),
|
|
5604
|
+
items.length > 0 && viewAllHref && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border px-3.5 py-2.5 text-center", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5605
|
+
"a",
|
|
5606
|
+
{
|
|
5607
|
+
href: viewAllHref,
|
|
5608
|
+
className: "text-xs font-medium text-primary hover:text-primary/80 transition-colors",
|
|
5609
|
+
children: [
|
|
5610
|
+
viewAllLabel,
|
|
5611
|
+
" \u2192"
|
|
5612
|
+
]
|
|
5613
|
+
}
|
|
5614
|
+
) })
|
|
5615
|
+
]
|
|
5616
|
+
}
|
|
5617
|
+
);
|
|
5618
|
+
}
|
|
5619
|
+
var DEFAULT_COLOR_SWATCHES = [
|
|
5620
|
+
"#EF4444",
|
|
5621
|
+
// Red
|
|
5622
|
+
"#F97316",
|
|
5623
|
+
// Orange
|
|
5624
|
+
"#F59E0B",
|
|
5625
|
+
// Amber
|
|
5626
|
+
"#10B981",
|
|
5627
|
+
// Emerald
|
|
5628
|
+
"#14B8A6",
|
|
5629
|
+
// Teal
|
|
5630
|
+
"#06B6D4",
|
|
5631
|
+
// Sky
|
|
5632
|
+
"#3B82F6",
|
|
5633
|
+
// Blue
|
|
5634
|
+
"#6366F1",
|
|
5635
|
+
// Indigo
|
|
5636
|
+
"#8B5CF6",
|
|
5637
|
+
// Purple
|
|
5638
|
+
"#EC4899",
|
|
5639
|
+
// Pink
|
|
5640
|
+
"#64748B",
|
|
5641
|
+
// Slate
|
|
5642
|
+
"#1E293B"
|
|
5643
|
+
// Charcoal
|
|
5644
|
+
];
|
|
5645
|
+
function isValidHex(hex) {
|
|
5646
|
+
const trimmed = hex.trim();
|
|
5647
|
+
const clean = trimmed.startsWith("#") ? trimmed.slice(1) : trimmed;
|
|
5648
|
+
return /^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(clean);
|
|
5649
|
+
}
|
|
5650
|
+
function normalizeHex(hex) {
|
|
5651
|
+
let clean = hex.trim();
|
|
5652
|
+
if (!clean.startsWith("#")) clean = `#${clean}`;
|
|
5653
|
+
if (/^#[0-9A-Fa-f]{3}$/.test(clean)) {
|
|
5654
|
+
clean = `#${clean[1]}${clean[1]}${clean[2]}${clean[2]}${clean[3]}${clean[3]}`;
|
|
5655
|
+
}
|
|
5656
|
+
return clean.toUpperCase();
|
|
5657
|
+
}
|
|
5658
|
+
function hexToHsl(hex) {
|
|
5659
|
+
if (!isValidHex(hex)) return { h: 0, s: 0, l: 0 };
|
|
5660
|
+
const normalized = normalizeHex(hex);
|
|
5661
|
+
const r = parseInt(normalized.slice(1, 3), 16) / 255;
|
|
5662
|
+
const g = parseInt(normalized.slice(3, 5), 16) / 255;
|
|
5663
|
+
const b = parseInt(normalized.slice(5, 7), 16) / 255;
|
|
5664
|
+
const max = Math.max(r, g, b);
|
|
5665
|
+
const min = Math.min(r, g, b);
|
|
5666
|
+
let h = 0;
|
|
5667
|
+
let s = 0;
|
|
5668
|
+
const l = (max + min) / 2;
|
|
5669
|
+
if (max !== min) {
|
|
5670
|
+
const d = max - min;
|
|
5671
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
5672
|
+
switch (max) {
|
|
5673
|
+
case r:
|
|
5674
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
5675
|
+
break;
|
|
5676
|
+
case g:
|
|
5677
|
+
h = (b - r) / d + 2;
|
|
5678
|
+
break;
|
|
5679
|
+
case b:
|
|
5680
|
+
h = (r - g) / d + 4;
|
|
5681
|
+
break;
|
|
5682
|
+
}
|
|
5683
|
+
h /= 6;
|
|
5684
|
+
}
|
|
5685
|
+
return {
|
|
5686
|
+
h: Math.round(h * 360),
|
|
5687
|
+
s: Math.round(s * 100),
|
|
5688
|
+
l: Math.round(l * 100)
|
|
5689
|
+
};
|
|
5690
|
+
}
|
|
5691
|
+
function hslToHex(h, s, l) {
|
|
5692
|
+
const normalizedH = (h % 360 + 360) % 360;
|
|
5693
|
+
const sPct = s / 100;
|
|
5694
|
+
const lPct = l / 100;
|
|
5695
|
+
const c = (1 - Math.abs(2 * lPct - 1)) * sPct;
|
|
5696
|
+
const x = c * (1 - Math.abs(normalizedH / 60 % 2 - 1));
|
|
5697
|
+
const m = lPct - c / 2;
|
|
5698
|
+
let r = 0;
|
|
5699
|
+
let g = 0;
|
|
5700
|
+
let b = 0;
|
|
5701
|
+
if (0 <= normalizedH && normalizedH < 60) {
|
|
5702
|
+
r = c;
|
|
5703
|
+
g = x;
|
|
5704
|
+
b = 0;
|
|
5705
|
+
} else if (60 <= normalizedH && normalizedH < 120) {
|
|
5706
|
+
r = x;
|
|
5707
|
+
g = c;
|
|
5708
|
+
b = 0;
|
|
5709
|
+
} else if (120 <= normalizedH && normalizedH < 180) {
|
|
5710
|
+
r = 0;
|
|
5711
|
+
g = c;
|
|
5712
|
+
b = x;
|
|
5713
|
+
} else if (180 <= normalizedH && normalizedH < 240) {
|
|
5714
|
+
r = 0;
|
|
5715
|
+
g = x;
|
|
5716
|
+
b = c;
|
|
5717
|
+
} else if (240 <= normalizedH && normalizedH < 300) {
|
|
5718
|
+
r = x;
|
|
5719
|
+
g = 0;
|
|
5720
|
+
b = c;
|
|
5721
|
+
} else if (300 <= normalizedH && normalizedH < 360) {
|
|
5722
|
+
r = c;
|
|
5723
|
+
g = 0;
|
|
5724
|
+
b = x;
|
|
5725
|
+
}
|
|
5726
|
+
const toHex = (n) => {
|
|
5727
|
+
const hex = Math.round((n + m) * 255).toString(16);
|
|
5728
|
+
return hex.length === 1 ? `0${hex}` : hex;
|
|
5729
|
+
};
|
|
5730
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`.toUpperCase();
|
|
5731
|
+
}
|
|
5732
|
+
var ColorPickerSwatch = React52__namespace.forwardRef(({ color, selected = false, size = "md", className, style, ...props }, ref) => {
|
|
5733
|
+
const sizeClasses2 = {
|
|
5734
|
+
sm: "w-5 h-5",
|
|
5735
|
+
md: "w-7 h-7",
|
|
5736
|
+
lg: "w-9 h-9"
|
|
5737
|
+
};
|
|
5738
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5739
|
+
"button",
|
|
5740
|
+
{
|
|
5741
|
+
ref,
|
|
5742
|
+
type: "button",
|
|
5743
|
+
"aria-pressed": selected,
|
|
5744
|
+
style: { backgroundColor: color, ...style },
|
|
5745
|
+
className: cn(
|
|
5746
|
+
"relative shrink-0 rounded-full border border-border/50 shadow-sm transition-transform hover:scale-110 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary flex items-center justify-center text-white text-xs font-bold",
|
|
5747
|
+
sizeClasses2[size],
|
|
5748
|
+
selected && "ring-2 ring-primary ring-offset-2 ring-offset-surface",
|
|
5749
|
+
className
|
|
5750
|
+
),
|
|
5751
|
+
...props,
|
|
5752
|
+
children: selected && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\u2713" })
|
|
5753
|
+
}
|
|
5754
|
+
);
|
|
5755
|
+
});
|
|
5756
|
+
ColorPickerSwatch.displayName = "ColorPickerSwatch";
|
|
5757
|
+
var ColorPicker = React52__namespace.forwardRef(
|
|
5758
|
+
({
|
|
5759
|
+
value,
|
|
5760
|
+
defaultValue = "#3B82F6",
|
|
5761
|
+
onChange,
|
|
5762
|
+
swatches = DEFAULT_COLOR_SWATCHES,
|
|
5763
|
+
disabled = false,
|
|
5764
|
+
showHexInput = true,
|
|
5765
|
+
className,
|
|
5766
|
+
...props
|
|
5767
|
+
}, ref) => {
|
|
5768
|
+
const isControlled = value !== void 0;
|
|
5769
|
+
const [localColor, setLocalColor] = React52__namespace.useState(
|
|
5770
|
+
normalizeHex(defaultValue)
|
|
5771
|
+
);
|
|
5772
|
+
const color = isControlled ? normalizeHex(value) : localColor;
|
|
5773
|
+
const [hexInputValue, setHexInputValue] = React52__namespace.useState(color);
|
|
5774
|
+
React52__namespace.useEffect(() => {
|
|
5775
|
+
setHexInputValue(color);
|
|
5776
|
+
}, [color]);
|
|
5777
|
+
const handleColorChange = React52__namespace.useCallback(
|
|
5778
|
+
(newHex) => {
|
|
5779
|
+
const normalized = normalizeHex(newHex);
|
|
5780
|
+
if (!isControlled) {
|
|
5781
|
+
setLocalColor(normalized);
|
|
5782
|
+
}
|
|
5783
|
+
onChange?.(normalized);
|
|
5784
|
+
},
|
|
5785
|
+
[isControlled, onChange]
|
|
5786
|
+
);
|
|
5787
|
+
const hsl = React52__namespace.useMemo(() => hexToHsl(color), [color]);
|
|
5788
|
+
const handleHueChange = (e) => {
|
|
5789
|
+
const h = Number(e.target.value);
|
|
5790
|
+
const s = hsl.s === 0 ? 100 : hsl.s;
|
|
5791
|
+
const l = hsl.s === 0 ? 50 : hsl.l;
|
|
5792
|
+
const newHex = hslToHex(h, s, l);
|
|
5793
|
+
handleColorChange(newHex);
|
|
5794
|
+
};
|
|
5795
|
+
const handleHexSubmit = () => {
|
|
5796
|
+
if (isValidHex(hexInputValue)) {
|
|
5797
|
+
handleColorChange(hexInputValue);
|
|
5798
|
+
} else {
|
|
5799
|
+
setHexInputValue(color);
|
|
5800
|
+
}
|
|
5801
|
+
};
|
|
5802
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("inline-block", className), ...props, children: /* @__PURE__ */ jsxRuntime.jsxs(Popover, { children: [
|
|
5803
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5804
|
+
"button",
|
|
5805
|
+
{
|
|
5806
|
+
type: "button",
|
|
5807
|
+
disabled,
|
|
5808
|
+
"aria-label": `Select color, current ${color}`,
|
|
5809
|
+
className: cn(
|
|
5810
|
+
"inline-flex items-center gap-2.5 px-3 py-1.5 rounded-kj-md border border-border bg-surface text-sm font-medium text-foreground transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary disabled:cursor-not-allowed disabled:opacity-50"
|
|
5811
|
+
),
|
|
5812
|
+
children: [
|
|
5813
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5814
|
+
"span",
|
|
5815
|
+
{
|
|
5816
|
+
style: { backgroundColor: color },
|
|
5817
|
+
className: "w-5 h-5 rounded-full border border-border/50 shadow-sm shrink-0"
|
|
5818
|
+
}
|
|
5819
|
+
),
|
|
5820
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-xs uppercase", children: color }),
|
|
5821
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5822
|
+
"svg",
|
|
5823
|
+
{
|
|
5824
|
+
width: 12,
|
|
5825
|
+
height: 12,
|
|
5826
|
+
viewBox: "0 0 24 24",
|
|
5827
|
+
fill: "none",
|
|
5828
|
+
stroke: "currentColor",
|
|
5829
|
+
strokeWidth: 2,
|
|
5830
|
+
className: "text-muted-foreground ml-auto",
|
|
5831
|
+
"aria-hidden": "true",
|
|
5832
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" })
|
|
5833
|
+
}
|
|
5834
|
+
)
|
|
5835
|
+
]
|
|
5836
|
+
}
|
|
5837
|
+
) }),
|
|
5838
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PopoverContent, { side: "bottom", align: "start", className: "w-64 p-3.5 space-y-3.5", children: [
|
|
5839
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 p-2 rounded-kj-md bg-muted/40 border border-border", children: [
|
|
5840
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5841
|
+
"span",
|
|
5842
|
+
{
|
|
5843
|
+
style: { backgroundColor: color },
|
|
5844
|
+
className: "w-8 h-8 rounded-full border border-border/50 shadow-sm shrink-0"
|
|
5845
|
+
}
|
|
5846
|
+
),
|
|
5847
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
5848
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Selected Color" }),
|
|
5849
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-mono font-bold text-foreground uppercase", children: color })
|
|
5850
|
+
] })
|
|
5851
|
+
] }),
|
|
5852
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
5853
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-semibold text-muted-foreground", children: "Preset Swatches" }),
|
|
5854
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-6 gap-2", children: swatches.map((swatch) => {
|
|
5855
|
+
const normalizedSwatch = normalizeHex(swatch);
|
|
5856
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5857
|
+
ColorPickerSwatch,
|
|
5858
|
+
{
|
|
5859
|
+
color: swatch,
|
|
5860
|
+
selected: normalizedSwatch === color,
|
|
5861
|
+
"aria-label": `Select color ${swatch}`,
|
|
5862
|
+
onClick: () => handleColorChange(swatch)
|
|
5863
|
+
},
|
|
5864
|
+
swatch
|
|
5865
|
+
);
|
|
5866
|
+
}) })
|
|
5867
|
+
] }),
|
|
5868
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
5869
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-semibold text-muted-foreground", children: "Hue" }),
|
|
5870
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5871
|
+
"input",
|
|
5872
|
+
{
|
|
5873
|
+
type: "range",
|
|
5874
|
+
min: 0,
|
|
5875
|
+
max: 360,
|
|
5876
|
+
value: hsl.h,
|
|
5877
|
+
onChange: handleHueChange,
|
|
5878
|
+
"aria-label": "Hue slider",
|
|
5879
|
+
className: "w-full h-3 rounded-full appearance-none cursor-pointer",
|
|
5880
|
+
style: {
|
|
5881
|
+
background: "linear-gradient(to right, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%)"
|
|
5882
|
+
}
|
|
5883
|
+
}
|
|
5884
|
+
)
|
|
5885
|
+
] }),
|
|
5886
|
+
showHexInput && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
5887
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-semibold text-muted-foreground", children: "Hex Code" }),
|
|
5888
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5889
|
+
"input",
|
|
5890
|
+
{
|
|
5891
|
+
type: "text",
|
|
5892
|
+
"aria-label": "Hex Code",
|
|
5893
|
+
value: hexInputValue,
|
|
5894
|
+
onChange: (e) => setHexInputValue(e.target.value),
|
|
5895
|
+
onBlur: handleHexSubmit,
|
|
5896
|
+
onKeyDown: (e) => {
|
|
5897
|
+
if (e.key === "Enter") handleHexSubmit();
|
|
5898
|
+
},
|
|
5899
|
+
placeholder: "#000000",
|
|
5900
|
+
className: "flex-1 px-2.5 py-1 text-xs font-mono rounded-kj-md border border-border bg-surface text-foreground uppercase focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary"
|
|
5901
|
+
}
|
|
5902
|
+
) })
|
|
5903
|
+
] })
|
|
5904
|
+
] })
|
|
5905
|
+
] }) });
|
|
5906
|
+
}
|
|
5907
|
+
);
|
|
5908
|
+
ColorPicker.displayName = "ColorPicker";
|
|
5909
|
+
var ColorPickerField = React52__namespace.forwardRef(({ label, hint, error, required, ...props }, ref) => {
|
|
5910
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Field, { children: [
|
|
5911
|
+
label && /* @__PURE__ */ jsxRuntime.jsx(Label, { required, children: label }),
|
|
5912
|
+
/* @__PURE__ */ jsxRuntime.jsx(ColorPicker, { ref, ...props }),
|
|
5913
|
+
hint && /* @__PURE__ */ jsxRuntime.jsx(Hint, { children: hint }),
|
|
5914
|
+
error && /* @__PURE__ */ jsxRuntime.jsx(Hint, { error: true, children: error })
|
|
5915
|
+
] });
|
|
5916
|
+
});
|
|
5917
|
+
ColorPickerField.displayName = "ColorPickerField";
|
|
5918
|
+
var COLUMN_CLASSES = {
|
|
5919
|
+
2: "grid-cols-2",
|
|
5920
|
+
3: "grid-cols-3",
|
|
5921
|
+
4: "grid-cols-4",
|
|
5922
|
+
5: "grid-cols-5"
|
|
5923
|
+
};
|
|
5924
|
+
var ASPECT_CLASSES = {
|
|
5925
|
+
square: "aspect-square",
|
|
5926
|
+
video: "aspect-video",
|
|
5927
|
+
"4/3": "aspect-[4/3]",
|
|
5928
|
+
auto: "aspect-auto"
|
|
5929
|
+
};
|
|
5930
|
+
function ImageGallery({
|
|
5931
|
+
images = [],
|
|
5932
|
+
columns = 3,
|
|
5933
|
+
aspectRatio = "square",
|
|
5934
|
+
maxVisible,
|
|
5935
|
+
className,
|
|
5936
|
+
thumbnailClassName,
|
|
5937
|
+
lightboxClassName,
|
|
5938
|
+
onImageClick
|
|
5939
|
+
}) {
|
|
5940
|
+
const [selectedIndex, setSelectedIndex] = React52__namespace.useState(null);
|
|
5941
|
+
const columnClass = COLUMN_CLASSES[columns] || "grid-cols-3";
|
|
5942
|
+
const aspectClass = ASPECT_CLASSES[aspectRatio] || (aspectRatio.startsWith("aspect-") ? aspectRatio : `aspect-[${aspectRatio}]`);
|
|
5943
|
+
const hasMaxVisible = typeof maxVisible === "number" && maxVisible > 0 && images.length > maxVisible;
|
|
5944
|
+
const visibleImages = hasMaxVisible ? images.slice(0, maxVisible) : images;
|
|
5945
|
+
const remainingCount = hasMaxVisible ? images.length - maxVisible + 1 : 0;
|
|
5946
|
+
const handleThumbnailClick = (index) => {
|
|
5947
|
+
setSelectedIndex(index);
|
|
5948
|
+
if (onImageClick) {
|
|
5949
|
+
onImageClick(index);
|
|
5950
|
+
}
|
|
5951
|
+
};
|
|
5952
|
+
const handleClose = React52__namespace.useCallback(() => {
|
|
5953
|
+
setSelectedIndex(null);
|
|
5954
|
+
}, []);
|
|
5955
|
+
const handleNext = React52__namespace.useCallback(() => {
|
|
5956
|
+
setSelectedIndex((prev) => prev === null ? null : (prev + 1) % images.length);
|
|
5957
|
+
}, [images.length]);
|
|
5958
|
+
const handlePrev = React52__namespace.useCallback(() => {
|
|
5959
|
+
setSelectedIndex((prev) => prev === null ? null : (prev - 1 + images.length) % images.length);
|
|
5960
|
+
}, [images.length]);
|
|
5961
|
+
React52__namespace.useEffect(() => {
|
|
5962
|
+
if (selectedIndex === null) return;
|
|
5963
|
+
const originalOverflow = document.body.style.overflow;
|
|
5964
|
+
const handleKeyDown = (e) => {
|
|
5965
|
+
if (e.key === "Escape") {
|
|
5966
|
+
handleClose();
|
|
5967
|
+
} else if (e.key === "ArrowRight") {
|
|
5968
|
+
handleNext();
|
|
5969
|
+
} else if (e.key === "ArrowLeft") {
|
|
5970
|
+
handlePrev();
|
|
5971
|
+
}
|
|
5972
|
+
};
|
|
5973
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
5974
|
+
document.body.style.overflow = "hidden";
|
|
5975
|
+
return () => {
|
|
5976
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
5977
|
+
document.body.style.overflow = originalOverflow;
|
|
5978
|
+
};
|
|
5979
|
+
}, [selectedIndex, handleClose, handleNext, handlePrev]);
|
|
5980
|
+
const activeImage = selectedIndex !== null ? images[selectedIndex] : null;
|
|
5981
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5982
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid gap-3 w-full", columnClass, className), children: visibleImages.map((img, idx) => {
|
|
5983
|
+
const isLastOverlay = hasMaxVisible && idx === maxVisible - 1;
|
|
5984
|
+
const thumbSrc = img.thumbnailSrc || img.src;
|
|
5985
|
+
const defaultAlt = img.alt || `Thumbnail ${idx + 1}`;
|
|
5986
|
+
const buttonAriaLabel = isLastOverlay ? `View all ${images.length} images` : defaultAlt;
|
|
5987
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5988
|
+
"button",
|
|
5989
|
+
{
|
|
5990
|
+
type: "button",
|
|
5991
|
+
"aria-label": buttonAriaLabel,
|
|
5992
|
+
onClick: () => handleThumbnailClick(idx),
|
|
5993
|
+
className: cn(
|
|
5994
|
+
"relative group overflow-hidden rounded-kj-lg bg-muted focus:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 cursor-pointer transition-all duration-200",
|
|
5995
|
+
aspectClass,
|
|
5996
|
+
thumbnailClassName
|
|
5997
|
+
),
|
|
5998
|
+
children: [
|
|
5999
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6000
|
+
"img",
|
|
6001
|
+
{
|
|
6002
|
+
src: thumbSrc,
|
|
6003
|
+
alt: img.alt || `Thumbnail ${idx + 1}`,
|
|
6004
|
+
className: "w-full h-full object-cover transition-transform duration-300 group-hover:scale-105"
|
|
6005
|
+
}
|
|
6006
|
+
),
|
|
6007
|
+
isLastOverlay && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 bg-black/60 backdrop-blur-[2px] flex items-center justify-center text-white font-bold text-xl group-hover:bg-black/70 transition-colors", children: [
|
|
6008
|
+
"+",
|
|
6009
|
+
remainingCount
|
|
6010
|
+
] })
|
|
6011
|
+
]
|
|
6012
|
+
},
|
|
6013
|
+
idx
|
|
6014
|
+
);
|
|
6015
|
+
}) }),
|
|
6016
|
+
selectedIndex !== null && activeImage && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6017
|
+
"div",
|
|
6018
|
+
{
|
|
6019
|
+
role: "dialog",
|
|
6020
|
+
"aria-modal": "true",
|
|
6021
|
+
"aria-label": "Image gallery lightbox",
|
|
6022
|
+
onClick: (e) => e.target === e.currentTarget && handleClose(),
|
|
6023
|
+
className: cn(
|
|
6024
|
+
"fixed inset-0 z-[100] bg-black/85 backdrop-blur-md flex flex-col justify-between p-4 sm:p-6 transition-opacity duration-200 animate-in fade-in-0",
|
|
6025
|
+
lightboxClassName
|
|
6026
|
+
),
|
|
6027
|
+
children: [
|
|
6028
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between w-full text-white z-10", children: [
|
|
6029
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-medium text-white/80 select-none", children: [
|
|
6030
|
+
selectedIndex + 1,
|
|
6031
|
+
" of ",
|
|
6032
|
+
images.length
|
|
6033
|
+
] }),
|
|
6034
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6035
|
+
"button",
|
|
6036
|
+
{
|
|
6037
|
+
type: "button",
|
|
6038
|
+
onClick: handleClose,
|
|
6039
|
+
"aria-label": "Close",
|
|
6040
|
+
className: "p-2 rounded-full text-white/80 hover:text-white hover:bg-white/10 transition-colors cursor-pointer",
|
|
6041
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: 20, height: 20, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) })
|
|
6042
|
+
}
|
|
6043
|
+
)
|
|
6044
|
+
] }),
|
|
6045
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1 flex items-center justify-between gap-4 my-auto min-h-0 w-full", children: [
|
|
6046
|
+
images.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6047
|
+
"button",
|
|
6048
|
+
{
|
|
6049
|
+
type: "button",
|
|
6050
|
+
onClick: handlePrev,
|
|
6051
|
+
"aria-label": "Previous image",
|
|
6052
|
+
className: "p-3 rounded-full text-white/80 hover:text-white hover:bg-white/10 transition-colors cursor-pointer z-10 shrink-0",
|
|
6053
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" }) })
|
|
6054
|
+
}
|
|
6055
|
+
),
|
|
6056
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex flex-col items-center justify-center h-full min-h-0 px-2 select-none", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6057
|
+
"img",
|
|
6058
|
+
{
|
|
6059
|
+
src: activeImage.src,
|
|
6060
|
+
alt: activeImage.alt || `Image ${selectedIndex + 1}`,
|
|
6061
|
+
className: "max-h-[70vh] max-w-full object-contain rounded-kj-md shadow-2xl transition-transform"
|
|
6062
|
+
}
|
|
6063
|
+
) }),
|
|
6064
|
+
images.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6065
|
+
"button",
|
|
6066
|
+
{
|
|
6067
|
+
type: "button",
|
|
6068
|
+
onClick: handleNext,
|
|
6069
|
+
"aria-label": "Next image",
|
|
6070
|
+
className: "p-3 rounded-full text-white/80 hover:text-white hover:bg-white/10 transition-colors cursor-pointer z-10 shrink-0",
|
|
6071
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" }) })
|
|
6072
|
+
}
|
|
6073
|
+
)
|
|
6074
|
+
] }),
|
|
6075
|
+
(activeImage.title || activeImage.caption) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center text-center text-white pb-2 z-10", children: [
|
|
6076
|
+
activeImage.title && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold text-white", children: activeImage.title }),
|
|
6077
|
+
activeImage.caption && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs sm:text-sm text-white/70 max-w-lg mt-0.5", children: activeImage.caption })
|
|
6078
|
+
] })
|
|
6079
|
+
]
|
|
6080
|
+
}
|
|
6081
|
+
)
|
|
6082
|
+
] });
|
|
6083
|
+
}
|
|
2499
6084
|
|
|
2500
6085
|
exports.Accordion = Accordion;
|
|
2501
6086
|
exports.AccordionContent = AccordionContent;
|
|
2502
6087
|
exports.AccordionItem = AccordionItem;
|
|
2503
6088
|
exports.AccordionTrigger = AccordionTrigger;
|
|
2504
6089
|
exports.Alert = Alert;
|
|
6090
|
+
exports.AppShell = AppShell;
|
|
6091
|
+
exports.AppShellBanner = AppShellBanner;
|
|
6092
|
+
exports.AppShellFooter = AppShellFooter;
|
|
6093
|
+
exports.AppShellHeader = AppShellHeader;
|
|
6094
|
+
exports.AppShellMain = AppShellMain;
|
|
2505
6095
|
exports.Avatar = Avatar;
|
|
2506
6096
|
exports.AvatarGroup = AvatarGroup;
|
|
2507
6097
|
exports.Badge = Badge;
|
|
6098
|
+
exports.BlogCard = BlogCard;
|
|
2508
6099
|
exports.BottomNavigation = BottomNavigation;
|
|
2509
6100
|
exports.BottomSheet = BottomSheet;
|
|
2510
6101
|
exports.BottomSheetContent = BottomSheetContent;
|
|
@@ -2516,6 +6107,7 @@ exports.Breadcrumb = Breadcrumb;
|
|
|
2516
6107
|
exports.BreadcrumbItem = BreadcrumbItem;
|
|
2517
6108
|
exports.BreadcrumbSeparator = BreadcrumbSeparator;
|
|
2518
6109
|
exports.Button = Button;
|
|
6110
|
+
exports.Calendar = Calendar;
|
|
2519
6111
|
exports.Card = Card;
|
|
2520
6112
|
exports.CardContent = CardContent;
|
|
2521
6113
|
exports.CardDescription = CardDescription;
|
|
@@ -2525,10 +6117,20 @@ exports.CardTitle = CardTitle;
|
|
|
2525
6117
|
exports.Checkbox = Checkbox;
|
|
2526
6118
|
exports.CheckboxField = CheckboxField;
|
|
2527
6119
|
exports.CodeBlock = CodeBlock;
|
|
6120
|
+
exports.ColorPicker = ColorPicker;
|
|
6121
|
+
exports.ColorPickerField = ColorPickerField;
|
|
6122
|
+
exports.ColorPickerSwatch = ColorPickerSwatch;
|
|
6123
|
+
exports.Combobox = Combobox;
|
|
6124
|
+
exports.ComboboxField = ComboboxField;
|
|
2528
6125
|
exports.CommandPalette = CommandPalette;
|
|
2529
6126
|
exports.ConfirmDialog = ConfirmDialog;
|
|
6127
|
+
exports.DEFAULT_COLOR_SWATCHES = DEFAULT_COLOR_SWATCHES;
|
|
2530
6128
|
exports.DashboardShell = DashboardShell;
|
|
2531
6129
|
exports.DataTable = DataTable;
|
|
6130
|
+
exports.DatePicker = DatePicker;
|
|
6131
|
+
exports.DatePickerField = DatePickerField;
|
|
6132
|
+
exports.DateRangePicker = DateRangePicker;
|
|
6133
|
+
exports.DateRangePickerField = DateRangePickerField;
|
|
2532
6134
|
exports.DetailPageLayout = DetailPageLayout;
|
|
2533
6135
|
exports.Drawer = Drawer;
|
|
2534
6136
|
exports.DropdownMenu = DropdownMenu;
|
|
@@ -2536,12 +6138,19 @@ exports.DropdownMenuContent = DropdownMenuContent;
|
|
|
2536
6138
|
exports.DropdownMenuItem = DropdownMenuItem;
|
|
2537
6139
|
exports.DropdownMenuSeparator = DropdownMenuSeparator;
|
|
2538
6140
|
exports.DropdownMenuTrigger = DropdownMenuTrigger;
|
|
6141
|
+
exports.Dropzone = Dropzone;
|
|
2539
6142
|
exports.EmptyState = EmptyState;
|
|
2540
6143
|
exports.ErrorState = ErrorState;
|
|
2541
6144
|
exports.Fab = Fab;
|
|
2542
6145
|
exports.Field = Field;
|
|
6146
|
+
exports.FileUpload = FileUpload;
|
|
6147
|
+
exports.FileUploadField = FileUploadField;
|
|
2543
6148
|
exports.FormField = FormField;
|
|
2544
6149
|
exports.Hint = Hint;
|
|
6150
|
+
exports.ImageGallery = ImageGallery;
|
|
6151
|
+
exports.InboxContent = InboxContent;
|
|
6152
|
+
exports.InboxPopover = InboxPopover;
|
|
6153
|
+
exports.InboxTrigger = InboxTrigger;
|
|
2545
6154
|
exports.Input = Input;
|
|
2546
6155
|
exports.Kbd = Kbd;
|
|
2547
6156
|
exports.Label = Label;
|
|
@@ -2550,22 +6159,42 @@ exports.Modal = Modal;
|
|
|
2550
6159
|
exports.ModalActions = ModalActions;
|
|
2551
6160
|
exports.ModalDescription = ModalDescription;
|
|
2552
6161
|
exports.ModalTitle = ModalTitle;
|
|
6162
|
+
exports.NotificationItem = NotificationItem;
|
|
2553
6163
|
exports.PageHeader = PageHeader;
|
|
2554
6164
|
exports.Pagination = Pagination;
|
|
2555
6165
|
exports.Popover = Popover;
|
|
2556
6166
|
exports.PopoverContent = PopoverContent;
|
|
2557
6167
|
exports.PopoverTrigger = PopoverTrigger;
|
|
6168
|
+
exports.PricingCard = PricingCard;
|
|
2558
6169
|
exports.Progress = Progress;
|
|
6170
|
+
exports.ProgressRing = ProgressRing;
|
|
6171
|
+
exports.ProgressRingField = ProgressRingField;
|
|
6172
|
+
exports.ProjectCard = ProjectCard;
|
|
2559
6173
|
exports.Radio = Radio;
|
|
6174
|
+
exports.RangeCalendar = RangeCalendar;
|
|
6175
|
+
exports.Rating = Rating;
|
|
6176
|
+
exports.RatingField = RatingField;
|
|
6177
|
+
exports.RatingSummary = RatingSummary;
|
|
6178
|
+
exports.SectionHeader = SectionHeader;
|
|
2560
6179
|
exports.Segmented = Segmented;
|
|
2561
6180
|
exports.Select = Select;
|
|
2562
6181
|
exports.SelectField = SelectField;
|
|
6182
|
+
exports.Separator = Separator;
|
|
2563
6183
|
exports.SettingsLayout = SettingsLayout;
|
|
2564
6184
|
exports.SidebarNav = SidebarNav;
|
|
2565
6185
|
exports.Skeleton = Skeleton;
|
|
2566
6186
|
exports.Slider = Slider;
|
|
2567
6187
|
exports.Spinner = Spinner;
|
|
2568
6188
|
exports.Stat = Stat;
|
|
6189
|
+
exports.Stepper = Stepper;
|
|
6190
|
+
exports.StepperContent = StepperContent;
|
|
6191
|
+
exports.StepperDescription = StepperDescription;
|
|
6192
|
+
exports.StepperIndicator = StepperIndicator;
|
|
6193
|
+
exports.StepperItem = StepperItem;
|
|
6194
|
+
exports.StepperList = StepperList;
|
|
6195
|
+
exports.StepperSeparator = StepperSeparator;
|
|
6196
|
+
exports.StepperTitle = StepperTitle;
|
|
6197
|
+
exports.StepperTrigger = StepperTrigger;
|
|
2569
6198
|
exports.Switch = Switch;
|
|
2570
6199
|
exports.Table = Table;
|
|
2571
6200
|
exports.TableBody = TableBody;
|
|
@@ -2581,12 +6210,28 @@ exports.TabsList = TabsList;
|
|
|
2581
6210
|
exports.TabsTrigger = TabsTrigger;
|
|
2582
6211
|
exports.TextField = TextField;
|
|
2583
6212
|
exports.Textarea = Textarea;
|
|
6213
|
+
exports.Timeline = Timeline;
|
|
6214
|
+
exports.TimelineConnector = TimelineConnector;
|
|
6215
|
+
exports.TimelineContent = TimelineContent;
|
|
6216
|
+
exports.TimelineDot = TimelineDot;
|
|
6217
|
+
exports.TimelineItem = TimelineItem;
|
|
6218
|
+
exports.TimelineSeparator = TimelineSeparator;
|
|
6219
|
+
exports.TimelineTime = TimelineTime;
|
|
6220
|
+
exports.TimelineTitle = TimelineTitle;
|
|
2584
6221
|
exports.ToastProvider = ToastProvider;
|
|
6222
|
+
exports.ToggleGroup = ToggleGroup;
|
|
2585
6223
|
exports.Tooltip = Tooltip;
|
|
2586
6224
|
exports.badgeVariants = badgeVariants;
|
|
2587
6225
|
exports.buttonVariants = buttonVariants;
|
|
2588
6226
|
exports.cn = cn;
|
|
6227
|
+
exports.formatRelativeTime = formatRelativeTime;
|
|
6228
|
+
exports.hexToHsl = hexToHsl;
|
|
6229
|
+
exports.hslToHex = hslToHex;
|
|
6230
|
+
exports.isValidHex = isValidHex;
|
|
6231
|
+
exports.normalizeHex = normalizeHex;
|
|
2589
6232
|
exports.sliderThumbCSS = sliderThumbCSS;
|
|
6233
|
+
exports.useInboxState = useInboxState;
|
|
6234
|
+
exports.useStepper = useStepper;
|
|
2590
6235
|
exports.useToast = useToast;
|
|
2591
6236
|
//# sourceMappingURL=index.cjs.map
|
|
2592
6237
|
//# sourceMappingURL=index.cjs.map
|