@yomologic/react-ui 0.2.5 → 0.2.6

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.js CHANGED
@@ -47,11 +47,14 @@ __export(index_exports, {
47
47
  Dropdown: () => Dropdown,
48
48
  EmptyState: () => EmptyState,
49
49
  Input: () => Input,
50
+ Nav: () => Nav,
50
51
  RadioGroup: () => RadioGroup,
51
52
  SectionLayout: () => SectionLayout,
52
53
  SidebarNav: () => SidebarNav,
53
54
  Spinner: () => Spinner,
54
- cn: () => cn
55
+ ThemeProvider: () => ThemeProvider,
56
+ cn: () => cn,
57
+ useTheme: () => useTheme
55
58
  });
56
59
  module.exports = __toCommonJS(index_exports);
57
60
 
@@ -87,9 +90,11 @@ var Button = import_react.default.forwardRef(
87
90
  danger: "[background-color:var(--color-error)] text-white hover:bg-red-700 focus:[--tw-ring-color:var(--color-error)]"
88
91
  };
89
92
  const sizes = {
90
- sm: "[font-size:var(--button-text-sm)] [padding-left:var(--button-padding-sm-x)] [padding-right:var(--button-padding-sm-x)] [padding-top:var(--button-padding-sm-y)] [padding-bottom:var(--button-padding-sm-y)] gap-1.5",
91
- md: "[font-size:var(--button-text-md)] [padding-left:var(--button-padding-md-x)] [padding-right:var(--button-padding-md-x)] [padding-top:var(--button-padding-md-y)] [padding-bottom:var(--button-padding-md-y)] gap-2",
92
- lg: "[font-size:var(--button-text-lg)] [padding-left:var(--button-padding-lg-x)] [padding-right:var(--button-padding-lg-x)] [padding-top:var(--button-padding-lg-y)] [padding-bottom:var(--button-padding-lg-y)] gap-2.5"
93
+ xs: "[font-size:var(--button-font-size-xs)] [padding-left:var(--button-padding-xs-x)] [padding-right:var(--button-padding-xs-x)] [padding-top:var(--button-padding-xs-y)] [padding-bottom:var(--button-padding-xs-y)] gap-1",
94
+ sm: "[font-size:var(--button-font-size-sm)] [padding-left:var(--button-padding-sm-x)] [padding-right:var(--button-padding-sm-x)] [padding-top:var(--button-padding-sm-y)] [padding-bottom:var(--button-padding-sm-y)] gap-1.5",
95
+ md: "[font-size:var(--button-font-size-md)] [padding-left:var(--button-padding-md-x)] [padding-right:var(--button-padding-md-x)] [padding-top:var(--button-padding-md-y)] [padding-bottom:var(--button-padding-md-y)] gap-2",
96
+ lg: "[font-size:var(--button-font-size-lg)] [padding-left:var(--button-padding-lg-x)] [padding-right:var(--button-padding-lg-x)] [padding-top:var(--button-padding-lg-y)] [padding-bottom:var(--button-padding-lg-y)] gap-2.5",
97
+ xl: "[font-size:var(--button-font-size-xl)] [padding-left:var(--button-padding-xl-x)] [padding-right:var(--button-padding-xl-x)] [padding-top:var(--button-padding-xl-y)] [padding-bottom:var(--button-padding-xl-y)] gap-3"
93
98
  };
94
99
  const radiusStyle = "[border-radius:var(--button-radius)]";
95
100
  const fontWeightStyle = "[font-weight:var(--button-font-weight)]";
@@ -164,7 +169,8 @@ var Input = import_react2.default.forwardRef(
164
169
  id,
165
170
  ...props
166
171
  }, ref) => {
167
- const inputId = id || label?.toLowerCase().replace(/\s+/g, "-");
172
+ const autoId = (0, import_react2.useId)();
173
+ const inputId = id || `input-${autoId}`;
168
174
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: cn("flex flex-col", fullWidth && "w-full"), children: [
169
175
  label && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
170
176
  "label",
@@ -304,9 +310,11 @@ var Badge = import_react4.default.forwardRef(
304
310
  info: "bg-cyan-100 text-cyan-800"
305
311
  };
306
312
  const sizes = {
313
+ xs: "text-[0.625rem] px-1.5 py-0.5",
307
314
  sm: "text-xs px-2 py-0.5",
308
315
  md: "text-sm px-2.5 py-1",
309
- lg: "text-base px-3 py-1.5"
316
+ lg: "text-base px-3 py-1.5",
317
+ xl: "text-lg px-3.5 py-2"
310
318
  };
311
319
  const dotVariants = {
312
320
  default: "bg-gray-600",
@@ -338,6 +346,7 @@ var Badge = import_react4.default.forwardRef(
338
346
  Badge.displayName = "Badge";
339
347
 
340
348
  // src/ui/checkbox.tsx
349
+ var import_react5 = require("react");
341
350
  var import_jsx_runtime5 = require("react/jsx-runtime");
342
351
  function Checkbox({
343
352
  label,
@@ -345,14 +354,37 @@ function Checkbox({
345
354
  onChange,
346
355
  disabled = false,
347
356
  className,
348
- id
357
+ id,
358
+ size = "md"
349
359
  }) {
350
- const checkboxId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
360
+ const autoId = (0, import_react5.useId)();
361
+ const checkboxId = id || `checkbox-${autoId}`;
351
362
  const handleChange = (e) => {
352
363
  if (onChange) {
353
364
  onChange(e.target.checked);
354
365
  }
355
366
  };
367
+ const sizeStyles = {
368
+ xs: `[width:var(--checkbox-size-xs)] [height:var(--checkbox-size-xs)]`,
369
+ sm: `[width:var(--checkbox-size-sm)] [height:var(--checkbox-size-sm)]`,
370
+ md: `[width:var(--checkbox-size-md)] [height:var(--checkbox-size-md)]`,
371
+ lg: `[width:var(--checkbox-size-lg)] [height:var(--checkbox-size-lg)]`,
372
+ xl: `[width:var(--checkbox-size-xl)] [height:var(--checkbox-size-xl)]`
373
+ };
374
+ const labelSizeStyles = {
375
+ xs: `[font-size:var(--checkbox-label-font-size-xs)]`,
376
+ sm: `[font-size:var(--checkbox-label-font-size-sm)]`,
377
+ md: `[font-size:var(--checkbox-label-font-size-md)]`,
378
+ lg: `[font-size:var(--checkbox-label-font-size-lg)]`,
379
+ xl: `[font-size:var(--checkbox-label-font-size-xl)]`
380
+ };
381
+ const labelSpacingStyles = {
382
+ xs: `[margin-left:var(--checkbox-label-spacing-xs)]`,
383
+ sm: `[margin-left:var(--checkbox-label-spacing-sm)]`,
384
+ md: `[margin-left:var(--checkbox-label-spacing-md)]`,
385
+ lg: `[margin-left:var(--checkbox-label-spacing-lg)]`,
386
+ xl: `[margin-left:var(--checkbox-label-spacing-xl)]`
387
+ };
356
388
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: cn("flex items-center", className), children: [
357
389
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
358
390
  "input",
@@ -363,7 +395,8 @@ function Checkbox({
363
395
  onChange: handleChange,
364
396
  disabled,
365
397
  className: cn(
366
- "h-4 w-4 rounded border-gray-400 text-blue-600 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2",
398
+ sizeStyles[size],
399
+ "rounded-(--checkbox-radius) border-gray-400 text-blue-600 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2",
367
400
  disabled && "cursor-not-allowed opacity-50"
368
401
  )
369
402
  }
@@ -373,7 +406,9 @@ function Checkbox({
373
406
  {
374
407
  htmlFor: checkboxId,
375
408
  className: cn(
376
- "ml-2 text-sm font-medium text-gray-600",
409
+ labelSpacingStyles[size],
410
+ labelSizeStyles[size],
411
+ "font-medium text-gray-600",
377
412
  disabled && "cursor-not-allowed opacity-50",
378
413
  !disabled && "cursor-pointer"
379
414
  ),
@@ -391,7 +426,8 @@ function CheckboxGroup({
391
426
  className,
392
427
  orientation = "vertical",
393
428
  required = false,
394
- disabled = false
429
+ disabled = false,
430
+ size = "md"
395
431
  }) {
396
432
  const handleChange = (optionValue, checked) => {
397
433
  if (onChange) {
@@ -402,6 +438,27 @@ function CheckboxGroup({
402
438
  }
403
439
  }
404
440
  };
441
+ const sizeStyles = {
442
+ xs: `[width:var(--checkbox-size-xs)] [height:var(--checkbox-size-xs)]`,
443
+ sm: `[width:var(--checkbox-size-sm)] [height:var(--checkbox-size-sm)]`,
444
+ md: `[width:var(--checkbox-size-md)] [height:var(--checkbox-size-md)]`,
445
+ lg: `[width:var(--checkbox-size-lg)] [height:var(--checkbox-size-lg)]`,
446
+ xl: `[width:var(--checkbox-size-xl)] [height:var(--checkbox-size-xl)]`
447
+ };
448
+ const labelSizeStyles = {
449
+ xs: `[font-size:var(--checkbox-label-font-size-xs)]`,
450
+ sm: `[font-size:var(--checkbox-label-font-size-sm)]`,
451
+ md: `[font-size:var(--checkbox-label-font-size-md)]`,
452
+ lg: `[font-size:var(--checkbox-label-font-size-lg)]`,
453
+ xl: `[font-size:var(--checkbox-label-font-size-xl)]`
454
+ };
455
+ const labelSpacingStyles = {
456
+ xs: `[margin-left:var(--checkbox-label-spacing-xs)]`,
457
+ sm: `[margin-left:var(--checkbox-label-spacing-sm)]`,
458
+ md: `[margin-left:var(--checkbox-label-spacing-md)]`,
459
+ lg: `[margin-left:var(--checkbox-label-spacing-lg)]`,
460
+ xl: `[margin-left:var(--checkbox-label-spacing-xl)]`
461
+ };
405
462
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className, children: [
406
463
  label && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "block text-sm font-semibold text-gray-600 mb-1", children: [
407
464
  label,
@@ -428,7 +485,8 @@ function CheckboxGroup({
428
485
  onChange: (e) => handleChange(option.value, e.target.checked),
429
486
  disabled: isDisabled,
430
487
  className: cn(
431
- "h-4 w-4 rounded border-gray-400 text-blue-600 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2",
488
+ sizeStyles[size],
489
+ "rounded-(--checkbox-radius) border-gray-400 text-blue-600 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2",
432
490
  isDisabled && "cursor-not-allowed opacity-50"
433
491
  )
434
492
  }
@@ -438,7 +496,9 @@ function CheckboxGroup({
438
496
  {
439
497
  htmlFor: `${name}-${option.value}`,
440
498
  className: cn(
441
- "ml-2 text-sm font-medium text-gray-600",
499
+ labelSpacingStyles[size],
500
+ labelSizeStyles[size],
501
+ "font-medium text-gray-600",
442
502
  isDisabled && "cursor-not-allowed opacity-50",
443
503
  !isDisabled && "cursor-pointer"
444
504
  ),
@@ -463,13 +523,35 @@ function RadioGroup({
463
523
  className,
464
524
  orientation = "vertical",
465
525
  required = false,
466
- disabled = false
526
+ disabled = false,
527
+ size = "md"
467
528
  }) {
468
529
  const handleChange = (e) => {
469
530
  if (onChange) {
470
531
  onChange(e.target.value);
471
532
  }
472
533
  };
534
+ const sizeStyles = {
535
+ xs: `[width:var(--radio-size-xs)] [height:var(--radio-size-xs)]`,
536
+ sm: `[width:var(--radio-size-sm)] [height:var(--radio-size-sm)]`,
537
+ md: `[width:var(--radio-size-md)] [height:var(--radio-size-md)]`,
538
+ lg: `[width:var(--radio-size-lg)] [height:var(--radio-size-lg)]`,
539
+ xl: `[width:var(--radio-size-xl)] [height:var(--radio-size-xl)]`
540
+ };
541
+ const labelSizeStyles = {
542
+ xs: `[font-size:var(--radio-label-font-size-xs)]`,
543
+ sm: `[font-size:var(--radio-label-font-size-sm)]`,
544
+ md: `[font-size:var(--radio-label-font-size-md)]`,
545
+ lg: `[font-size:var(--radio-label-font-size-lg)]`,
546
+ xl: `[font-size:var(--radio-label-font-size-xl)]`
547
+ };
548
+ const labelSpacingStyles = {
549
+ xs: `[margin-left:var(--radio-label-spacing-xs)]`,
550
+ sm: `[margin-left:var(--radio-label-spacing-sm)]`,
551
+ md: `[margin-left:var(--radio-label-spacing-md)]`,
552
+ lg: `[margin-left:var(--radio-label-spacing-lg)]`,
553
+ xl: `[margin-left:var(--radio-label-spacing-xl)]`
554
+ };
473
555
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className, children: [
474
556
  label && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "block text-sm font-semibold text-gray-600 mb-1", children: [
475
557
  label,
@@ -496,7 +578,8 @@ function RadioGroup({
496
578
  onChange: handleChange,
497
579
  disabled: isDisabled,
498
580
  className: cn(
499
- "h-4 w-4 border-gray-400 text-blue-600 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2",
581
+ sizeStyles[size],
582
+ "border-gray-400 text-blue-600 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2",
500
583
  isDisabled && "cursor-not-allowed opacity-50"
501
584
  )
502
585
  }
@@ -506,7 +589,9 @@ function RadioGroup({
506
589
  {
507
590
  htmlFor: `${name}-${option.value}`,
508
591
  className: cn(
509
- "ml-2 text-sm font-medium text-gray-600",
592
+ labelSpacingStyles[size],
593
+ labelSizeStyles[size],
594
+ "font-medium text-gray-600",
510
595
  isDisabled && "cursor-not-allowed opacity-50",
511
596
  !isDisabled && "cursor-pointer"
512
597
  ),
@@ -521,7 +606,7 @@ function RadioGroup({
521
606
  }
522
607
 
523
608
  // src/ui/dropdown.tsx
524
- var import_react5 = require("react");
609
+ var import_react6 = require("react");
525
610
  var import_lucide_react = require("lucide-react");
526
611
  var import_jsx_runtime7 = require("react/jsx-runtime");
527
612
  function Dropdown({
@@ -535,16 +620,38 @@ function Dropdown({
535
620
  error,
536
621
  helperText,
537
622
  required = false,
623
+ size = "md",
538
624
  className = ""
539
625
  }) {
540
- const [isOpen, setIsOpen] = (0, import_react5.useState)(false);
541
- const dropdownRef = (0, import_react5.useRef)(null);
626
+ const [isOpen, setIsOpen] = (0, import_react6.useState)(false);
627
+ const dropdownRef = (0, import_react6.useRef)(null);
542
628
  const getSelectedLabel = () => {
543
629
  if (!value) return placeholder;
544
630
  const selected = options.find((opt) => opt.value === value);
545
631
  return selected ? selected.label : placeholder;
546
632
  };
547
- (0, import_react5.useEffect)(() => {
633
+ const sizeStyles = {
634
+ xs: `[padding-left:var(--dropdown-padding-xs-x)] [padding-right:var(--dropdown-padding-xs-x)] [padding-top:var(--dropdown-padding-xs-y)] [padding-bottom:var(--dropdown-padding-xs-y)] [font-size:var(--dropdown-font-size-xs)]`,
635
+ sm: `[padding-left:var(--dropdown-padding-sm-x)] [padding-right:var(--dropdown-padding-sm-x)] [padding-top:var(--dropdown-padding-sm-y)] [padding-bottom:var(--dropdown-padding-sm-y)] [font-size:var(--dropdown-font-size-sm)]`,
636
+ md: `[padding-left:var(--dropdown-padding-md-x)] [padding-right:var(--dropdown-padding-md-x)] [padding-top:var(--dropdown-padding-md-y)] [padding-bottom:var(--dropdown-padding-md-y)] [font-size:var(--dropdown-font-size-md)]`,
637
+ lg: `[padding-left:var(--dropdown-padding-lg-x)] [padding-right:var(--dropdown-padding-lg-x)] [padding-top:var(--dropdown-padding-lg-y)] [padding-bottom:var(--dropdown-padding-lg-y)] [font-size:var(--dropdown-font-size-lg)]`,
638
+ xl: `[padding-left:var(--dropdown-padding-xl-x)] [padding-right:var(--dropdown-padding-xl-x)] [padding-top:var(--dropdown-padding-xl-y)] [padding-bottom:var(--dropdown-padding-xl-y)] [font-size:var(--dropdown-font-size-xl)]`
639
+ };
640
+ const iconSizeStyles = {
641
+ xs: `[width:var(--dropdown-icon-size-xs)] [height:var(--dropdown-icon-size-xs)]`,
642
+ sm: `[width:var(--dropdown-icon-size-sm)] [height:var(--dropdown-icon-size-sm)]`,
643
+ md: `[width:var(--dropdown-icon-size-md)] [height:var(--dropdown-icon-size-md)]`,
644
+ lg: `[width:var(--dropdown-icon-size-lg)] [height:var(--dropdown-icon-size-lg)]`,
645
+ xl: `[width:var(--dropdown-icon-size-xl)] [height:var(--dropdown-icon-size-xl)]`
646
+ };
647
+ const optionSizeStyles = {
648
+ xs: `[padding-left:var(--dropdown-option-padding-xs-x)] [padding-right:var(--dropdown-option-padding-xs-x)] [padding-top:var(--dropdown-option-padding-xs-y)] [padding-bottom:var(--dropdown-option-padding-xs-y)] [font-size:var(--dropdown-option-font-size-xs)]`,
649
+ sm: `[padding-left:var(--dropdown-option-padding-sm-x)] [padding-right:var(--dropdown-option-padding-sm-x)] [padding-top:var(--dropdown-option-padding-sm-y)] [padding-bottom:var(--dropdown-option-padding-sm-y)] [font-size:var(--dropdown-option-font-size-sm)]`,
650
+ md: `[padding-left:var(--dropdown-option-padding-md-x)] [padding-right:var(--dropdown-option-padding-md-x)] [padding-top:var(--dropdown-option-padding-md-y)] [padding-bottom:var(--dropdown-option-padding-md-y)] [font-size:var(--dropdown-option-font-size-md)]`,
651
+ lg: `[padding-left:var(--dropdown-option-padding-lg-x)] [padding-right:var(--dropdown-option-padding-lg-x)] [padding-top:var(--dropdown-option-padding-lg-y)] [padding-bottom:var(--dropdown-option-padding-lg-y)] [font-size:var(--dropdown-option-font-size-lg)]`,
652
+ xl: `[padding-left:var(--dropdown-option-padding-xl-x)] [padding-right:var(--dropdown-option-padding-xl-x)] [padding-top:var(--dropdown-option-padding-xl-y)] [padding-bottom:var(--dropdown-option-padding-xl-y)] [font-size:var(--dropdown-option-font-size-xl)]`
653
+ };
654
+ (0, import_react6.useEffect)(() => {
548
655
  const handleClickOutside = (event) => {
549
656
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
550
657
  setIsOpen(false);
@@ -580,7 +687,7 @@ function Dropdown({
580
687
  onKeyDown: handleKeyDown,
581
688
  disabled,
582
689
  className: `
583
- w-full px-4 py-2 text-left bg-white border rounded-lg
690
+ w-full ${sizeStyles[size]} text-left bg-white border rounded-(--dropdown-radius)
584
691
  flex items-center justify-between
585
692
  transition-all duration-200
586
693
  ${error ? "border-red-500 focus:ring-2 focus:ring-red-200 focus:border-red-500" : "border-gray-400 focus:ring-2 focus:ring-blue-200 focus:border-blue-500"}
@@ -592,7 +699,7 @@ function Dropdown({
592
699
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
593
700
  import_lucide_react.ChevronDown,
594
701
  {
595
- className: `w-5 h-5 text-gray-400 transition-transform duration-200 shrink-0 ml-2 ${isOpen ? "transform rotate-180" : ""}`
702
+ className: `${iconSizeStyles[size]} text-gray-400 transition-transform duration-200 shrink-0 ml-2 ${isOpen ? "transform rotate-180" : ""}`
596
703
  }
597
704
  )
598
705
  ]
@@ -615,7 +722,7 @@ function Dropdown({
615
722
  onClick: () => !option.disabled && handleSelect(option.value),
616
723
  disabled: option.disabled,
617
724
  className: `
618
- w-full px-4 py-2 text-left text-sm
725
+ w-full ${optionSizeStyles[size]} text-left
619
726
  transition-colors duration-150
620
727
  ${option.value === value ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-900 hover:bg-gray-100"}
621
728
  ${option.disabled ? "opacity-50 cursor-not-allowed" : ""}
@@ -640,9 +747,9 @@ function Dropdown({
640
747
  }
641
748
 
642
749
  // src/ui/spinner.tsx
643
- var import_react6 = __toESM(require("react"));
750
+ var import_react7 = __toESM(require("react"));
644
751
  var import_jsx_runtime8 = require("react/jsx-runtime");
645
- var Spinner = import_react6.default.forwardRef(
752
+ var Spinner = import_react7.default.forwardRef(
646
753
  ({ className, size = "md", color = "primary", label, ...props }, ref) => {
647
754
  const sizes = {
648
755
  sm: "h-4 w-4",
@@ -704,13 +811,13 @@ var Spinner = import_react6.default.forwardRef(
704
811
  Spinner.displayName = "Spinner";
705
812
 
706
813
  // src/ui/code-snippet.tsx
707
- var import_react7 = require("react");
814
+ var import_react8 = require("react");
708
815
  var import_react_syntax_highlighter = require("react-syntax-highlighter");
709
816
  var import_prism = require("react-syntax-highlighter/dist/esm/styles/prism");
710
817
  var import_jsx_runtime9 = require("react/jsx-runtime");
711
818
  function CodeSnippet({ code, language = "tsx" }) {
712
- const [copied, setCopied] = (0, import_react7.useState)(false);
713
- const [showTooltip, setShowTooltip] = (0, import_react7.useState)(false);
819
+ const [copied, setCopied] = (0, import_react8.useState)(false);
820
+ const [showTooltip, setShowTooltip] = (0, import_react8.useState)(false);
714
821
  const handleCopy = async () => {
715
822
  try {
716
823
  await navigator.clipboard.writeText(code);
@@ -802,9 +909,9 @@ function CodeSnippet({ code, language = "tsx" }) {
802
909
  }
803
910
 
804
911
  // src/feedback/alert.tsx
805
- var import_react8 = __toESM(require("react"));
912
+ var import_react9 = __toESM(require("react"));
806
913
  var import_jsx_runtime10 = require("react/jsx-runtime");
807
- var Alert = import_react8.default.forwardRef(
914
+ var Alert = import_react9.default.forwardRef(
808
915
  ({
809
916
  className,
810
917
  variant = "info",
@@ -907,9 +1014,9 @@ var Alert = import_react8.default.forwardRef(
907
1014
  Alert.displayName = "Alert";
908
1015
 
909
1016
  // src/layout/container.tsx
910
- var import_react9 = __toESM(require("react"));
1017
+ var import_react10 = __toESM(require("react"));
911
1018
  var import_jsx_runtime11 = require("react/jsx-runtime");
912
- var Container = import_react9.default.forwardRef(
1019
+ var Container = import_react10.default.forwardRef(
913
1020
  ({
914
1021
  className,
915
1022
  maxWidth = "xl",
@@ -946,7 +1053,7 @@ var Container = import_react9.default.forwardRef(
946
1053
  Container.displayName = "Container";
947
1054
 
948
1055
  // src/layout/section-layout.tsx
949
- var import_react10 = __toESM(require("react"));
1056
+ var import_react11 = __toESM(require("react"));
950
1057
  var import_jsx_runtime12 = require("react/jsx-runtime");
951
1058
  function SectionLayout({
952
1059
  children,
@@ -955,7 +1062,7 @@ function SectionLayout({
955
1062
  if (!hasStickyPreview) {
956
1063
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_jsx_runtime12.Fragment, { children });
957
1064
  }
958
- const childArray = import_react10.default.Children.toArray(children);
1065
+ const childArray = import_react11.default.Children.toArray(children);
959
1066
  if (childArray.length === 0) {
960
1067
  return null;
961
1068
  }
@@ -967,48 +1074,308 @@ function SectionLayout({
967
1074
  ] });
968
1075
  }
969
1076
 
970
- // src/layout/sidebar-nav.tsx
971
- var import_react11 = require("react");
1077
+ // src/layout/nav.tsx
1078
+ var import_react12 = __toESM(require("react"));
972
1079
  var import_lucide_react2 = require("lucide-react");
973
1080
  var import_jsx_runtime13 = require("react/jsx-runtime");
1081
+ var Nav = import_react12.default.forwardRef(
1082
+ ({
1083
+ className,
1084
+ items,
1085
+ variant = "primary",
1086
+ orientation = "horizontal",
1087
+ size = "md",
1088
+ mobileBreakpoint = "md",
1089
+ logo,
1090
+ actions,
1091
+ sticky = false,
1092
+ activeId,
1093
+ onItemClick,
1094
+ ...props
1095
+ }, ref) => {
1096
+ const [isMobileMenuOpen, setIsMobileMenuOpen] = (0, import_react12.useState)(false);
1097
+ const [openDropdownId, setOpenDropdownId] = (0, import_react12.useState)(null);
1098
+ const dropdownRef = (0, import_react12.useRef)(null);
1099
+ (0, import_react12.useEffect)(() => {
1100
+ function handleClickOutside(event) {
1101
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
1102
+ setOpenDropdownId(null);
1103
+ }
1104
+ }
1105
+ document.addEventListener("mousedown", handleClickOutside);
1106
+ return () => {
1107
+ document.removeEventListener("mousedown", handleClickOutside);
1108
+ };
1109
+ }, []);
1110
+ (0, import_react12.useEffect)(() => {
1111
+ function handleEscape(event) {
1112
+ if (event.key === "Escape") {
1113
+ setIsMobileMenuOpen(false);
1114
+ setOpenDropdownId(null);
1115
+ }
1116
+ }
1117
+ document.addEventListener("keydown", handleEscape);
1118
+ return () => {
1119
+ document.removeEventListener("keydown", handleEscape);
1120
+ };
1121
+ }, []);
1122
+ const baseStyles = cn(
1123
+ "bg-[var(--color-background)] border-b border-[var(--color-border)]",
1124
+ sticky && "sticky top-0 z-50"
1125
+ );
1126
+ const containerStyles = cn(
1127
+ "[min-height:var(--nav-height)]",
1128
+ "flex items-center justify-between",
1129
+ "px-[var(--spacing-lg)]"
1130
+ );
1131
+ const itemPaddingStyles = {
1132
+ xs: "[padding-left:var(--nav-item-padding-xs-x)] [padding-right:var(--nav-item-padding-xs-x)] [padding-top:var(--nav-item-padding-xs-y)] [padding-bottom:var(--nav-item-padding-xs-y)]",
1133
+ sm: "[padding-left:var(--nav-item-padding-sm-x)] [padding-right:var(--nav-item-padding-sm-x)] [padding-top:var(--nav-item-padding-sm-y)] [padding-bottom:var(--nav-item-padding-sm-y)]",
1134
+ md: "[padding-left:var(--nav-item-padding-md-x)] [padding-right:var(--nav-item-padding-md-x)] [padding-top:var(--nav-item-padding-md-y)] [padding-bottom:var(--nav-item-padding-md-y)]",
1135
+ lg: "[padding-left:var(--nav-item-padding-lg-x)] [padding-right:var(--nav-item-padding-lg-x)] [padding-top:var(--nav-item-padding-lg-y)] [padding-bottom:var(--nav-item-padding-lg-y)]",
1136
+ xl: "[padding-left:var(--nav-item-padding-xl-x)] [padding-right:var(--nav-item-padding-xl-x)] [padding-top:var(--nav-item-padding-xl-y)] [padding-bottom:var(--nav-item-padding-xl-y)]"
1137
+ };
1138
+ const fontSizeStyles = {
1139
+ xs: "[font-size:var(--nav-font-size-xs)]",
1140
+ sm: "[font-size:var(--nav-font-size-sm)]",
1141
+ md: "[font-size:var(--nav-font-size-md)]",
1142
+ lg: "[font-size:var(--nav-font-size-lg)]",
1143
+ xl: "[font-size:var(--nav-font-size-xl)]"
1144
+ };
1145
+ const variantItemStyles = {
1146
+ primary: "rounded-[var(--nav-border-radius)] hover:bg-blue-50 transition-colors",
1147
+ secondary: "rounded-[var(--nav-border-radius)] hover:bg-[var(--color-muted)] transition-colors",
1148
+ outline: cn(
1149
+ "rounded-[var(--nav-border-radius)] border border-[var(--color-border)] hover:bg-[var(--color-muted)] transition-colors"
1150
+ ),
1151
+ ghost: "rounded-[var(--nav-border-radius)] hover:bg-[var(--color-muted)]/50 transition-colors"
1152
+ };
1153
+ const activeItemStyles = {
1154
+ primary: "bg-blue-100 text-blue-700",
1155
+ secondary: "bg-[var(--color-muted)] [font-weight:var(--font-semibold)]",
1156
+ outline: "border-blue-600 bg-blue-50 text-blue-700",
1157
+ ghost: "bg-[var(--color-muted)]"
1158
+ };
1159
+ const breakpointClasses = {
1160
+ sm: "sm:hidden",
1161
+ md: "md:hidden",
1162
+ lg: "lg:hidden"
1163
+ };
1164
+ const breakpointShowClasses = {
1165
+ sm: "hidden sm:flex",
1166
+ md: "hidden md:flex",
1167
+ lg: "hidden lg:flex"
1168
+ };
1169
+ const handleItemClick = (item) => {
1170
+ if (item.disabled) return;
1171
+ if (item.type === "dropdown") {
1172
+ setOpenDropdownId(openDropdownId === item.id ? null : item.id);
1173
+ return;
1174
+ }
1175
+ if (item.onClick) {
1176
+ item.onClick();
1177
+ }
1178
+ if (onItemClick) {
1179
+ onItemClick(item);
1180
+ }
1181
+ setIsMobileMenuOpen(false);
1182
+ setOpenDropdownId(null);
1183
+ };
1184
+ const renderNavItem = (item, isMobile = false) => {
1185
+ if (item.type === "divider") {
1186
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1187
+ "div",
1188
+ {
1189
+ className: cn(
1190
+ orientation === "horizontal" && !isMobile && "h-6 border-l border-[var(--color-border)] mx-2",
1191
+ (orientation === "vertical" || isMobile) && "w-full h-0 border-t border-[var(--color-border)] my-2"
1192
+ )
1193
+ },
1194
+ item.id
1195
+ );
1196
+ }
1197
+ if (item.type === "custom" && item.render) {
1198
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { children: item.render() }, item.id);
1199
+ }
1200
+ const isActive = activeId === item.id;
1201
+ const isDropdownOpen = openDropdownId === item.id;
1202
+ const hasChildren = item.children && item.children.length > 0;
1203
+ const itemBaseStyles = cn(
1204
+ "flex items-center [gap:var(--nav-gap)] font-medium text-[var(--color-foreground)] cursor-pointer select-none",
1205
+ itemPaddingStyles[size],
1206
+ fontSizeStyles[size],
1207
+ variantItemStyles[variant],
1208
+ isActive && activeItemStyles[variant],
1209
+ orientation === "vertical" && "w-full",
1210
+ item.disabled && "opacity-50 cursor-not-allowed"
1211
+ );
1212
+ const content = /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1213
+ item.icon && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "flex-shrink-0", children: item.icon }),
1214
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: item.label }),
1215
+ item.badge && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ml-auto px-2 py-0.5 [font-size:var(--text-xs)] font-semibold bg-red-500 text-white rounded-[var(--radius-full)]", children: item.badge }),
1216
+ hasChildren && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1217
+ import_lucide_react2.ChevronDown,
1218
+ {
1219
+ className: cn(
1220
+ "w-4 h-4 transition-transform",
1221
+ isDropdownOpen && "rotate-180"
1222
+ )
1223
+ }
1224
+ )
1225
+ ] });
1226
+ if (hasChildren) {
1227
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "relative", ref: dropdownRef, children: [
1228
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1229
+ "button",
1230
+ {
1231
+ onClick: () => handleItemClick(item),
1232
+ className: itemBaseStyles,
1233
+ disabled: item.disabled,
1234
+ children: content
1235
+ }
1236
+ ),
1237
+ isDropdownOpen && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1238
+ "div",
1239
+ {
1240
+ className: cn(
1241
+ "absolute left-0 mt-[var(--nav-gap)] min-w-[200px] bg-[var(--color-background)] border border-[var(--color-border)] rounded-[var(--nav-border-radius)] shadow-lg z-50",
1242
+ orientation === "vertical" && "left-full top-0 ml-2 mt-0"
1243
+ ),
1244
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "py-1", children: item.children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1245
+ "button",
1246
+ {
1247
+ onClick: () => handleItemClick(child),
1248
+ disabled: child.disabled,
1249
+ className: cn(
1250
+ "w-full flex items-center gap-2 px-4 py-2 [font-size:var(--text-sm)] text-[var(--color-foreground)] hover:bg-[var(--color-muted)] transition-colors",
1251
+ child.disabled && "opacity-50 cursor-not-allowed",
1252
+ activeId === child.id && "bg-[var(--color-muted)] [font-weight:var(--font-semibold)]"
1253
+ ),
1254
+ children: [
1255
+ child.icon && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "flex-shrink-0", children: child.icon }),
1256
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: child.label }),
1257
+ child.badge && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ml-auto px-2 py-0.5 [font-size:var(--text-xs)] font-semibold bg-red-500 text-white rounded-[var(--radius-full)]", children: child.badge })
1258
+ ]
1259
+ },
1260
+ child.id
1261
+ )) })
1262
+ }
1263
+ )
1264
+ ] }, item.id);
1265
+ }
1266
+ if (item.href) {
1267
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1268
+ "a",
1269
+ {
1270
+ href: item.href,
1271
+ target: item.target,
1272
+ onClick: () => handleItemClick(item),
1273
+ className: itemBaseStyles,
1274
+ children: content
1275
+ },
1276
+ item.id
1277
+ );
1278
+ }
1279
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1280
+ "button",
1281
+ {
1282
+ onClick: () => handleItemClick(item),
1283
+ disabled: item.disabled,
1284
+ className: itemBaseStyles,
1285
+ children: content
1286
+ },
1287
+ item.id
1288
+ );
1289
+ };
1290
+ const desktopNav = /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1291
+ "div",
1292
+ {
1293
+ className: cn(
1294
+ "items-center [gap:var(--nav-gap)]",
1295
+ breakpointShowClasses[mobileBreakpoint],
1296
+ orientation === "horizontal" ? "flex flex-row" : "flex flex-col"
1297
+ ),
1298
+ children: items.map((item) => renderNavItem(item))
1299
+ }
1300
+ );
1301
+ const mobileNav = /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1302
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1303
+ "button",
1304
+ {
1305
+ onClick: () => setIsMobileMenuOpen(!isMobileMenuOpen),
1306
+ className: cn(
1307
+ "p-2 text-[var(--color-foreground)] hover:bg-[var(--color-muted)] rounded-[var(--nav-border-radius)] transition-colors",
1308
+ breakpointClasses[mobileBreakpoint]
1309
+ ),
1310
+ "aria-label": "Toggle menu",
1311
+ children: isMobileMenuOpen ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react2.X, { className: "w-6 h-6" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react2.Menu, { className: "w-6 h-6" })
1312
+ }
1313
+ ),
1314
+ isMobileMenuOpen && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1315
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1316
+ "div",
1317
+ {
1318
+ className: "fixed inset-0 bg-black/20 z-40",
1319
+ onClick: () => setIsMobileMenuOpen(false)
1320
+ }
1321
+ ),
1322
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fixed top-[var(--nav-height)] left-0 right-0 bg-[var(--color-background)] border-b border-[var(--color-border)] shadow-lg z-50 max-h-[calc(100vh-var(--nav-height))] overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex flex-col py-2", children: items.map((item) => renderNavItem(item, true)) }) })
1323
+ ] })
1324
+ ] });
1325
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("nav", { ref, className: cn(baseStyles, className), ...props, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: containerStyles, children: [
1326
+ logo && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex-shrink-0", children: logo }),
1327
+ desktopNav,
1328
+ actions && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex-shrink-0 flex items-center gap-2", children: actions }),
1329
+ mobileNav
1330
+ ] }) });
1331
+ }
1332
+ );
1333
+ Nav.displayName = "Nav";
1334
+
1335
+ // src/layout/sidebar-nav.tsx
1336
+ var import_react13 = require("react");
1337
+ var import_lucide_react3 = require("lucide-react");
1338
+ var import_jsx_runtime14 = require("react/jsx-runtime");
974
1339
  function SidebarNav({
975
1340
  title,
976
1341
  subtitle,
977
1342
  items,
1343
+ sections,
978
1344
  activeItem,
979
1345
  onItemClick,
980
1346
  footer,
981
1347
  position = "right"
982
1348
  }) {
983
- const [mobileMenuOpen, setMobileMenuOpen] = (0, import_react11.useState)(false);
1349
+ const [mobileMenuOpen, setMobileMenuOpen] = (0, import_react13.useState)(false);
984
1350
  const isLeft = position === "left";
985
1351
  const handleItemClick = (itemId) => {
986
1352
  onItemClick(itemId);
987
1353
  setMobileMenuOpen(false);
988
1354
  };
989
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
990
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "lg:hidden fixed top-0 left-0 right-0 z-50 bg-white border-b border-gray-200 px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1355
+ const useSections = sections || (items ? [{ title: "", items }] : []);
1356
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
1357
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "lg:hidden fixed top-0 left-0 right-0 z-50 bg-white border-b border-gray-200 px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
991
1358
  "div",
992
1359
  {
993
1360
  className: `flex items-center ${isLeft ? "justify-between" : "justify-between flex-row-reverse"}`,
994
1361
  children: [
995
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1362
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
996
1363
  "button",
997
1364
  {
998
1365
  onClick: () => setMobileMenuOpen(!mobileMenuOpen),
999
1366
  className: "p-2 rounded-lg hover:bg-gray-100 transition-colors",
1000
1367
  "aria-label": "Toggle menu",
1001
- children: mobileMenuOpen ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react2.X, { className: "w-6 h-6 text-gray-700" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react2.Menu, { className: "w-6 h-6 text-gray-700" })
1368
+ children: mobileMenuOpen ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react3.X, { className: "w-6 h-6 text-gray-700" }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react3.Menu, { className: "w-6 h-6 text-gray-700" })
1002
1369
  }
1003
1370
  ),
1004
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
1005
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h1", { className: "text-lg font-bold text-gray-900", children: title }),
1006
- subtitle && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-xs text-gray-500", children: subtitle })
1371
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
1372
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h1", { className: "text-lg font-bold text-gray-900", children: title }),
1373
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-xs text-gray-500", children: subtitle })
1007
1374
  ] })
1008
1375
  ]
1009
1376
  }
1010
1377
  ) }),
1011
- mobileMenuOpen && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1378
+ mobileMenuOpen && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1012
1379
  "div",
1013
1380
  {
1014
1381
  className: "fixed inset-0 bg-black/50 lg:hidden",
@@ -1016,7 +1383,7 @@ function SidebarNav({
1016
1383
  onClick: () => setMobileMenuOpen(false)
1017
1384
  }
1018
1385
  ),
1019
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1386
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1020
1387
  "aside",
1021
1388
  {
1022
1389
  className: `
@@ -1027,26 +1394,29 @@ function SidebarNav({
1027
1394
  ${mobileMenuOpen ? "translate-x-0" : `${isLeft ? "-translate-x-full" : "translate-x-full"} lg:translate-x-0`}
1028
1395
  `,
1029
1396
  children: [
1030
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "hidden lg:block p-6 border-b border-gray-200", children: [
1031
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h1", { className: "text-xl font-bold text-gray-900", children: title }),
1032
- subtitle && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-xs text-gray-500 mt-1", children: subtitle })
1397
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "hidden lg:block p-6 border-b border-gray-200", children: [
1398
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h1", { className: "text-xl font-bold text-gray-900", children: title }),
1399
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-xs text-gray-500 mt-1", children: subtitle })
1033
1400
  ] }),
1034
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "lg:hidden h-[57px]", "aria-hidden": "true" }),
1035
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("nav", { className: "p-4", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("ul", { className: "space-y-1", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1036
- "button",
1037
- {
1038
- onClick: () => handleItemClick(item.id),
1039
- className: `
1040
- w-full flex items-center gap-3 px-4 py-3 rounded-lg text-sm font-medium transition-colors
1041
- ${activeItem === item.id ? "bg-blue-50 text-blue-700" : "text-gray-700 hover:bg-gray-50"}
1042
- `,
1043
- children: [
1044
- item.icon && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "shrink-0", children: item.icon }),
1045
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: item.label })
1046
- ]
1047
- }
1048
- ) }, item.id)) }) }),
1049
- footer && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "p-4 border-t border-gray-200 mt-auto", children: footer })
1401
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "lg:hidden h-[57px]", "aria-hidden": "true" }),
1402
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("nav", { className: "p-4", children: useSections.map((section, sectionIndex) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: sectionIndex > 0 ? "mt-6" : "", children: [
1403
+ section.title && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { className: "px-4 mb-2 text-xs font-semibold text-gray-500 uppercase tracking-wider", children: section.title }),
1404
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("ul", { className: "space-y-1", children: section.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1405
+ "button",
1406
+ {
1407
+ onClick: () => handleItemClick(item.id),
1408
+ className: `
1409
+ w-full flex items-center gap-3 px-4 py-3 rounded-lg text-sm font-medium transition-colors
1410
+ ${activeItem === item.id ? "bg-blue-50 text-blue-700" : "text-gray-700 hover:bg-gray-50"}
1411
+ `,
1412
+ children: [
1413
+ item.icon && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "shrink-0", children: item.icon }),
1414
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: item.label })
1415
+ ]
1416
+ }
1417
+ ) }, item.id)) })
1418
+ ] }, sectionIndex)) }),
1419
+ footer && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "p-4 border-t border-gray-200 mt-auto", children: footer })
1050
1420
  ]
1051
1421
  }
1052
1422
  )
@@ -1054,11 +1424,11 @@ function SidebarNav({
1054
1424
  }
1055
1425
 
1056
1426
  // src/shared/empty-state.tsx
1057
- var import_react12 = __toESM(require("react"));
1058
- var import_jsx_runtime14 = require("react/jsx-runtime");
1059
- var EmptyState = import_react12.default.forwardRef(
1427
+ var import_react14 = __toESM(require("react"));
1428
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1429
+ var EmptyState = import_react14.default.forwardRef(
1060
1430
  ({ className, icon, title, description, action, ...props }, ref) => {
1061
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1431
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1062
1432
  "div",
1063
1433
  {
1064
1434
  ref,
@@ -1068,16 +1438,452 @@ var EmptyState = import_react12.default.forwardRef(
1068
1438
  ),
1069
1439
  ...props,
1070
1440
  children: [
1071
- icon && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "mb-4 text-gray-400", children: icon }),
1072
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { className: "text-lg font-semibold text-gray-900 mb-2", children: title }),
1073
- description && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm text-gray-500 mb-6 max-w-sm", children: description }),
1074
- action && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { children: action })
1441
+ icon && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "mb-4 text-gray-400", children: icon }),
1442
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h3", { className: "text-lg font-semibold text-gray-900 mb-2", children: title }),
1443
+ description && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-sm text-gray-500 mb-6 max-w-sm", children: description }),
1444
+ action && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { children: action })
1075
1445
  ]
1076
1446
  }
1077
1447
  );
1078
1448
  }
1079
1449
  );
1080
1450
  EmptyState.displayName = "EmptyState";
1451
+
1452
+ // src/shared/contexts/ThemeContext.tsx
1453
+ var import_react15 = require("react");
1454
+
1455
+ // src/styles/themes/default.json
1456
+ var default_default = {
1457
+ name: "Default Theme",
1458
+ version: "1.0.0",
1459
+ colors: {
1460
+ primary: {
1461
+ "50": "#eff6ff",
1462
+ "100": "#dbeafe",
1463
+ "200": "#bfdbfe",
1464
+ "300": "#93c5fd",
1465
+ "400": "#60a5fa",
1466
+ "500": "#3b82f6",
1467
+ "600": "#2563eb",
1468
+ "700": "#1d4ed8",
1469
+ "800": "#1e40af",
1470
+ "900": "#1e3a8a"
1471
+ },
1472
+ secondary: {
1473
+ "50": "#f8fafc",
1474
+ "100": "#f1f5f9",
1475
+ "200": "#e2e8f0",
1476
+ "300": "#cbd5e1",
1477
+ "400": "#94a3b8",
1478
+ "500": "#64748b",
1479
+ "600": "#475569",
1480
+ "700": "#334155",
1481
+ "800": "#1e293b",
1482
+ "900": "#0f172a"
1483
+ },
1484
+ success: "#10b981",
1485
+ error: "#ef4444",
1486
+ warning: "#f59e0b",
1487
+ info: "#3b82f6",
1488
+ gray: {
1489
+ "50": "#f9fafb",
1490
+ "100": "#f3f4f6",
1491
+ "200": "#e5e7eb",
1492
+ "300": "#d1d5db",
1493
+ "400": "#9ca3af",
1494
+ "500": "#6b7280",
1495
+ "600": "#4b5563",
1496
+ "700": "#374151",
1497
+ "800": "#1f2937",
1498
+ "900": "#111827"
1499
+ },
1500
+ background: "#ffffff",
1501
+ foreground: "#111827",
1502
+ muted: "#f3f4f6",
1503
+ mutedForeground: "#6b7280"
1504
+ },
1505
+ spacing: {
1506
+ xs: "0.25rem",
1507
+ sm: "0.5rem",
1508
+ md: "1rem",
1509
+ lg: "1.5rem",
1510
+ xl: "2rem",
1511
+ "2xl": "3rem"
1512
+ },
1513
+ borderRadius: {
1514
+ none: "0",
1515
+ sm: "0.25rem",
1516
+ md: "0.5rem",
1517
+ lg: "0.75rem",
1518
+ xl: "1rem",
1519
+ full: "9999px"
1520
+ },
1521
+ typography: {
1522
+ fontFamily: {
1523
+ sans: [
1524
+ "Inter",
1525
+ "system-ui",
1526
+ "-apple-system",
1527
+ "BlinkMacSystemFont",
1528
+ "Segoe UI",
1529
+ "Roboto",
1530
+ "Helvetica Neue",
1531
+ "Arial",
1532
+ "sans-serif"
1533
+ ],
1534
+ mono: [
1535
+ "Monaco",
1536
+ "Consolas",
1537
+ "Liberation Mono",
1538
+ "Courier New",
1539
+ "monospace"
1540
+ ]
1541
+ },
1542
+ fontSize: {
1543
+ xs: "0.75rem",
1544
+ sm: "0.875rem",
1545
+ base: "1rem",
1546
+ lg: "1.125rem",
1547
+ xl: "1.25rem",
1548
+ "2xl": "1.5rem",
1549
+ "3xl": "1.875rem"
1550
+ },
1551
+ fontWeight: {
1552
+ normal: "400",
1553
+ medium: "500",
1554
+ semibold: "600",
1555
+ bold: "700"
1556
+ }
1557
+ },
1558
+ components: {
1559
+ button: {
1560
+ padding: {
1561
+ xs: { x: "0.5rem", y: "0.375rem" },
1562
+ sm: { x: "0.75rem", y: "0.5rem" },
1563
+ md: { x: "1rem", y: "0.625rem" },
1564
+ lg: { x: "1.25rem", y: "0.75rem" },
1565
+ xl: { x: "1.5rem", y: "0.875rem" }
1566
+ },
1567
+ fontSize: {
1568
+ xs: "0.75rem",
1569
+ sm: "0.875rem",
1570
+ md: "1rem",
1571
+ lg: "1.125rem",
1572
+ xl: "1.25rem"
1573
+ },
1574
+ borderRadius: "0.5rem",
1575
+ fontWeight: "500"
1576
+ },
1577
+ card: {
1578
+ padding: {
1579
+ none: "0",
1580
+ sm: "0.75rem",
1581
+ md: "1rem",
1582
+ lg: "1.5rem"
1583
+ },
1584
+ borderRadius: "0.75rem",
1585
+ borderWidth: "1px",
1586
+ shadow: {
1587
+ flat: "0 1px 2px 0 rgb(0 0 0 / 0.05)",
1588
+ elevated: "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)"
1589
+ }
1590
+ },
1591
+ input: {
1592
+ padding: {
1593
+ xs: "0.375rem 0.5rem",
1594
+ sm: "0.5rem 0.75rem",
1595
+ md: "0.625rem 1rem",
1596
+ lg: "0.75rem 1.25rem",
1597
+ xl: "0.875rem 1.5rem"
1598
+ },
1599
+ fontSize: {
1600
+ xs: "0.75rem",
1601
+ sm: "0.875rem",
1602
+ md: "1rem",
1603
+ lg: "1.125rem",
1604
+ xl: "1.25rem"
1605
+ },
1606
+ borderRadius: "0.5rem",
1607
+ borderWidth: "1px"
1608
+ },
1609
+ checkbox: {
1610
+ size: {
1611
+ xs: "0.75rem",
1612
+ sm: "0.875rem",
1613
+ md: "1rem",
1614
+ lg: "1.25rem",
1615
+ xl: "1.5rem"
1616
+ },
1617
+ labelSpacing: {
1618
+ xs: "0.25rem",
1619
+ sm: "0.375rem",
1620
+ md: "0.5rem",
1621
+ lg: "0.625rem",
1622
+ xl: "0.75rem"
1623
+ },
1624
+ labelFontSize: {
1625
+ xs: "0.625rem",
1626
+ sm: "0.75rem",
1627
+ md: "0.875rem",
1628
+ lg: "1rem",
1629
+ xl: "1.125rem"
1630
+ },
1631
+ borderRadius: "0.25rem"
1632
+ },
1633
+ radio: {
1634
+ size: {
1635
+ xs: "0.75rem",
1636
+ sm: "0.875rem",
1637
+ md: "1rem",
1638
+ lg: "1.25rem",
1639
+ xl: "1.5rem"
1640
+ },
1641
+ labelSpacing: {
1642
+ xs: "0.25rem",
1643
+ sm: "0.375rem",
1644
+ md: "0.5rem",
1645
+ lg: "0.625rem",
1646
+ xl: "0.75rem"
1647
+ },
1648
+ labelFontSize: {
1649
+ xs: "0.625rem",
1650
+ sm: "0.75rem",
1651
+ md: "0.875rem",
1652
+ lg: "1rem",
1653
+ xl: "1.125rem"
1654
+ }
1655
+ },
1656
+ dropdown: {
1657
+ padding: {
1658
+ xs: { x: "0.5rem", y: "0.25rem" },
1659
+ sm: { x: "0.75rem", y: "0.375rem" },
1660
+ md: { x: "1rem", y: "0.5rem" },
1661
+ lg: { x: "1.25rem", y: "0.625rem" },
1662
+ xl: { x: "1.5rem", y: "0.75rem" }
1663
+ },
1664
+ fontSize: {
1665
+ xs: "0.75rem",
1666
+ sm: "0.875rem",
1667
+ md: "1rem",
1668
+ lg: "1.125rem",
1669
+ xl: "1.25rem"
1670
+ },
1671
+ iconSize: {
1672
+ xs: "0.875rem",
1673
+ sm: "1rem",
1674
+ md: "1.25rem",
1675
+ lg: "1.5rem",
1676
+ xl: "1.75rem"
1677
+ },
1678
+ optionPadding: {
1679
+ xs: { x: "0.5rem", y: "0.25rem" },
1680
+ sm: { x: "0.75rem", y: "0.375rem" },
1681
+ md: { x: "1rem", y: "0.5rem" },
1682
+ lg: { x: "1.25rem", y: "0.625rem" },
1683
+ xl: { x: "1.5rem", y: "0.75rem" }
1684
+ },
1685
+ optionFontSize: {
1686
+ xs: "0.625rem",
1687
+ sm: "0.75rem",
1688
+ md: "0.875rem",
1689
+ lg: "1rem",
1690
+ xl: "1.125rem"
1691
+ },
1692
+ borderRadius: "0.5rem",
1693
+ borderWidth: "1px"
1694
+ },
1695
+ nav: {
1696
+ height: "4rem",
1697
+ itemPadding: {
1698
+ xs: { x: "0.375rem", y: "0.25rem" },
1699
+ sm: { x: "0.5rem", y: "0.375rem" },
1700
+ md: { x: "0.75rem", y: "0.5rem" },
1701
+ lg: { x: "1rem", y: "0.625rem" },
1702
+ xl: { x: "1.25rem", y: "0.75rem" }
1703
+ },
1704
+ fontSize: {
1705
+ xs: "0.625rem",
1706
+ sm: "0.75rem",
1707
+ md: "0.875rem",
1708
+ lg: "1rem",
1709
+ xl: "1.125rem"
1710
+ },
1711
+ borderRadius: "0.375rem",
1712
+ gap: "0.25rem"
1713
+ }
1714
+ }
1715
+ };
1716
+
1717
+ // src/shared/contexts/ThemeContext.tsx
1718
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1719
+ var ThemeContext = (0, import_react15.createContext)(void 0);
1720
+ function ThemeProvider({ children }) {
1721
+ const [theme, setThemeState] = (0, import_react15.useState)(default_default);
1722
+ const applyTheme = (newTheme) => {
1723
+ const root = document.documentElement;
1724
+ const colors = newTheme.colors;
1725
+ Object.entries(colors.primary).forEach(([shade, value]) => {
1726
+ if (value) {
1727
+ root.style.setProperty(`--color-primary-${shade}`, value);
1728
+ }
1729
+ });
1730
+ Object.entries(colors.secondary).forEach(([shade, value]) => {
1731
+ if (value) {
1732
+ root.style.setProperty(`--color-secondary-${shade}`, value);
1733
+ }
1734
+ });
1735
+ root.style.setProperty("--color-success", colors.success);
1736
+ root.style.setProperty("--color-error", colors.error);
1737
+ root.style.setProperty("--color-warning", colors.warning);
1738
+ root.style.setProperty("--color-info", colors.info);
1739
+ Object.entries(colors.gray).forEach(([shade, value]) => {
1740
+ if (value) {
1741
+ root.style.setProperty(`--color-gray-${shade}`, value);
1742
+ }
1743
+ });
1744
+ root.style.setProperty("--color-background", colors.background);
1745
+ root.style.setProperty("--color-foreground", colors.foreground);
1746
+ root.style.setProperty("--color-muted", colors.muted);
1747
+ root.style.setProperty("--color-muted-foreground", colors.mutedForeground);
1748
+ Object.entries(newTheme.spacing).forEach(([key, value]) => {
1749
+ root.style.setProperty(`--spacing-${key}`, value);
1750
+ });
1751
+ Object.entries(newTheme.borderRadius).forEach(([key, value]) => {
1752
+ root.style.setProperty(`--radius-${key}`, value);
1753
+ });
1754
+ const { typography } = newTheme;
1755
+ root.style.setProperty(
1756
+ "--font-sans",
1757
+ typography.fontFamily.sans.join(", ")
1758
+ );
1759
+ root.style.setProperty(
1760
+ "--font-mono",
1761
+ typography.fontFamily.mono.join(", ")
1762
+ );
1763
+ Object.entries(typography.fontSize).forEach(([key, value]) => {
1764
+ root.style.setProperty(`--text-${key}`, value);
1765
+ });
1766
+ Object.entries(typography.fontWeight).forEach(([key, value]) => {
1767
+ root.style.setProperty(`--font-${key}`, value);
1768
+ });
1769
+ const button = newTheme.components.button;
1770
+ Object.entries(button.padding).forEach(([size, padding]) => {
1771
+ root.style.setProperty(`--button-padding-${size}-x`, padding.x);
1772
+ root.style.setProperty(`--button-padding-${size}-y`, padding.y);
1773
+ });
1774
+ Object.entries(button.fontSize).forEach(([size, fontSize]) => {
1775
+ root.style.setProperty(`--button-font-size-${size}`, fontSize);
1776
+ });
1777
+ root.style.setProperty("--button-radius", button.borderRadius);
1778
+ root.style.setProperty("--button-font-weight", button.fontWeight);
1779
+ const card = newTheme.components.card;
1780
+ Object.entries(card.padding).forEach(([size, padding]) => {
1781
+ root.style.setProperty(`--card-padding-${size}`, padding);
1782
+ });
1783
+ root.style.setProperty("--card-radius", card.borderRadius);
1784
+ root.style.setProperty("--card-border-width", card.borderWidth);
1785
+ root.style.setProperty("--card-shadow-flat", card.shadow.flat);
1786
+ root.style.setProperty("--card-shadow-elevated", card.shadow.elevated);
1787
+ const input = newTheme.components.input;
1788
+ Object.entries(input.padding).forEach(([size, padding]) => {
1789
+ root.style.setProperty(`--input-padding-${size}`, padding);
1790
+ });
1791
+ Object.entries(input.fontSize).forEach(([size, fontSize]) => {
1792
+ root.style.setProperty(`--input-font-size-${size}`, fontSize);
1793
+ });
1794
+ root.style.setProperty("--input-radius", input.borderRadius);
1795
+ root.style.setProperty("--input-border-width", input.borderWidth);
1796
+ const checkbox = newTheme.components.checkbox;
1797
+ Object.entries(checkbox.size).forEach(([size, dimension]) => {
1798
+ root.style.setProperty(`--checkbox-size-${size}`, dimension);
1799
+ });
1800
+ Object.entries(checkbox.labelSpacing).forEach(([size, spacing]) => {
1801
+ root.style.setProperty(`--checkbox-label-spacing-${size}`, spacing);
1802
+ });
1803
+ Object.entries(checkbox.labelFontSize).forEach(([size, fontSize]) => {
1804
+ root.style.setProperty(`--checkbox-label-font-size-${size}`, fontSize);
1805
+ });
1806
+ root.style.setProperty("--checkbox-radius", checkbox.borderRadius);
1807
+ const radio = newTheme.components.radio;
1808
+ Object.entries(radio.size).forEach(([size, dimension]) => {
1809
+ root.style.setProperty(`--radio-size-${size}`, dimension);
1810
+ });
1811
+ Object.entries(radio.labelSpacing).forEach(([size, spacing]) => {
1812
+ root.style.setProperty(`--radio-label-spacing-${size}`, spacing);
1813
+ });
1814
+ Object.entries(radio.labelFontSize).forEach(([size, fontSize]) => {
1815
+ root.style.setProperty(`--radio-label-font-size-${size}`, fontSize);
1816
+ });
1817
+ const dropdown = newTheme.components.dropdown;
1818
+ Object.entries(dropdown.padding).forEach(([size, padding]) => {
1819
+ root.style.setProperty(`--dropdown-padding-${size}-x`, padding.x);
1820
+ root.style.setProperty(`--dropdown-padding-${size}-y`, padding.y);
1821
+ });
1822
+ Object.entries(dropdown.fontSize).forEach(([size, fontSize]) => {
1823
+ root.style.setProperty(`--dropdown-font-size-${size}`, fontSize);
1824
+ });
1825
+ Object.entries(dropdown.iconSize).forEach(([size, iconSize]) => {
1826
+ root.style.setProperty(`--dropdown-icon-size-${size}`, iconSize);
1827
+ });
1828
+ Object.entries(dropdown.optionPadding).forEach(([size, padding]) => {
1829
+ root.style.setProperty(`--dropdown-option-padding-${size}-x`, padding.x);
1830
+ root.style.setProperty(`--dropdown-option-padding-${size}-y`, padding.y);
1831
+ });
1832
+ Object.entries(dropdown.optionFontSize).forEach(([size, fontSize]) => {
1833
+ root.style.setProperty(`--dropdown-option-font-size-${size}`, fontSize);
1834
+ });
1835
+ root.style.setProperty("--dropdown-radius", dropdown.borderRadius);
1836
+ root.style.setProperty("--dropdown-border-width", dropdown.borderWidth);
1837
+ const nav = newTheme.components.nav;
1838
+ root.style.setProperty("--nav-height", nav.height);
1839
+ Object.entries(nav.itemPadding).forEach(([size, padding]) => {
1840
+ root.style.setProperty(`--nav-item-padding-${size}-x`, padding.x);
1841
+ root.style.setProperty(`--nav-item-padding-${size}-y`, padding.y);
1842
+ });
1843
+ Object.entries(nav.fontSize).forEach(([size, fontSize]) => {
1844
+ root.style.setProperty(`--nav-font-size-${size}`, fontSize);
1845
+ });
1846
+ root.style.setProperty("--nav-border-radius", nav.borderRadius);
1847
+ root.style.setProperty("--nav-gap", nav.gap);
1848
+ setThemeState(newTheme);
1849
+ };
1850
+ const setTheme = (newTheme) => {
1851
+ applyTheme(newTheme);
1852
+ if (typeof window !== "undefined") {
1853
+ localStorage.setItem("theme", JSON.stringify(newTheme));
1854
+ }
1855
+ };
1856
+ const resetTheme = () => {
1857
+ applyTheme(default_default);
1858
+ if (typeof window !== "undefined") {
1859
+ localStorage.removeItem("theme");
1860
+ }
1861
+ };
1862
+ (0, import_react15.useEffect)(() => {
1863
+ if (typeof window !== "undefined") {
1864
+ const savedTheme = localStorage.getItem("theme");
1865
+ if (savedTheme) {
1866
+ try {
1867
+ const parsedTheme = JSON.parse(savedTheme);
1868
+ applyTheme(parsedTheme);
1869
+ } catch (error) {
1870
+ console.error("Failed to parse saved theme:", error);
1871
+ applyTheme(default_default);
1872
+ }
1873
+ } else {
1874
+ applyTheme(default_default);
1875
+ }
1876
+ }
1877
+ }, []);
1878
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ThemeContext.Provider, { value: { theme, setTheme, applyTheme, resetTheme }, children });
1879
+ }
1880
+ function useTheme() {
1881
+ const context = (0, import_react15.useContext)(ThemeContext);
1882
+ if (context === void 0) {
1883
+ throw new Error("useTheme must be used within a ThemeProvider");
1884
+ }
1885
+ return context;
1886
+ }
1081
1887
  // Annotate the CommonJS export names for ESM import in node:
1082
1888
  0 && (module.exports = {
1083
1889
  Alert,
@@ -1096,10 +1902,13 @@ EmptyState.displayName = "EmptyState";
1096
1902
  Dropdown,
1097
1903
  EmptyState,
1098
1904
  Input,
1905
+ Nav,
1099
1906
  RadioGroup,
1100
1907
  SectionLayout,
1101
1908
  SidebarNav,
1102
1909
  Spinner,
1103
- cn
1910
+ ThemeProvider,
1911
+ cn,
1912
+ useTheme
1104
1913
  });
1105
1914
  //# sourceMappingURL=index.js.map