@work-rjkashyap/unified-ui 0.3.2 → 0.3.4

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.
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkZBGR7MUW_cjs = require('./chunk-ZBGR7MUW.cjs');
3
+ var chunk6ZZZBOCH_cjs = require('./chunk-6ZZZBOCH.cjs');
4
4
  var chunkECIGDEAH_cjs = require('./chunk-ECIGDEAH.cjs');
5
5
  var chunkXCKK6P46_cjs = require('./chunk-XCKK6P46.cjs');
6
6
  var chunk4ON3M3OM_cjs = require('./chunk-4ON3M3OM.cjs');
@@ -138,10 +138,10 @@ function mapRecord(varNames, values) {
138
138
  }
139
139
  function buildLightThemeVars() {
140
140
  return {
141
- ...mapRecord(colorVarNames, chunkZBGR7MUW_cjs.semanticLight),
142
- ...mapRecord(radiusVarNames, chunkZBGR7MUW_cjs.radius),
143
- ...mapRecord(shadowVarNames, chunkZBGR7MUW_cjs.shadow),
144
- ...mapRecord(zIndexVarNames, chunkZBGR7MUW_cjs.zIndex),
141
+ ...mapRecord(colorVarNames, chunk6ZZZBOCH_cjs.semanticLight),
142
+ ...mapRecord(radiusVarNames, chunk6ZZZBOCH_cjs.radius),
143
+ ...mapRecord(shadowVarNames, chunk6ZZZBOCH_cjs.shadow),
144
+ ...mapRecord(zIndexVarNames, chunk6ZZZBOCH_cjs.zIndex),
145
145
  ...mapRecord(durationVarNames, chunkXCKK6P46_cjs.durationCSS),
146
146
  ...mapRecord(easingVarNames, chunkXCKK6P46_cjs.easingCSS),
147
147
  ...mapRecord(fontFamilyVarNames, chunkECIGDEAH_cjs.fontFamily)
@@ -149,10 +149,10 @@ function buildLightThemeVars() {
149
149
  }
150
150
  function buildDarkThemeVars() {
151
151
  return {
152
- ...mapRecord(colorVarNames, chunkZBGR7MUW_cjs.semanticDark),
153
- ...mapRecord(radiusVarNames, chunkZBGR7MUW_cjs.radius),
154
- ...mapRecord(shadowVarNames, chunkZBGR7MUW_cjs.shadowDark),
155
- ...mapRecord(zIndexVarNames, chunkZBGR7MUW_cjs.zIndex),
152
+ ...mapRecord(colorVarNames, chunk6ZZZBOCH_cjs.semanticDark),
153
+ ...mapRecord(radiusVarNames, chunk6ZZZBOCH_cjs.radius),
154
+ ...mapRecord(shadowVarNames, chunk6ZZZBOCH_cjs.shadowDark),
155
+ ...mapRecord(zIndexVarNames, chunk6ZZZBOCH_cjs.zIndex),
156
156
  ...mapRecord(durationVarNames, chunkXCKK6P46_cjs.durationCSS),
157
157
  ...mapRecord(easingVarNames, chunkXCKK6P46_cjs.easingCSS),
158
158
  ...mapRecord(fontFamilyVarNames, chunkECIGDEAH_cjs.fontFamily)
@@ -215,48 +215,48 @@ var cssVar = {
215
215
 
216
216
  // src/theme/presets.ts
217
217
  var STATUS_LIGHT = {
218
- success: chunkZBGR7MUW_cjs.green[600],
218
+ success: chunk6ZZZBOCH_cjs.green[600],
219
219
  successForeground: "oklch(0.145 0 0)",
220
- successMuted: chunkZBGR7MUW_cjs.green[50],
221
- successMutedForeground: chunkZBGR7MUW_cjs.green[700],
222
- warning: chunkZBGR7MUW_cjs.amber[500],
220
+ successMuted: chunk6ZZZBOCH_cjs.green[50],
221
+ successMutedForeground: chunk6ZZZBOCH_cjs.green[700],
222
+ warning: chunk6ZZZBOCH_cjs.amber[500],
223
223
  warningForeground: "oklch(0.145 0 0)",
224
- warningMuted: chunkZBGR7MUW_cjs.amber[50],
225
- warningMutedForeground: chunkZBGR7MUW_cjs.amber[700],
226
- danger: chunkZBGR7MUW_cjs.red[600],
224
+ warningMuted: chunk6ZZZBOCH_cjs.amber[50],
225
+ warningMutedForeground: chunk6ZZZBOCH_cjs.amber[700],
226
+ danger: chunk6ZZZBOCH_cjs.red[600],
227
227
  dangerForeground: "oklch(0.985 0 0)",
228
- dangerHover: chunkZBGR7MUW_cjs.red[700],
229
- dangerActive: chunkZBGR7MUW_cjs.red[800],
230
- dangerMuted: chunkZBGR7MUW_cjs.red[50],
231
- dangerMutedForeground: chunkZBGR7MUW_cjs.red[700],
232
- destructive: chunkZBGR7MUW_cjs.red[600],
228
+ dangerHover: chunk6ZZZBOCH_cjs.red[700],
229
+ dangerActive: chunk6ZZZBOCH_cjs.red[800],
230
+ dangerMuted: chunk6ZZZBOCH_cjs.red[50],
231
+ dangerMutedForeground: chunk6ZZZBOCH_cjs.red[700],
232
+ destructive: chunk6ZZZBOCH_cjs.red[600],
233
233
  destructiveForeground: "oklch(0.985 0 0)",
234
- info: chunkZBGR7MUW_cjs.blue[600],
234
+ info: chunk6ZZZBOCH_cjs.blue[600],
235
235
  infoForeground: "oklch(0.985 0 0)",
236
- infoMuted: chunkZBGR7MUW_cjs.blue[50],
237
- infoMutedForeground: chunkZBGR7MUW_cjs.blue[700]
236
+ infoMuted: chunk6ZZZBOCH_cjs.blue[50],
237
+ infoMutedForeground: chunk6ZZZBOCH_cjs.blue[700]
238
238
  };
239
239
  var STATUS_DARK = {
240
- success: chunkZBGR7MUW_cjs.green[500],
240
+ success: chunk6ZZZBOCH_cjs.green[500],
241
241
  successForeground: "oklch(0.145 0 0)",
242
- successMuted: chunkZBGR7MUW_cjs.green[950],
243
- successMutedForeground: chunkZBGR7MUW_cjs.green[300],
244
- warning: chunkZBGR7MUW_cjs.amber[400],
242
+ successMuted: chunk6ZZZBOCH_cjs.green[950],
243
+ successMutedForeground: chunk6ZZZBOCH_cjs.green[300],
244
+ warning: chunk6ZZZBOCH_cjs.amber[400],
245
245
  warningForeground: "oklch(0.145 0 0)",
246
- warningMuted: chunkZBGR7MUW_cjs.amber[950],
247
- warningMutedForeground: chunkZBGR7MUW_cjs.amber[300],
248
- danger: chunkZBGR7MUW_cjs.red[500],
246
+ warningMuted: chunk6ZZZBOCH_cjs.amber[950],
247
+ warningMutedForeground: chunk6ZZZBOCH_cjs.amber[300],
248
+ danger: chunk6ZZZBOCH_cjs.red[500],
249
249
  dangerForeground: "oklch(0.985 0 0)",
250
- dangerHover: chunkZBGR7MUW_cjs.red[400],
251
- dangerActive: chunkZBGR7MUW_cjs.red[300],
252
- dangerMuted: chunkZBGR7MUW_cjs.red[950],
253
- dangerMutedForeground: chunkZBGR7MUW_cjs.red[300],
254
- destructive: chunkZBGR7MUW_cjs.red[500],
250
+ dangerHover: chunk6ZZZBOCH_cjs.red[400],
251
+ dangerActive: chunk6ZZZBOCH_cjs.red[300],
252
+ dangerMuted: chunk6ZZZBOCH_cjs.red[950],
253
+ dangerMutedForeground: chunk6ZZZBOCH_cjs.red[300],
254
+ destructive: chunk6ZZZBOCH_cjs.red[500],
255
255
  destructiveForeground: "oklch(0.985 0 0)",
256
- info: chunkZBGR7MUW_cjs.blue[400],
256
+ info: chunk6ZZZBOCH_cjs.blue[400],
257
257
  infoForeground: "oklch(0.145 0 0)",
258
- infoMuted: chunkZBGR7MUW_cjs.blue[950],
259
- infoMutedForeground: chunkZBGR7MUW_cjs.blue[300]
258
+ infoMuted: chunk6ZZZBOCH_cjs.blue[950],
259
+ infoMutedForeground: chunk6ZZZBOCH_cjs.blue[300]
260
260
  };
261
261
  var CHART_LIGHT = {
262
262
  chart1: "oklch(0.646 0.222 41.116)",
@@ -416,7 +416,7 @@ function buildNeutralPreset(name, key, palette) {
416
416
  disabledForeground: palette[600],
417
417
  sidebar: palette[900],
418
418
  sidebarForeground: palette[50],
419
- sidebarPrimary: chunkZBGR7MUW_cjs.blue[600],
419
+ sidebarPrimary: chunk6ZZZBOCH_cjs.blue[600],
420
420
  sidebarPrimaryForeground: palette[50],
421
421
  sidebarAccent: palette[800],
422
422
  sidebarAccentForeground: palette[50],
@@ -425,7 +425,7 @@ function buildNeutralPreset(name, key, palette) {
425
425
  }
426
426
  };
427
427
  }
428
- function buildChromaticPreset(name, key, primary, surface = chunkZBGR7MUW_cjs.zinc) {
428
+ function buildChromaticPreset(name, key, primary, surface = chunk6ZZZBOCH_cjs.zinc) {
429
429
  return {
430
430
  name,
431
431
  key,
@@ -527,16 +527,16 @@ var COLOR_PRESETS = [
527
527
  // Neutral Presets (achromatic primaries)
528
528
  // -------------------------------------------------------------------------
529
529
  {
530
- swatch: chunkZBGR7MUW_cjs.zinc[900],
531
- ...buildNeutralPreset("Zinc", "zinc", chunkZBGR7MUW_cjs.zinc)
530
+ swatch: chunk6ZZZBOCH_cjs.zinc[900],
531
+ ...buildNeutralPreset("Zinc", "zinc", chunk6ZZZBOCH_cjs.zinc)
532
532
  },
533
533
  {
534
- swatch: chunkZBGR7MUW_cjs.slate[900],
535
- ...buildNeutralPreset("Slate", "slate", chunkZBGR7MUW_cjs.slate)
534
+ swatch: chunk6ZZZBOCH_cjs.slate[900],
535
+ ...buildNeutralPreset("Slate", "slate", chunk6ZZZBOCH_cjs.slate)
536
536
  },
537
537
  {
538
- swatch: chunkZBGR7MUW_cjs.gray[900],
539
- ...buildNeutralPreset("Gray", "gray", chunkZBGR7MUW_cjs.gray)
538
+ swatch: chunk6ZZZBOCH_cjs.gray[900],
539
+ ...buildNeutralPreset("Gray", "gray", chunk6ZZZBOCH_cjs.gray)
540
540
  },
541
541
  {
542
542
  swatch: stone[900],
@@ -550,12 +550,12 @@ var COLOR_PRESETS = [
550
550
  // Chromatic Presets (colored primaries)
551
551
  // -------------------------------------------------------------------------
552
552
  {
553
- swatch: chunkZBGR7MUW_cjs.blue[600],
554
- ...buildChromaticPreset("Blue", "blue", chunkZBGR7MUW_cjs.blue)
553
+ swatch: chunk6ZZZBOCH_cjs.blue[600],
554
+ ...buildChromaticPreset("Blue", "blue", chunk6ZZZBOCH_cjs.blue)
555
555
  },
556
556
  {
557
- swatch: chunkZBGR7MUW_cjs.green[600],
558
- ...buildChromaticPreset("Green", "green", chunkZBGR7MUW_cjs.green)
557
+ swatch: chunk6ZZZBOCH_cjs.green[600],
558
+ ...buildChromaticPreset("Green", "green", chunk6ZZZBOCH_cjs.green)
559
559
  },
560
560
  {
561
561
  swatch: violet[600],
@@ -570,16 +570,56 @@ var COLOR_PRESETS = [
570
570
  ...buildChromaticPreset("Orange", "orange", orange)
571
571
  },
572
572
  {
573
- swatch: chunkZBGR7MUW_cjs.red[600],
574
- ...buildChromaticPreset("Red", "red", chunkZBGR7MUW_cjs.red)
573
+ swatch: chunk6ZZZBOCH_cjs.red[600],
574
+ ...buildChromaticPreset("Red", "red", chunk6ZZZBOCH_cjs.red)
575
575
  },
576
576
  {
577
- swatch: chunkZBGR7MUW_cjs.teal[600],
578
- ...buildChromaticPreset("Teal", "teal", chunkZBGR7MUW_cjs.teal)
577
+ swatch: chunk6ZZZBOCH_cjs.teal[600],
578
+ ...buildChromaticPreset("Teal", "teal", chunk6ZZZBOCH_cjs.teal)
579
579
  },
580
580
  {
581
- swatch: chunkZBGR7MUW_cjs.brand[600],
582
- ...buildChromaticPreset("Brand", "brand", chunkZBGR7MUW_cjs.brand)
581
+ swatch: chunk6ZZZBOCH_cjs.brand[600],
582
+ ...buildChromaticPreset("Brand", "brand", chunk6ZZZBOCH_cjs.brand)
583
+ },
584
+ {
585
+ swatch: chunk6ZZZBOCH_cjs.indigo[600],
586
+ ...buildChromaticPreset("Indigo", "indigo", chunk6ZZZBOCH_cjs.indigo)
587
+ },
588
+ {
589
+ swatch: chunk6ZZZBOCH_cjs.purple[600],
590
+ ...buildChromaticPreset("Purple", "purple", chunk6ZZZBOCH_cjs.purple)
591
+ },
592
+ {
593
+ swatch: chunk6ZZZBOCH_cjs.pink[600],
594
+ ...buildChromaticPreset("Pink", "pink", chunk6ZZZBOCH_cjs.pink)
595
+ },
596
+ {
597
+ swatch: chunk6ZZZBOCH_cjs.cyan[600],
598
+ ...buildChromaticPreset("Cyan", "cyan", chunk6ZZZBOCH_cjs.cyan)
599
+ },
600
+ {
601
+ swatch: chunk6ZZZBOCH_cjs.emerald[600],
602
+ ...buildChromaticPreset("Emerald", "emerald", chunk6ZZZBOCH_cjs.emerald)
603
+ },
604
+ {
605
+ swatch: chunk6ZZZBOCH_cjs.yellow[600],
606
+ ...buildChromaticPreset("Yellow", "yellow", chunk6ZZZBOCH_cjs.yellow)
607
+ },
608
+ {
609
+ swatch: chunk6ZZZBOCH_cjs.fuchsia[600],
610
+ ...buildChromaticPreset("Fuchsia", "fuchsia", chunk6ZZZBOCH_cjs.fuchsia)
611
+ },
612
+ {
613
+ swatch: chunk6ZZZBOCH_cjs.sky[600],
614
+ ...buildChromaticPreset("Sky", "sky", chunk6ZZZBOCH_cjs.sky)
615
+ },
616
+ {
617
+ swatch: chunk6ZZZBOCH_cjs.lime[600],
618
+ ...buildChromaticPreset("Lime", "lime", chunk6ZZZBOCH_cjs.lime)
619
+ },
620
+ {
621
+ swatch: chunk6ZZZBOCH_cjs.amber[600],
622
+ ...buildChromaticPreset("Amber", "amber", chunk6ZZZBOCH_cjs.amber)
583
623
  }
584
624
  ];
585
625
  function getColorPreset(key) {
@@ -600,6 +640,7 @@ function getRadiusPreset(key) {
600
640
  return RADIUS_PRESETS.find((r) => r.key === key) ?? RADIUS_PRESETS[4];
601
641
  }
602
642
  var FONT_PRESETS = [
643
+ // ---- Built-in fonts (loaded via next/font in the docs app) ----
603
644
  {
604
645
  name: "Outfit",
605
646
  key: "outfit",
@@ -612,6 +653,164 @@ var FONT_PRESETS = [
612
653
  value: 'var(--font-inter), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
613
654
  sample: "Aa"
614
655
  },
656
+ {
657
+ name: "Geist Sans",
658
+ key: "geist-sans",
659
+ value: 'var(--font-geist-sans), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
660
+ sample: "Aa"
661
+ },
662
+ {
663
+ name: "DM Sans",
664
+ key: "dm-sans",
665
+ value: 'var(--font-dm-sans), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
666
+ sample: "Aa"
667
+ },
668
+ {
669
+ name: "Plus Jakarta Sans",
670
+ key: "plus-jakarta-sans",
671
+ value: 'var(--font-plus-jakarta-sans), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
672
+ sample: "Aa"
673
+ },
674
+ {
675
+ name: "Open Sans",
676
+ key: "open-sans",
677
+ value: 'var(--font-open-sans), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
678
+ sample: "Aa"
679
+ },
680
+ {
681
+ name: "Poppins",
682
+ key: "poppins",
683
+ value: 'var(--font-poppins), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
684
+ sample: "Aa"
685
+ },
686
+ {
687
+ name: "Montserrat",
688
+ key: "montserrat",
689
+ value: 'var(--font-montserrat), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
690
+ sample: "Aa"
691
+ },
692
+ {
693
+ name: "Lato",
694
+ key: "lato",
695
+ value: 'var(--font-lato), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
696
+ sample: "Aa"
697
+ },
698
+ {
699
+ name: "Nunito",
700
+ key: "nunito",
701
+ value: 'var(--font-nunito), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
702
+ sample: "Aa"
703
+ },
704
+ {
705
+ name: "Raleway",
706
+ key: "raleway",
707
+ value: 'var(--font-raleway), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
708
+ sample: "Aa"
709
+ },
710
+ {
711
+ name: "Rubik",
712
+ key: "rubik",
713
+ value: 'var(--font-rubik), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
714
+ sample: "Aa"
715
+ },
716
+ {
717
+ name: "Source Sans 3",
718
+ key: "source-sans-3",
719
+ value: 'var(--font-source-sans-3), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
720
+ sample: "Aa"
721
+ },
722
+ {
723
+ name: "Work Sans",
724
+ key: "work-sans",
725
+ value: 'var(--font-work-sans), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
726
+ sample: "Aa"
727
+ },
728
+ {
729
+ name: "Manrope",
730
+ key: "manrope",
731
+ value: 'var(--font-manrope), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
732
+ sample: "Aa"
733
+ },
734
+ {
735
+ name: "Space Grotesk",
736
+ key: "space-grotesk",
737
+ value: 'var(--font-space-grotesk), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
738
+ sample: "Aa"
739
+ },
740
+ // ---- Additional popular fonts ----
741
+ {
742
+ name: "Figtree",
743
+ key: "figtree",
744
+ value: 'var(--font-figtree), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
745
+ sample: "Aa"
746
+ },
747
+ {
748
+ name: "IBM Plex Sans",
749
+ key: "ibm-plex-sans",
750
+ value: 'var(--font-ibm-plex-sans), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
751
+ sample: "Aa"
752
+ },
753
+ {
754
+ name: "Quicksand",
755
+ key: "quicksand",
756
+ value: 'var(--font-quicksand), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
757
+ sample: "Aa"
758
+ },
759
+ {
760
+ name: "Cabin",
761
+ key: "cabin",
762
+ value: 'var(--font-cabin), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
763
+ sample: "Aa"
764
+ },
765
+ {
766
+ name: "Barlow",
767
+ key: "barlow",
768
+ value: 'var(--font-barlow), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
769
+ sample: "Aa"
770
+ },
771
+ {
772
+ name: "Josefin Sans",
773
+ key: "josefin-sans",
774
+ value: 'var(--font-josefin-sans), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
775
+ sample: "Aa"
776
+ },
777
+ {
778
+ name: "Karla",
779
+ key: "karla",
780
+ value: 'var(--font-karla), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
781
+ sample: "Aa"
782
+ },
783
+ {
784
+ name: "Mulish",
785
+ key: "mulish",
786
+ value: 'var(--font-mulish), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
787
+ sample: "Aa"
788
+ },
789
+ {
790
+ name: "Noto Sans",
791
+ key: "noto-sans",
792
+ value: 'var(--font-noto-sans), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
793
+ sample: "Aa"
794
+ },
795
+ {
796
+ name: "Ubuntu",
797
+ key: "ubuntu",
798
+ value: 'var(--font-ubuntu), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
799
+ sample: "Aa"
800
+ },
801
+ {
802
+ name: "Sora",
803
+ key: "sora",
804
+ value: 'var(--font-sora), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
805
+ sample: "Aa"
806
+ },
807
+ {
808
+ name: "Lexend",
809
+ key: "lexend",
810
+ value: 'var(--font-lexend), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
811
+ sample: "Aa"
812
+ },
813
+ // ---- Generic stacks ----
615
814
  {
616
815
  name: "System",
617
816
  key: "system",
@@ -751,6 +950,53 @@ var SURFACE_STYLE_PRESETS = [
751
950
  }
752
951
  ];
753
952
  var DEFAULT_SURFACE_STYLE_KEY = "bordered";
953
+ var MENU_COLOR_PRESETS = [
954
+ {
955
+ name: "Default",
956
+ key: "default",
957
+ description: "Uses the color preset's built-in sidebar colors"
958
+ },
959
+ {
960
+ name: "Muted",
961
+ key: "muted",
962
+ description: "Sidebar matches the muted/surface tone \u2014 blends with content"
963
+ },
964
+ {
965
+ name: "Inverted",
966
+ key: "inverted",
967
+ description: "Dark sidebar in light mode, lighter sidebar in dark mode for contrast"
968
+ },
969
+ {
970
+ name: "Primary",
971
+ key: "primary",
972
+ description: "Sidebar uses the primary color as its background"
973
+ }
974
+ ];
975
+ var DEFAULT_MENU_COLOR_KEY = "default";
976
+ function getMenuColorPreset(key) {
977
+ return MENU_COLOR_PRESETS.find((p) => p.key === key) ?? MENU_COLOR_PRESETS[0];
978
+ }
979
+ var MENU_ACCENT_PRESETS = [
980
+ {
981
+ name: "None",
982
+ key: "none",
983
+ description: "No visual accent highlight on sidebar items"
984
+ },
985
+ {
986
+ name: "Subtle",
987
+ key: "subtle",
988
+ description: "Soft background tint on hover and active sidebar items"
989
+ },
990
+ {
991
+ name: "Bold",
992
+ key: "bold",
993
+ description: "Prominent primary-colored accent on active sidebar items"
994
+ }
995
+ ];
996
+ var DEFAULT_MENU_ACCENT_KEY = "subtle";
997
+ function getMenuAccentPreset(key) {
998
+ return MENU_ACCENT_PRESETS.find((p) => p.key === key) ?? MENU_ACCENT_PRESETS[1];
999
+ }
754
1000
  var STYLE_PRESETS = [
755
1001
  {
756
1002
  name: "Vega",
@@ -868,7 +1114,9 @@ var DEFAULT_THEME_CONFIG = {
868
1114
  radius: DEFAULT_RADIUS_KEY,
869
1115
  font: DEFAULT_FONT_KEY,
870
1116
  shadow: DEFAULT_SHADOW_KEY,
871
- surfaceStyle: DEFAULT_SURFACE_STYLE_KEY
1117
+ surfaceStyle: DEFAULT_SURFACE_STYLE_KEY,
1118
+ menuColor: DEFAULT_MENU_COLOR_KEY,
1119
+ menuAccent: DEFAULT_MENU_ACCENT_KEY
872
1120
  };
873
1121
  function buildThemeOverrides(config, mode) {
874
1122
  const vars = {};
@@ -978,6 +1226,76 @@ function buildThemeOverrides(config, mode) {
978
1226
  vars["--ds-gap-default"] = sv.gapDefault;
979
1227
  vars["--ds-border-width"] = sv.borderWidth;
980
1228
  vars["--ds-control-height"] = sv.controlHeight;
1229
+ const colorPresetObj = getColorPreset(config.colorPreset);
1230
+ const presetColors = mode === "dark" ? colorPresetObj.dark : colorPresetObj.light;
1231
+ if (config.menuColor === "muted") {
1232
+ if (mode === "light") {
1233
+ vars["--sidebar"] = presetColors.muted;
1234
+ vars["--sidebar-foreground"] = presetColors.foreground;
1235
+ vars["--sidebar-border"] = presetColors.border;
1236
+ } else {
1237
+ vars["--sidebar"] = presetColors.muted;
1238
+ vars["--sidebar-foreground"] = presetColors.foreground;
1239
+ vars["--sidebar-border"] = presetColors.border;
1240
+ }
1241
+ } else if (config.menuColor === "inverted") {
1242
+ if (mode === "light") {
1243
+ vars["--sidebar"] = "oklch(0.205 0 0)";
1244
+ vars["--sidebar-foreground"] = "oklch(0.95 0 0)";
1245
+ vars["--sidebar-primary"] = presetColors.primary;
1246
+ vars["--sidebar-primary-foreground"] = "oklch(0.985 0 0)";
1247
+ vars["--sidebar-border"] = "oklch(1 0 0 / 10%)";
1248
+ vars["--sidebar-ring"] = "oklch(0.439 0 0)";
1249
+ } else {
1250
+ vars["--sidebar"] = "oklch(0.269 0 0)";
1251
+ vars["--sidebar-foreground"] = "oklch(0.95 0 0)";
1252
+ vars["--sidebar-primary"] = presetColors.primary;
1253
+ vars["--sidebar-primary-foreground"] = "oklch(0.985 0 0)";
1254
+ vars["--sidebar-border"] = "oklch(1 0 0 / 8%)";
1255
+ vars["--sidebar-ring"] = "oklch(0.5 0 0)";
1256
+ }
1257
+ } else if (config.menuColor === "primary") {
1258
+ if (mode === "light") {
1259
+ vars["--sidebar"] = presetColors.primary;
1260
+ vars["--sidebar-foreground"] = presetColors.primaryForeground;
1261
+ vars["--sidebar-primary"] = presetColors.primaryForeground;
1262
+ vars["--sidebar-primary-foreground"] = presetColors.primary;
1263
+ vars["--sidebar-border"] = `color-mix(in oklch, ${presetColors.primaryForeground} 15%, transparent)`;
1264
+ vars["--sidebar-ring"] = presetColors.primaryForeground;
1265
+ } else {
1266
+ vars["--sidebar"] = presetColors.primary;
1267
+ vars["--sidebar-foreground"] = presetColors.primaryForeground;
1268
+ vars["--sidebar-primary"] = presetColors.primaryForeground;
1269
+ vars["--sidebar-primary-foreground"] = presetColors.primary;
1270
+ vars["--sidebar-border"] = `color-mix(in oklch, ${presetColors.primaryForeground} 15%, transparent)`;
1271
+ vars["--sidebar-ring"] = presetColors.primaryForeground;
1272
+ }
1273
+ }
1274
+ if (config.menuAccent === "none") {
1275
+ vars["--sidebar-accent"] = "transparent";
1276
+ vars["--sidebar-accent-foreground"] = vars["--sidebar-foreground"] ?? presetColors.sidebarForeground;
1277
+ } else if (config.menuAccent === "bold") {
1278
+ if (config.menuColor === "primary") {
1279
+ if (mode === "light") {
1280
+ vars["--sidebar-accent"] = `color-mix(in oklch, ${presetColors.primaryForeground} 20%, transparent)`;
1281
+ vars["--sidebar-accent-foreground"] = presetColors.primaryForeground;
1282
+ } else {
1283
+ vars["--sidebar-accent"] = `color-mix(in oklch, ${presetColors.primaryForeground} 20%, transparent)`;
1284
+ vars["--sidebar-accent-foreground"] = presetColors.primaryForeground;
1285
+ }
1286
+ } else if (config.menuColor === "inverted") {
1287
+ vars["--sidebar-accent"] = presetColors.primary;
1288
+ vars["--sidebar-accent-foreground"] = presetColors.primaryForeground;
1289
+ } else {
1290
+ if (mode === "light") {
1291
+ vars["--sidebar-accent"] = presetColors.primaryMuted;
1292
+ vars["--sidebar-accent-foreground"] = presetColors.primary;
1293
+ } else {
1294
+ vars["--sidebar-accent"] = presetColors.primaryMuted;
1295
+ vars["--sidebar-accent-foreground"] = presetColors.primaryMutedForeground;
1296
+ }
1297
+ }
1298
+ }
981
1299
  if (config.surfaceStyle === "elevated") {
982
1300
  vars["--card"] = mode === "dark" ? "oklch(0.205 0 0)" : "oklch(1 0 0)";
983
1301
  vars["--border"] = mode === "dark" ? "oklch(0.205 0 0 / 0)" : "oklch(0.922 0 0 / 0)";
@@ -1000,6 +1318,8 @@ function generateThemeCSS(config) {
1000
1318
  ` * Radius: ${getRadiusPreset(config.radius).label}`,
1001
1319
  ` * Font: ${getFontPreset(config.font).name}`,
1002
1320
  ` * Shadows: ${getShadowPreset(config.shadow).name}`,
1321
+ ` * Menu Color: ${getMenuColorPreset(config.menuColor).name}`,
1322
+ ` * Menu Accent: ${getMenuAccentPreset(config.menuAccent).name}`,
1003
1323
  " * ============================================ */",
1004
1324
  "",
1005
1325
  ":root {",
@@ -1009,7 +1329,7 @@ function generateThemeCSS(config) {
1009
1329
  ".dark {",
1010
1330
  formatVars(darkVars),
1011
1331
  "}"
1012
- ].join("\n");
1332
+ ].filter(Boolean).join("\n");
1013
1333
  }
1014
1334
  var STORAGE_KEY = "ds-theme-customizer";
1015
1335
  var STYLE_ELEMENT_ID = "ds-theme-customizer";
@@ -1037,7 +1357,9 @@ function loadConfig() {
1037
1357
  shadow: SHADOW_PRESETS.some((s) => s.key === parsed.shadow) ? parsed.shadow : DEFAULT_THEME_CONFIG.shadow,
1038
1358
  surfaceStyle: SURFACE_STYLE_PRESETS.some(
1039
1359
  (s) => s.key === parsed.surfaceStyle
1040
- ) ? parsed.surfaceStyle : DEFAULT_THEME_CONFIG.surfaceStyle
1360
+ ) ? parsed.surfaceStyle : DEFAULT_THEME_CONFIG.surfaceStyle,
1361
+ menuColor: MENU_COLOR_PRESETS.some((p) => p.key === parsed.menuColor) ? parsed.menuColor : DEFAULT_THEME_CONFIG.menuColor,
1362
+ menuAccent: MENU_ACCENT_PRESETS.some((p) => p.key === parsed.menuAccent) ? parsed.menuAccent : DEFAULT_THEME_CONFIG.menuAccent
1041
1363
  };
1042
1364
  } catch {
1043
1365
  return DEFAULT_THEME_CONFIG;
@@ -1081,7 +1403,7 @@ function removeStyles() {
1081
1403
  }
1082
1404
  }
1083
1405
  function configsEqual(a, b) {
1084
- return a.style === b.style && a.colorPreset === b.colorPreset && a.radius === b.radius && a.font === b.font && a.shadow === b.shadow && a.surfaceStyle === b.surfaceStyle;
1406
+ return a.style === b.style && a.colorPreset === b.colorPreset && a.radius === b.radius && a.font === b.font && a.shadow === b.shadow && a.surfaceStyle === b.surfaceStyle && a.menuColor === b.menuColor && a.menuAccent === b.menuAccent;
1085
1407
  }
1086
1408
  function ThemeCustomizerProvider({
1087
1409
  children,
@@ -1187,6 +1509,18 @@ function ThemeCustomizerProvider({
1187
1509
  return { ...prev, surfaceStyle: key };
1188
1510
  });
1189
1511
  }, []);
1512
+ const setMenuColor = react.useCallback((key) => {
1513
+ setConfigState((prev) => {
1514
+ if (prev.menuColor === key) return prev;
1515
+ return { ...prev, menuColor: key };
1516
+ });
1517
+ }, []);
1518
+ const setMenuAccent = react.useCallback((key) => {
1519
+ setConfigState((prev) => {
1520
+ if (prev.menuAccent === key) return prev;
1521
+ return { ...prev, menuAccent: key };
1522
+ });
1523
+ }, []);
1190
1524
  const resetConfig = react.useCallback(() => {
1191
1525
  setConfigState(DEFAULT_THEME_CONFIG);
1192
1526
  }, []);
@@ -1204,6 +1538,8 @@ function ThemeCustomizerProvider({
1204
1538
  setFont,
1205
1539
  setShadow,
1206
1540
  setSurfaceStyle,
1541
+ setMenuColor,
1542
+ setMenuAccent,
1207
1543
  resetConfig,
1208
1544
  isDefault,
1209
1545
  generateCSS: generateCSSFn
@@ -1217,6 +1553,8 @@ function ThemeCustomizerProvider({
1217
1553
  setFont,
1218
1554
  setShadow,
1219
1555
  setSurfaceStyle,
1556
+ setMenuColor,
1557
+ setMenuAccent,
1220
1558
  resetConfig,
1221
1559
  isDefault,
1222
1560
  generateCSSFn
@@ -1251,50 +1589,6 @@ function CheckIcon({ className }) {
1251
1589
  }
1252
1590
  );
1253
1591
  }
1254
- function ColorSwatch({
1255
- preset,
1256
- isActive,
1257
- onClick
1258
- }) {
1259
- return /* @__PURE__ */ jsxRuntime.jsxs(
1260
- "button",
1261
- {
1262
- type: "button",
1263
- onClick,
1264
- className: chunk4ON3M3OM_cjs.cn(
1265
- "group relative flex items-center gap-2 rounded-md border px-3 py-2 text-left text-sm transition-all duration-fast ease-standard",
1266
- "hover:border-border-strong hover:bg-muted/50",
1267
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
1268
- isActive ? "border-primary bg-muted/60 shadow-sm" : "border-border bg-transparent"
1269
- ),
1270
- title: preset.name,
1271
- children: [
1272
- /* @__PURE__ */ jsxRuntime.jsx(
1273
- "span",
1274
- {
1275
- className: chunk4ON3M3OM_cjs.cn(
1276
- "size-5 shrink-0 rounded-full border shadow-xs",
1277
- isActive ? "border-primary/50 ring-2 ring-primary/20" : "border-border"
1278
- ),
1279
- style: { backgroundColor: preset.swatch },
1280
- "aria-hidden": "true"
1281
- }
1282
- ),
1283
- /* @__PURE__ */ jsxRuntime.jsx(
1284
- "span",
1285
- {
1286
- className: chunk4ON3M3OM_cjs.cn(
1287
- "text-sm font-medium",
1288
- isActive ? "text-foreground" : "text-muted-foreground"
1289
- ),
1290
- children: preset.name
1291
- }
1292
- ),
1293
- isActive && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "ml-auto text-primary" })
1294
- ]
1295
- }
1296
- );
1297
- }
1298
1592
  function RadiusOption({
1299
1593
  preset,
1300
1594
  isActive,
@@ -1335,49 +1629,433 @@ function RadiusOption({
1335
1629
  }
1336
1630
  );
1337
1631
  }
1338
- function FontOption({
1339
- preset,
1340
- isActive,
1341
- onClick
1342
- }) {
1632
+ function ChevronDownIcon({ className }) {
1633
+ return /* @__PURE__ */ jsxRuntime.jsx(
1634
+ "svg",
1635
+ {
1636
+ className: chunk4ON3M3OM_cjs.cn("size-4 shrink-0", className),
1637
+ xmlns: "http://www.w3.org/2000/svg",
1638
+ viewBox: "0 0 24 24",
1639
+ fill: "none",
1640
+ stroke: "currentColor",
1641
+ strokeWidth: "2",
1642
+ strokeLinecap: "round",
1643
+ strokeLinejoin: "round",
1644
+ "aria-hidden": "true",
1645
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" })
1646
+ }
1647
+ );
1648
+ }
1649
+ function SearchIcon({ className }) {
1343
1650
  return /* @__PURE__ */ jsxRuntime.jsxs(
1344
- "button",
1651
+ "svg",
1345
1652
  {
1346
- type: "button",
1347
- onClick,
1348
- className: chunk4ON3M3OM_cjs.cn(
1349
- "flex items-center gap-2 rounded-md border px-3 py-2 text-left transition-all duration-fast ease-standard",
1350
- "hover:border-border-strong hover:bg-muted/50",
1351
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
1352
- isActive ? "border-primary bg-muted/60 shadow-sm" : "border-border bg-transparent"
1353
- ),
1354
- title: preset.name,
1653
+ className: chunk4ON3M3OM_cjs.cn("size-4 shrink-0", className),
1654
+ xmlns: "http://www.w3.org/2000/svg",
1655
+ viewBox: "0 0 24 24",
1656
+ fill: "none",
1657
+ stroke: "currentColor",
1658
+ strokeWidth: "2",
1659
+ strokeLinecap: "round",
1660
+ strokeLinejoin: "round",
1661
+ "aria-hidden": "true",
1355
1662
  children: [
1356
- /* @__PURE__ */ jsxRuntime.jsx(
1357
- "span",
1358
- {
1359
- className: chunk4ON3M3OM_cjs.cn(
1360
- "text-base font-semibold leading-none",
1361
- isActive ? "text-foreground" : "text-muted-foreground"
1362
- ),
1363
- style: { fontFamily: preset.value },
1364
- children: preset.sample
1365
- }
1663
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "11", cy: "11", r: "8" }),
1664
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m21 21-4.3-4.3" })
1665
+ ]
1666
+ }
1667
+ );
1668
+ }
1669
+ function FontCombobox({
1670
+ presets,
1671
+ activeKey,
1672
+ onSelect
1673
+ }) {
1674
+ const [open, setOpen] = react.useState(false);
1675
+ const [search, setSearch] = react.useState("");
1676
+ const [highlightIndex, setHighlightIndex] = react.useState(-1);
1677
+ const containerRef = react.useRef(null);
1678
+ const listRef = react.useRef(null);
1679
+ const inputRef = react.useRef(null);
1680
+ const activePreset = react.useMemo(
1681
+ () => presets.find((p) => p.key === activeKey) ?? presets[0],
1682
+ [presets, activeKey]
1683
+ );
1684
+ const filtered = react.useMemo(() => {
1685
+ if (!search.trim()) return presets;
1686
+ const q = search.toLowerCase();
1687
+ return presets.filter((p) => p.name.toLowerCase().includes(q));
1688
+ }, [presets, search]);
1689
+ react.useEffect(() => {
1690
+ setHighlightIndex(0);
1691
+ }, [filtered]);
1692
+ react.useEffect(() => {
1693
+ if (!open) return;
1694
+ function handleClick(e) {
1695
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
1696
+ setOpen(false);
1697
+ }
1698
+ }
1699
+ document.addEventListener("mousedown", handleClick);
1700
+ return () => document.removeEventListener("mousedown", handleClick);
1701
+ }, [open]);
1702
+ react.useEffect(() => {
1703
+ if (!open) return;
1704
+ function handleKey(e) {
1705
+ if (e.key === "Escape") {
1706
+ setOpen(false);
1707
+ }
1708
+ }
1709
+ document.addEventListener("keydown", handleKey);
1710
+ return () => document.removeEventListener("keydown", handleKey);
1711
+ }, [open]);
1712
+ react.useEffect(() => {
1713
+ if (open) {
1714
+ requestAnimationFrame(() => inputRef.current?.focus());
1715
+ } else {
1716
+ setSearch("");
1717
+ setHighlightIndex(-1);
1718
+ }
1719
+ }, [open]);
1720
+ react.useEffect(() => {
1721
+ if (!open || highlightIndex < 0 || !listRef.current) return;
1722
+ const items = listRef.current.querySelectorAll("[data-font-item]");
1723
+ items[highlightIndex]?.scrollIntoView({ block: "nearest" });
1724
+ }, [highlightIndex, open]);
1725
+ const handleSelect = react.useCallback(
1726
+ (key) => {
1727
+ onSelect(key);
1728
+ setOpen(false);
1729
+ },
1730
+ [onSelect]
1731
+ );
1732
+ const handleKeyDown = react.useCallback(
1733
+ (e) => {
1734
+ if (e.key === "ArrowDown") {
1735
+ e.preventDefault();
1736
+ setHighlightIndex((i) => Math.min(i + 1, filtered.length - 1));
1737
+ } else if (e.key === "ArrowUp") {
1738
+ e.preventDefault();
1739
+ setHighlightIndex((i) => Math.max(i - 1, 0));
1740
+ } else if (e.key === "Enter") {
1741
+ e.preventDefault();
1742
+ if (highlightIndex >= 0 && highlightIndex < filtered.length) {
1743
+ handleSelect(filtered[highlightIndex].key);
1744
+ }
1745
+ }
1746
+ },
1747
+ [filtered, highlightIndex, handleSelect]
1748
+ );
1749
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "relative", children: [
1750
+ /* @__PURE__ */ jsxRuntime.jsxs(
1751
+ "button",
1752
+ {
1753
+ type: "button",
1754
+ onClick: () => setOpen((prev) => !prev),
1755
+ className: chunk4ON3M3OM_cjs.cn(
1756
+ "flex w-full items-center gap-2 rounded-md border px-3 py-2 text-left text-sm transition-all duration-fast ease-standard",
1757
+ "hover:border-border-strong hover:bg-muted/50",
1758
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
1759
+ open ? "border-primary shadow-sm" : "border-border"
1366
1760
  ),
1367
- /* @__PURE__ */ jsxRuntime.jsx(
1368
- "span",
1369
- {
1370
- className: chunk4ON3M3OM_cjs.cn(
1371
- "text-sm",
1372
- isActive ? "text-foreground font-medium" : "text-muted-foreground"
1373
- ),
1374
- children: preset.name
1375
- }
1761
+ "aria-haspopup": "listbox",
1762
+ "aria-expanded": open,
1763
+ children: [
1764
+ /* @__PURE__ */ jsxRuntime.jsx(
1765
+ "span",
1766
+ {
1767
+ className: "text-sm font-semibold leading-none text-muted-foreground",
1768
+ style: { fontFamily: activePreset.value },
1769
+ children: activePreset.sample
1770
+ }
1771
+ ),
1772
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate font-medium text-foreground", children: activePreset.name }),
1773
+ /* @__PURE__ */ jsxRuntime.jsx(
1774
+ ChevronDownIcon,
1775
+ {
1776
+ className: chunk4ON3M3OM_cjs.cn(
1777
+ "text-muted-foreground transition-transform duration-fast",
1778
+ open && "rotate-180"
1779
+ )
1780
+ }
1781
+ )
1782
+ ]
1783
+ }
1784
+ ),
1785
+ open && /* @__PURE__ */ jsxRuntime.jsxs(
1786
+ "div",
1787
+ {
1788
+ className: chunk4ON3M3OM_cjs.cn(
1789
+ "absolute left-0 z-50 mt-1 w-full rounded-md border border-border bg-popover shadow-md",
1790
+ "animate-in fade-in-0 zoom-in-95 slide-in-from-top-2"
1376
1791
  ),
1377
- isActive && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "ml-auto text-primary" })
1378
- ]
1792
+ role: "dialog",
1793
+ "aria-label": "Select font",
1794
+ children: [
1795
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 border-b border-border px-3 py-2", children: [
1796
+ /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { className: "text-muted-foreground" }),
1797
+ /* @__PURE__ */ jsxRuntime.jsx(
1798
+ "input",
1799
+ {
1800
+ ref: inputRef,
1801
+ type: "text",
1802
+ value: search,
1803
+ onChange: (e) => setSearch(e.target.value),
1804
+ onKeyDown: handleKeyDown,
1805
+ placeholder: "Search fonts\u2026",
1806
+ className: "flex-1 bg-transparent text-sm text-foreground placeholder:text-muted-foreground outline-none",
1807
+ "aria-label": "Search fonts",
1808
+ autoComplete: "off",
1809
+ spellCheck: false
1810
+ }
1811
+ )
1812
+ ] }),
1813
+ /* @__PURE__ */ jsxRuntime.jsx(
1814
+ "div",
1815
+ {
1816
+ ref: listRef,
1817
+ className: "max-h-52 overflow-y-auto overscroll-contain p-1",
1818
+ role: "listbox",
1819
+ children: filtered.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "No fonts found" }) : filtered.map((preset, index) => {
1820
+ const isActive = preset.key === activeKey;
1821
+ const isHighlighted = index === highlightIndex;
1822
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1823
+ "button",
1824
+ {
1825
+ type: "button",
1826
+ "data-font-item": "",
1827
+ role: "option",
1828
+ "aria-selected": isActive,
1829
+ onClick: () => handleSelect(preset.key),
1830
+ onMouseEnter: () => setHighlightIndex(index),
1831
+ className: chunk4ON3M3OM_cjs.cn(
1832
+ "flex w-full items-center gap-2.5 rounded-sm px-2.5 py-1.5 text-left text-sm transition-colors",
1833
+ "outline-none",
1834
+ isHighlighted && "bg-muted",
1835
+ isActive && "text-foreground font-medium",
1836
+ !isActive && "text-muted-foreground"
1837
+ ),
1838
+ children: [
1839
+ /* @__PURE__ */ jsxRuntime.jsx(
1840
+ "span",
1841
+ {
1842
+ className: "w-6 text-center text-base font-semibold leading-none",
1843
+ style: { fontFamily: preset.value },
1844
+ "aria-hidden": "true",
1845
+ children: preset.sample
1846
+ }
1847
+ ),
1848
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate", children: preset.name }),
1849
+ isActive && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "text-primary shrink-0" })
1850
+ ]
1851
+ },
1852
+ preset.key
1853
+ );
1854
+ })
1855
+ }
1856
+ )
1857
+ ]
1858
+ }
1859
+ )
1860
+ ] });
1861
+ }
1862
+ function ColorCombobox({
1863
+ presets,
1864
+ activeKey,
1865
+ onSelect
1866
+ }) {
1867
+ const [open, setOpen] = react.useState(false);
1868
+ const [search, setSearch] = react.useState("");
1869
+ const [highlightIndex, setHighlightIndex] = react.useState(-1);
1870
+ const containerRef = react.useRef(null);
1871
+ const listRef = react.useRef(null);
1872
+ const inputRef = react.useRef(null);
1873
+ const activePreset = react.useMemo(
1874
+ () => presets.find((p) => p.key === activeKey) ?? presets[0],
1875
+ [presets, activeKey]
1876
+ );
1877
+ const filtered = react.useMemo(() => {
1878
+ if (!search.trim()) return presets;
1879
+ const q = search.toLowerCase();
1880
+ return presets.filter((p) => p.name.toLowerCase().includes(q));
1881
+ }, [presets, search]);
1882
+ react.useEffect(() => {
1883
+ setHighlightIndex(0);
1884
+ }, [filtered]);
1885
+ react.useEffect(() => {
1886
+ if (!open) return;
1887
+ function handleClick(e) {
1888
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
1889
+ setOpen(false);
1890
+ }
1891
+ }
1892
+ document.addEventListener("mousedown", handleClick);
1893
+ return () => document.removeEventListener("mousedown", handleClick);
1894
+ }, [open]);
1895
+ react.useEffect(() => {
1896
+ if (!open) return;
1897
+ function handleKey(e) {
1898
+ if (e.key === "Escape") {
1899
+ setOpen(false);
1900
+ }
1379
1901
  }
1902
+ document.addEventListener("keydown", handleKey);
1903
+ return () => document.removeEventListener("keydown", handleKey);
1904
+ }, [open]);
1905
+ react.useEffect(() => {
1906
+ if (open) {
1907
+ requestAnimationFrame(() => inputRef.current?.focus());
1908
+ } else {
1909
+ setSearch("");
1910
+ setHighlightIndex(-1);
1911
+ }
1912
+ }, [open]);
1913
+ react.useEffect(() => {
1914
+ if (!open || highlightIndex < 0 || !listRef.current) return;
1915
+ const items = listRef.current.querySelectorAll("[data-color-item]");
1916
+ items[highlightIndex]?.scrollIntoView({ block: "nearest" });
1917
+ }, [highlightIndex, open]);
1918
+ const handleSelect = react.useCallback(
1919
+ (key) => {
1920
+ onSelect(key);
1921
+ setOpen(false);
1922
+ },
1923
+ [onSelect]
1380
1924
  );
1925
+ const handleKeyDown = react.useCallback(
1926
+ (e) => {
1927
+ if (e.key === "ArrowDown") {
1928
+ e.preventDefault();
1929
+ setHighlightIndex((i) => Math.min(i + 1, filtered.length - 1));
1930
+ } else if (e.key === "ArrowUp") {
1931
+ e.preventDefault();
1932
+ setHighlightIndex((i) => Math.max(i - 1, 0));
1933
+ } else if (e.key === "Enter") {
1934
+ e.preventDefault();
1935
+ if (highlightIndex >= 0 && highlightIndex < filtered.length) {
1936
+ handleSelect(filtered[highlightIndex].key);
1937
+ }
1938
+ }
1939
+ },
1940
+ [filtered, highlightIndex, handleSelect]
1941
+ );
1942
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "relative", children: [
1943
+ /* @__PURE__ */ jsxRuntime.jsxs(
1944
+ "button",
1945
+ {
1946
+ type: "button",
1947
+ onClick: () => setOpen((prev) => !prev),
1948
+ className: chunk4ON3M3OM_cjs.cn(
1949
+ "flex w-full items-center gap-2 rounded-md border px-3 py-2 text-left text-sm transition-all duration-fast ease-standard",
1950
+ "hover:border-border-strong hover:bg-muted/50",
1951
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
1952
+ open ? "border-primary shadow-sm" : "border-border"
1953
+ ),
1954
+ "aria-haspopup": "listbox",
1955
+ "aria-expanded": open,
1956
+ children: [
1957
+ /* @__PURE__ */ jsxRuntime.jsx(
1958
+ "span",
1959
+ {
1960
+ className: chunk4ON3M3OM_cjs.cn(
1961
+ "size-5 shrink-0 rounded-full border shadow-xs",
1962
+ "border-border"
1963
+ ),
1964
+ style: { backgroundColor: activePreset.swatch },
1965
+ "aria-hidden": "true"
1966
+ }
1967
+ ),
1968
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate font-medium text-foreground", children: activePreset.name }),
1969
+ /* @__PURE__ */ jsxRuntime.jsx(
1970
+ ChevronDownIcon,
1971
+ {
1972
+ className: chunk4ON3M3OM_cjs.cn(
1973
+ "text-muted-foreground transition-transform duration-fast",
1974
+ open && "rotate-180"
1975
+ )
1976
+ }
1977
+ )
1978
+ ]
1979
+ }
1980
+ ),
1981
+ open && /* @__PURE__ */ jsxRuntime.jsxs(
1982
+ "div",
1983
+ {
1984
+ className: chunk4ON3M3OM_cjs.cn(
1985
+ "absolute left-0 z-50 mt-1 w-full rounded-md border border-border bg-popover shadow-md",
1986
+ "animate-in fade-in-0 zoom-in-95 slide-in-from-top-2"
1987
+ ),
1988
+ role: "dialog",
1989
+ "aria-label": "Select color",
1990
+ children: [
1991
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 border-b border-border px-3 py-2", children: [
1992
+ /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { className: "text-muted-foreground" }),
1993
+ /* @__PURE__ */ jsxRuntime.jsx(
1994
+ "input",
1995
+ {
1996
+ ref: inputRef,
1997
+ type: "text",
1998
+ value: search,
1999
+ onChange: (e) => setSearch(e.target.value),
2000
+ onKeyDown: handleKeyDown,
2001
+ placeholder: "Search colors\u2026",
2002
+ className: "flex-1 bg-transparent text-sm text-foreground placeholder:text-muted-foreground outline-none",
2003
+ "aria-label": "Search colors",
2004
+ autoComplete: "off",
2005
+ spellCheck: false
2006
+ }
2007
+ )
2008
+ ] }),
2009
+ /* @__PURE__ */ jsxRuntime.jsx(
2010
+ "div",
2011
+ {
2012
+ ref: listRef,
2013
+ className: "max-h-52 overflow-y-auto overscroll-contain p-1",
2014
+ role: "listbox",
2015
+ children: filtered.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "No colors found" }) : filtered.map((preset, index) => {
2016
+ const isActive = preset.key === activeKey;
2017
+ const isHighlighted = index === highlightIndex;
2018
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2019
+ "button",
2020
+ {
2021
+ type: "button",
2022
+ "data-color-item": "",
2023
+ role: "option",
2024
+ "aria-selected": isActive,
2025
+ onClick: () => handleSelect(preset.key),
2026
+ onMouseEnter: () => setHighlightIndex(index),
2027
+ className: chunk4ON3M3OM_cjs.cn(
2028
+ "flex w-full items-center gap-2.5 rounded-sm px-2.5 py-1.5 text-left text-sm transition-colors",
2029
+ "outline-none",
2030
+ isHighlighted && "bg-muted",
2031
+ isActive && "text-foreground font-medium",
2032
+ !isActive && "text-muted-foreground"
2033
+ ),
2034
+ children: [
2035
+ /* @__PURE__ */ jsxRuntime.jsx(
2036
+ "span",
2037
+ {
2038
+ className: chunk4ON3M3OM_cjs.cn(
2039
+ "size-4 shrink-0 rounded-full border shadow-xs",
2040
+ isActive ? "border-primary/50 ring-2 ring-primary/20" : "border-border"
2041
+ ),
2042
+ style: { backgroundColor: preset.swatch },
2043
+ "aria-hidden": "true"
2044
+ }
2045
+ ),
2046
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate", children: preset.name }),
2047
+ isActive && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "text-primary shrink-0" })
2048
+ ]
2049
+ },
2050
+ preset.key
2051
+ );
2052
+ })
2053
+ }
2054
+ )
2055
+ ]
2056
+ }
2057
+ )
2058
+ ] });
1381
2059
  }
1382
2060
  function PillToggle({
1383
2061
  label,
@@ -1535,6 +2213,8 @@ function ThemeCustomizer({
1535
2213
  setFont,
1536
2214
  setShadow,
1537
2215
  setSurfaceStyle,
2216
+ setMenuColor,
2217
+ setMenuAccent,
1538
2218
  resetConfig,
1539
2219
  isDefault,
1540
2220
  generateCSS
@@ -1555,15 +2235,14 @@ function ThemeCustomizer({
1555
2235
  },
1556
2236
  preset.key
1557
2237
  )) }) }),
1558
- /* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Color", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2", children: COLOR_PRESETS.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
1559
- ColorSwatch,
2238
+ /* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Color", children: /* @__PURE__ */ jsxRuntime.jsx(
2239
+ ColorCombobox,
1560
2240
  {
1561
- preset,
1562
- isActive: config.colorPreset === preset.key,
1563
- onClick: () => setColorPreset(preset.key)
1564
- },
1565
- preset.key
1566
- )) }) }),
2241
+ presets: COLOR_PRESETS,
2242
+ activeKey: config.colorPreset,
2243
+ onSelect: setColorPreset
2244
+ }
2245
+ ) }),
1567
2246
  /* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Radius", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: RADIUS_PRESETS.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
1568
2247
  RadiusOption,
1569
2248
  {
@@ -1573,15 +2252,14 @@ function ThemeCustomizer({
1573
2252
  },
1574
2253
  preset.key
1575
2254
  )) }) }),
1576
- /* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Font", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2", children: FONT_PRESETS.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
1577
- FontOption,
2255
+ /* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Font", children: /* @__PURE__ */ jsxRuntime.jsx(
2256
+ FontCombobox,
1578
2257
  {
1579
- preset,
1580
- isActive: config.font === preset.key,
1581
- onClick: () => setFont(preset.key)
1582
- },
1583
- preset.key
1584
- )) }) }),
2258
+ presets: FONT_PRESETS,
2259
+ activeKey: config.font,
2260
+ onSelect: setFont
2261
+ }
2262
+ ) }),
1585
2263
  /* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Shadow", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: SHADOW_PRESETS.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
1586
2264
  PillToggle,
1587
2265
  {
@@ -1602,6 +2280,26 @@ function ThemeCustomizer({
1602
2280
  },
1603
2281
  preset.key
1604
2282
  )) }) }),
2283
+ /* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Menu Color", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: MENU_COLOR_PRESETS.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
2284
+ PillToggle,
2285
+ {
2286
+ label: preset.name,
2287
+ isActive: config.menuColor === preset.key,
2288
+ onClick: () => setMenuColor(preset.key),
2289
+ description: preset.description
2290
+ },
2291
+ preset.key
2292
+ )) }) }),
2293
+ /* @__PURE__ */ jsxRuntime.jsx(Section, { title: "Menu Accent", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: MENU_ACCENT_PRESETS.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
2294
+ PillToggle,
2295
+ {
2296
+ label: preset.name,
2297
+ isActive: config.menuAccent === preset.key,
2298
+ onClick: () => setMenuAccent(preset.key),
2299
+ description: preset.description
2300
+ },
2301
+ preset.key
2302
+ )) }) }),
1605
2303
  (showCopyButton || showResetButton) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 border-t border-border pt-4", children: [
1606
2304
  showCopyButton && /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { getText: generateCSS, className: "flex-1" }),
1607
2305
  showResetButton && !isDefault && /* @__PURE__ */ jsxRuntime.jsxs(
@@ -1737,6 +2435,8 @@ function DSThemeProvider({
1737
2435
  exports.COLOR_PRESETS = COLOR_PRESETS;
1738
2436
  exports.COLOR_PRESET_KEYS = COLOR_PRESET_KEYS;
1739
2437
  exports.DEFAULT_FONT_KEY = DEFAULT_FONT_KEY;
2438
+ exports.DEFAULT_MENU_ACCENT_KEY = DEFAULT_MENU_ACCENT_KEY;
2439
+ exports.DEFAULT_MENU_COLOR_KEY = DEFAULT_MENU_COLOR_KEY;
1740
2440
  exports.DEFAULT_RADIUS_KEY = DEFAULT_RADIUS_KEY;
1741
2441
  exports.DEFAULT_SHADOW_KEY = DEFAULT_SHADOW_KEY;
1742
2442
  exports.DEFAULT_STYLE_KEY = DEFAULT_STYLE_KEY;
@@ -1744,11 +2444,14 @@ exports.DEFAULT_SURFACE_STYLE_KEY = DEFAULT_SURFACE_STYLE_KEY;
1744
2444
  exports.DEFAULT_THEME_CONFIG = DEFAULT_THEME_CONFIG;
1745
2445
  exports.DSThemeProvider = DSThemeProvider;
1746
2446
  exports.FONT_PRESETS = FONT_PRESETS;
2447
+ exports.MENU_ACCENT_PRESETS = MENU_ACCENT_PRESETS;
2448
+ exports.MENU_COLOR_PRESETS = MENU_COLOR_PRESETS;
1747
2449
  exports.RADIUS_PRESETS = RADIUS_PRESETS;
1748
2450
  exports.SHADOW_PRESETS = SHADOW_PRESETS;
1749
2451
  exports.STYLE_PRESETS = STYLE_PRESETS;
1750
2452
  exports.SURFACE_STYLE_PRESETS = SURFACE_STYLE_PRESETS;
1751
2453
  exports.ThemeCustomizer = ThemeCustomizer;
2454
+ exports.ThemeCustomizerContext = ThemeCustomizerContext;
1752
2455
  exports.ThemeCustomizerProvider = ThemeCustomizerProvider;
1753
2456
  exports.buildDarkThemeVars = buildDarkThemeVars;
1754
2457
  exports.buildLightThemeVars = buildLightThemeVars;
@@ -1759,6 +2462,8 @@ exports.cssVar = cssVar;
1759
2462
  exports.generateThemeCSS = generateThemeCSS;
1760
2463
  exports.getColorPreset = getColorPreset;
1761
2464
  exports.getFontPreset = getFontPreset;
2465
+ exports.getMenuAccentPreset = getMenuAccentPreset;
2466
+ exports.getMenuColorPreset = getMenuColorPreset;
1762
2467
  exports.getRadiusPreset = getRadiusPreset;
1763
2468
  exports.getShadowPreset = getShadowPreset;
1764
2469
  exports.getStylePreset = getStylePreset;