@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/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 React18 = require('react');
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 React18__namespace = /*#__PURE__*/_interopNamespace(React18);
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
217
+ var FormField = React52__namespace.forwardRef(
217
218
  ({ className, label, hint, error, required, children, ...props }, ref) => {
218
- const id = React18__namespace.useId();
219
+ const id = React52__namespace.useId();
219
220
  const hintId = `${id}-hint`;
220
221
  const errorId = `${id}-error`;
221
- const child = React18__namespace.Children.only(children);
222
- const clonedChild = React18__namespace.cloneElement(child, {
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 = React18__namespace.forwardRef(
243
- ({ className, error, leadingIcon, style, ...props }, ref) => {
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
453
+ var Checkbox = React52__namespace.forwardRef(
326
454
  ({ className, label, id, ...props }, ref) => {
327
- const autoId = React18__namespace.useId();
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 = React18__namespace.forwardRef(
465
+ var Radio = React52__namespace.forwardRef(
338
466
  ({ className, label, id, ...props }, ref) => {
339
- const autoId = React18__namespace.useId();
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 = React18__namespace.forwardRef(
477
+ var CheckboxField = React52__namespace.forwardRef(
350
478
  ({ label, hint, error, className, ...props }, ref) => {
351
- const id = React18__namespace.useId();
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 = React18__namespace.forwardRef(
500
+ var Switch = React52__namespace.forwardRef(
373
501
  ({ className, label, id, ...props }, ref) => {
374
- const autoId = React18__namespace.useId();
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 = React18__namespace.forwardRef(
385
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
386
- "input",
387
- {
388
- ref,
389
- type: "range",
390
- className: cn(
391
- "kj-slider w-full h-1.5 rounded-full bg-input appearance-none cursor-pointer",
392
- className
393
- ),
394
- ...props
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
- var Card = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.createContext(null);
731
+ var TabsContext = React52__namespace.createContext(null);
536
732
  function useTabs() {
537
- const ctx = React18__namespace.useContext(TabsContext);
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] = React18__namespace.useState(defaultValue ?? "");
543
- const uid = React18__namespace.useId();
738
+ const [internal, setInternal] = React52__namespace.useState(defaultValue ?? "");
739
+ const uid = React52__namespace.useId();
544
740
  const current = value ?? internal;
545
- const setValue = React18__namespace.useCallback(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.createContext(null);
846
+ var AccordionContext = React52__namespace.createContext(null);
651
847
  function Accordion({ type = "single", defaultValue = [], className, children, ...props }) {
652
- const [open, setOpen] = React18__namespace.useState(defaultValue);
653
- const toggle = React18__namespace.useCallback(
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 = React18__namespace.createContext("");
666
- var AccordionItem = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
866
+ var AccordionTrigger = React52__namespace.forwardRef(
671
867
  ({ className, children, ...props }, ref) => {
672
- const ctx = React18__namespace.useContext(AccordionContext);
673
- const value = React18__namespace.useContext(ItemContext);
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 = React18__namespace.forwardRef(
906
+ var AccordionContent = React52__namespace.forwardRef(
711
907
  ({ className, children, ...props }, ref) => {
712
- const ctx = React18__namespace.useContext(AccordionContext);
713
- const value = React18__namespace.useContext(ItemContext);
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 = React18__namespace.createContext(null);
923
+ var MenuContext = React52__namespace.createContext(null);
728
924
  function DropdownMenu({ children, className }) {
729
- const [open, setOpen] = React18__namespace.useState(false);
730
- const ref = React18__namespace.useRef(null);
731
- React18__namespace.useEffect(() => {
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 = React18__namespace.forwardRef(({ onClick, asChild, ...props }, ref) => {
747
- const ctx = React18__namespace.useContext(MenuContext);
942
+ var DropdownMenuTrigger = React52__namespace.forwardRef(({ onClick, asChild, ...props }, ref) => {
943
+ const ctx = React52__namespace.useContext(MenuContext);
748
944
  if (asChild) {
749
- const child = React18__namespace.Children.only(props.children);
750
- return React18__namespace.cloneElement(child, {
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 = React18__namespace.useContext(MenuContext);
781
- const ref = React18__namespace.useRef(null);
782
- React18__namespace.useEffect(() => {
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 = React18__namespace.forwardRef(
1025
+ var DropdownMenuItem = React52__namespace.forwardRef(
830
1026
  ({ className, danger, icon, children, onClick, ...props }, ref) => {
831
- const ctx = React18__namespace.useContext(MenuContext);
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("relative inline-flex group", className), tabIndex: 0, children: [
1036
- children,
1037
- /* @__PURE__ */ jsxRuntime.jsx(
1038
- "span",
1039
- {
1040
- role: "tooltip",
1041
- className: cn(
1042
- "pointer-events-none absolute bottom-[calc(100%+8px)] left-1/2 -translate-x-1/2 translate-y-1 whitespace-nowrap",
1043
- "rounded-kj-sm bg-foreground text-background text-xs font-medium px-2.5 py-1.5 shadow-kj-md",
1044
- "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",
1045
- "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"
1046
- ),
1047
- children: content
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 = React18__namespace.createContext(null);
1251
+ var ModalContext = React52__namespace.createContext(null);
1053
1252
  function Modal({ open, onClose, children, width = 440, className, showClose = true }) {
1054
- const titleId = React18__namespace.useId();
1055
- const descId = React18__namespace.useId();
1056
- const containerRef = React18__namespace.useRef(null);
1057
- const lastActiveElement = React18__namespace.useRef(null);
1058
- React18__namespace.useEffect(() => {
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 = React18__namespace.useContext(ModalContext);
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 = React18__namespace.useContext(ModalContext);
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 = React18__namespace.createContext(null);
1369
+ var ToastContext = React52__namespace.createContext(null);
1171
1370
  function useToast() {
1172
- const ctx = React18__namespace.useContext(ToastContext);
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] = React18__namespace.useState([]);
1194
- const idRef = React18__namespace.useRef(0);
1195
- const remove = React18__namespace.useCallback((id) => {
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 = React18__namespace.useCallback(
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 = React18__namespace.forwardRef(
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 EmptyState = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.useCallback(
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 = React18__namespace.useMemo(() => {
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 = React18__namespace.useMemo(() => {
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 = React18__namespace.useRef(null);
1316
- React18__namespace.useEffect(() => {
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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] = React18__namespace.useState(false);
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
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 = React18__namespace.useRef(null);
1746
- const lastActiveElement = React18__namespace.useRef(null);
1747
- React18__namespace.useEffect(() => {
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] = React18__namespace.useState("");
1867
- const [activeIndex, setActiveIndex] = React18__namespace.useState(0);
1868
- const containerRef = React18__namespace.useRef(null);
1869
- const listRef = React18__namespace.useRef(null);
1870
- React18__namespace.useEffect(() => {
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 = React18__namespace.useMemo(() => {
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
- React18__namespace.useEffect(() => {
2189
+ React52__namespace.useEffect(() => {
1887
2190
  setActiveIndex(0);
1888
2191
  }, [filteredItems]);
1889
- React18__namespace.useEffect(() => {
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
- React18__namespace.useEffect(() => {
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 = React18__namespace.forwardRef(
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 = React18__namespace.createContext(null);
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 = React18__namespace.useId();
2153
- const descId = React18__namespace.useId();
2154
- const containerRef = React18__namespace.useRef(null);
2155
- const lastActiveElement = React18__namespace.useRef(null);
2156
- const [mounted, setMounted] = React18__namespace.useState(open);
2157
- React18__namespace.useEffect(() => {
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
- React18__namespace.useEffect(() => {
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 = React18__namespace.useContext(BottomSheetContext);
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 = React18__namespace.useContext(BottomSheetContext);
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 = React18__namespace.forwardRef(
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 = React18__namespace.forwardRef(
2633
+ var CodeBlock = React52__namespace.forwardRef(
2331
2634
  ({ className, code, language, filename, copyable = true, maxHeight, ...props }, ref) => {
2332
- const [copied, setCopied] = React18__namespace.useState(false);
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
- var PopoverContext = React18__namespace.createContext(null);
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 = React18__namespace.useContext(PopoverContext);
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] = React18__namespace.useState(false);
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 = React18__namespace.useRef(null);
2389
- const ref = React18__namespace.useRef(null);
2390
- const setOpen = React18__namespace.useCallback(
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
- React18__namespace.useEffect(() => {
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 = React18__namespace.forwardRef(({ onClick, asChild, ...props }, ref) => {
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 = React18__namespace.Children.only(props.children);
2426
- return React18__namespace.cloneElement(child, {
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 = React18__namespace.useRef(null);
2478
- React18__namespace.useEffect(() => {
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