@salmexio/ui 0.4.0 → 1.0.0

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.
Files changed (110) hide show
  1. package/README.md +52 -3
  2. package/dist/dialogs/ContextMenu/ContextMenu.svelte +97 -94
  3. package/dist/dialogs/ContextMenu/ContextMenu.svelte.d.ts +3 -2
  4. package/dist/dialogs/ContextMenu/ContextMenu.svelte.d.ts.map +1 -1
  5. package/dist/dialogs/Modal/Modal.svelte +112 -116
  6. package/dist/dialogs/Modal/Modal.svelte.d.ts +1 -1
  7. package/dist/feedback/Alert/Alert.svelte +115 -221
  8. package/dist/feedback/Alert/Alert.svelte.d.ts +1 -1
  9. package/dist/feedback/ProgressBar/ProgressBar.svelte +246 -0
  10. package/dist/feedback/ProgressBar/ProgressBar.svelte.d.ts +40 -0
  11. package/dist/feedback/ProgressBar/ProgressBar.svelte.d.ts.map +1 -0
  12. package/dist/feedback/ProgressBar/index.d.ts +2 -0
  13. package/dist/feedback/ProgressBar/index.d.ts.map +1 -0
  14. package/dist/feedback/ProgressBar/index.js +1 -0
  15. package/dist/feedback/Skeleton/Skeleton.svelte +153 -0
  16. package/dist/feedback/Skeleton/Skeleton.svelte.d.ts +37 -0
  17. package/dist/feedback/Skeleton/Skeleton.svelte.d.ts.map +1 -0
  18. package/dist/feedback/Skeleton/index.d.ts +2 -0
  19. package/dist/feedback/Skeleton/index.d.ts.map +1 -0
  20. package/dist/feedback/Skeleton/index.js +1 -0
  21. package/dist/feedback/Spinner/Spinner.svelte +86 -151
  22. package/dist/feedback/Spinner/Spinner.svelte.d.ts +5 -3
  23. package/dist/feedback/Spinner/Spinner.svelte.d.ts.map +1 -1
  24. package/dist/feedback/Toast/Toaster.svelte +431 -0
  25. package/dist/feedback/Toast/Toaster.svelte.d.ts +22 -0
  26. package/dist/feedback/Toast/Toaster.svelte.d.ts.map +1 -0
  27. package/dist/feedback/Toast/index.d.ts +4 -0
  28. package/dist/feedback/Toast/index.d.ts.map +1 -0
  29. package/dist/feedback/Toast/index.js +2 -0
  30. package/dist/feedback/Toast/toastStore.d.ts +34 -0
  31. package/dist/feedback/Toast/toastStore.d.ts.map +1 -0
  32. package/dist/feedback/Toast/toastStore.js +43 -0
  33. package/dist/feedback/index.d.ts +4 -0
  34. package/dist/feedback/index.d.ts.map +1 -1
  35. package/dist/feedback/index.js +3 -0
  36. package/dist/forms/Checkbox/Checkbox.svelte +82 -104
  37. package/dist/forms/Checkbox/Checkbox.svelte.d.ts +1 -1
  38. package/dist/forms/Select/Select.svelte +137 -179
  39. package/dist/forms/Select/Select.svelte.d.ts +1 -1
  40. package/dist/forms/Slider/Slider.svelte +356 -0
  41. package/dist/forms/Slider/Slider.svelte.d.ts +50 -0
  42. package/dist/forms/Slider/Slider.svelte.d.ts.map +1 -0
  43. package/dist/forms/Slider/index.d.ts +2 -0
  44. package/dist/forms/Slider/index.d.ts.map +1 -0
  45. package/dist/forms/Slider/index.js +1 -0
  46. package/dist/forms/TextInput/TextInput.svelte +151 -167
  47. package/dist/forms/TextInput/TextInput.svelte.d.ts +1 -1
  48. package/dist/forms/Textarea/Textarea.svelte +615 -0
  49. package/dist/forms/Textarea/Textarea.svelte.d.ts +47 -0
  50. package/dist/forms/Textarea/Textarea.svelte.d.ts.map +1 -0
  51. package/dist/forms/Textarea/index.d.ts +2 -0
  52. package/dist/forms/Textarea/index.d.ts.map +1 -0
  53. package/dist/forms/Textarea/index.js +1 -0
  54. package/dist/forms/Toggle/Toggle.svelte +239 -0
  55. package/dist/forms/Toggle/Toggle.svelte.d.ts +39 -0
  56. package/dist/forms/Toggle/Toggle.svelte.d.ts.map +1 -0
  57. package/dist/forms/Toggle/index.d.ts +2 -0
  58. package/dist/forms/Toggle/index.d.ts.map +1 -0
  59. package/dist/forms/Toggle/index.js +1 -0
  60. package/dist/forms/index.d.ts +3 -0
  61. package/dist/forms/index.d.ts.map +1 -1
  62. package/dist/forms/index.js +3 -0
  63. package/dist/index.d.ts +0 -1
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +0 -1
  66. package/dist/layout/Card/Card.svelte +64 -39
  67. package/dist/layout/Card/Card.svelte.d.ts +1 -1
  68. package/dist/layout/Card/Card.svelte.d.ts.map +1 -1
  69. package/dist/layout/Container/Container.svelte +71 -71
  70. package/dist/layout/Container/Container.svelte.d.ts +2 -2
  71. package/dist/navigation/CommandPalette/CommandPalette.svelte +407 -189
  72. package/dist/navigation/CommandPalette/CommandPalette.svelte.d.ts +8 -3
  73. package/dist/navigation/CommandPalette/CommandPalette.svelte.d.ts.map +1 -1
  74. package/dist/navigation/Tabs/Tabs.svelte +95 -181
  75. package/dist/navigation/Tabs/Tabs.svelte.d.ts +2 -2
  76. package/dist/primitives/Badge/Badge.svelte +83 -220
  77. package/dist/primitives/Badge/Badge.svelte.d.ts +2 -2
  78. package/dist/primitives/Badge/Badge.svelte.d.ts.map +1 -1
  79. package/dist/primitives/Button/Button.svelte +144 -195
  80. package/dist/primitives/Button/Button.svelte.d.ts +3 -3
  81. package/dist/primitives/Button/Button.svelte.d.ts.map +1 -1
  82. package/dist/primitives/Tooltip/Tooltip.svelte +260 -0
  83. package/dist/primitives/Tooltip/Tooltip.svelte.d.ts +36 -0
  84. package/dist/primitives/Tooltip/Tooltip.svelte.d.ts.map +1 -0
  85. package/dist/primitives/Tooltip/index.d.ts +2 -0
  86. package/dist/primitives/Tooltip/index.d.ts.map +1 -0
  87. package/dist/primitives/Tooltip/index.js +1 -0
  88. package/dist/primitives/index.d.ts +1 -0
  89. package/dist/primitives/index.d.ts.map +1 -1
  90. package/dist/primitives/index.js +1 -0
  91. package/dist/styles/tokens.css +197 -265
  92. package/package.json +5 -5
  93. package/dist/windowing/Window/Window.svelte +0 -637
  94. package/dist/windowing/Window/Window.svelte.d.ts +0 -65
  95. package/dist/windowing/Window/Window.svelte.d.ts.map +0 -1
  96. package/dist/windowing/Window/index.d.ts +0 -2
  97. package/dist/windowing/Window/index.d.ts.map +0 -1
  98. package/dist/windowing/Window/index.js +0 -1
  99. package/dist/windowing/WindowManager/WindowManager.svelte +0 -425
  100. package/dist/windowing/WindowManager/WindowManager.svelte.d.ts +0 -38
  101. package/dist/windowing/WindowManager/WindowManager.svelte.d.ts.map +0 -1
  102. package/dist/windowing/WindowManager/index.d.ts +0 -2
  103. package/dist/windowing/WindowManager/index.d.ts.map +0 -1
  104. package/dist/windowing/WindowManager/index.js +0 -1
  105. package/dist/windowing/index.d.ts +0 -5
  106. package/dist/windowing/index.d.ts.map +0 -1
  107. package/dist/windowing/index.js +0 -3
  108. package/dist/windowing/windowStore.svelte.d.ts +0 -49
  109. package/dist/windowing/windowStore.svelte.d.ts.map +0 -1
  110. package/dist/windowing/windowStore.svelte.js +0 -170
@@ -1,7 +1,7 @@
1
1
  <!--
2
2
  @component Select
3
3
 
4
- Win2K × Basquiat — Dropdown select with sunken trigger field, raised panel,
4
+ Neo-Brutalist Dark — Dropdown select with clean trigger field, glass-blur panel,
5
5
  keyboard-first navigation, type-ahead search, option groups, and multi-select.
6
6
 
7
7
  Follows WAI-ARIA APG Select-Only Combobox pattern: DOM focus stays on
@@ -219,7 +219,7 @@ function scrollActiveIntoView() {
219
219
  if (!listboxEl || activeIndex < 0) return;
220
220
  const active = listboxEl.querySelector(`[data-option-index="${activeIndex}"]`) as HTMLElement;
221
221
  if (!active) return;
222
- // Manual scroll math only scrolls the listbox, never the page
222
+ // Manual scroll math -- only scrolls the listbox, never the page
223
223
  const listTop = listboxEl.scrollTop;
224
224
  const listHeight = listboxEl.clientHeight;
225
225
  const elTop = active.offsetTop;
@@ -430,29 +430,29 @@ onMount(() => {
430
430
  </script>
431
431
 
432
432
  <div
433
- class={cn('salmex-select-wrapper', `salmex-select-${size}`, className)}
433
+ class={cn('sx-select-wrapper', `sx-select-${size}`, className)}
434
434
  data-testid={testId}
435
435
  >
436
436
  <!-- Label -->
437
437
  <label
438
438
  id={labelId}
439
439
  for={id}
440
- class={cn('salmex-select-label', hideLabel && 'salmex-sr-only')}
440
+ class={cn('sx-select-label', hideLabel && 'sx-sr-only')}
441
441
  >
442
442
  {label}
443
- {#if required}<span class="salmex-select-required" aria-hidden="true">*</span>{/if}
443
+ {#if required}<span class="sx-select-required" aria-hidden="true">*</span>{/if}
444
444
  </label>
445
445
 
446
- <!-- Trigger button DOM focus always stays here -->
446
+ <!-- Trigger button -- DOM focus always stays here -->
447
447
  <button
448
448
  bind:this={triggerEl}
449
449
  {id}
450
450
  type="button"
451
451
  class={cn(
452
- 'salmex-select-trigger',
453
- isOpen && 'salmex-select-trigger-open',
454
- showError && 'salmex-select-trigger-error',
455
- disabled && 'salmex-select-trigger-disabled'
452
+ 'sx-select-trigger',
453
+ isOpen && 'sx-select-trigger-open',
454
+ showError && 'sx-select-trigger-error',
455
+ disabled && 'sx-select-trigger-disabled'
456
456
  )}
457
457
  role="combobox"
458
458
  aria-expanded={isOpen}
@@ -467,10 +467,10 @@ onMount(() => {
467
467
  onclick={toggle}
468
468
  onkeydown={handleKeydown}
469
469
  >
470
- <span class="salmex-select-value" class:salmex-select-placeholder={!selectedOption && selectedLabels.length === 0}>
470
+ <span class="sx-select-value" class:sx-select-placeholder={!selectedOption && selectedLabels.length === 0}>
471
471
  {displayText}
472
472
  </span>
473
- <span class="salmex-select-chevron" aria-hidden="true">
473
+ <span class="sx-select-chevron" aria-hidden="true">
474
474
  <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
475
475
  <path d="M3 4.5L6 7.5L9 4.5" />
476
476
  </svg>
@@ -478,22 +478,22 @@ onMount(() => {
478
478
  </button>
479
479
 
480
480
  <!-- Footer: error / hint -->
481
- <div class="salmex-select-footer">
481
+ <div class="sx-select-footer">
482
482
  {#if showError}
483
- <p id={errorId} class="salmex-select-error" role="alert" aria-live="assertive">{error}</p>
483
+ <p id={errorId} class="sx-select-error" role="alert" aria-live="assertive">{error}</p>
484
484
  {:else if hint}
485
- <p id={hintId} class="salmex-select-hint">{hint}</p>
485
+ <p id={hintId} class="sx-select-hint">{hint}</p>
486
486
  {/if}
487
487
  </div>
488
488
  </div>
489
489
 
490
- <!-- Dropdown panel fixed positioning to escape overflow/stacking contexts -->
490
+ <!-- Dropdown panel -- fixed positioning to escape overflow/stacking contexts -->
491
491
  {#if isOpen}
492
492
  <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
493
493
  <div
494
494
  bind:this={listboxEl}
495
495
  id={listboxId}
496
- class="salmex-select-panel"
496
+ class="sx-select-panel"
497
497
  style="position:fixed;left:{panelLeft}px;{placeAbove ? `bottom:${window.innerHeight - panelTop}px` : `top:${panelTop}px`};width:{panelWidth}px;max-height:{panelMaxHeight}px;"
498
498
  role="listbox"
499
499
  aria-labelledby={labelId}
@@ -504,7 +504,7 @@ onMount(() => {
504
504
  {#if groups.length > 0}
505
505
  {#each groups as group, gi}
506
506
  <div role="group" aria-label={group.label}>
507
- <div class="salmex-select-group-label">{group.label}</div>
507
+ <div class="sx-select-group-label">{group.label}</div>
508
508
  {#each group.options as opt, oi}
509
509
  {@const globalIdx = getGlobalIndex(gi, oi)}
510
510
  {@const isActive = globalIdx === activeIndex}
@@ -513,10 +513,10 @@ onMount(() => {
513
513
  <div
514
514
  id={getOptionId(globalIdx)}
515
515
  class={cn(
516
- 'salmex-select-option',
517
- isActive && 'salmex-select-option-active',
518
- isSelected && 'salmex-select-option-selected',
519
- opt.disabled && 'salmex-select-option-disabled'
516
+ 'sx-select-option',
517
+ isActive && 'sx-select-option-active',
518
+ isSelected && 'sx-select-option-selected',
519
+ opt.disabled && 'sx-select-option-disabled'
520
520
  )}
521
521
  role="option"
522
522
  tabindex="-1"
@@ -527,15 +527,15 @@ onMount(() => {
527
527
  onmousedown={(e) => handleOptionMouseDown(e, opt)}
528
528
  >
529
529
  {#if multiple}
530
- <span class="salmex-select-check" aria-hidden="true">
530
+ <span class="sx-select-check" aria-hidden="true">
531
531
  {#if isSelected}
532
532
  <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M2.5 6L5 8.5L9.5 3.5" /></svg>
533
533
  {/if}
534
534
  </span>
535
535
  {/if}
536
- <span class="salmex-select-option-label">{opt.label}</span>
536
+ <span class="sx-select-option-label">{opt.label}</span>
537
537
  {#if !multiple && isSelected}
538
- <span class="salmex-select-checkmark" aria-hidden="true">
538
+ <span class="sx-select-checkmark" aria-hidden="true">
539
539
  <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M2.5 6L5 8.5L9.5 3.5" /></svg>
540
540
  </span>
541
541
  {/if}
@@ -551,10 +551,10 @@ onMount(() => {
551
551
  <div
552
552
  id={getOptionId(i)}
553
553
  class={cn(
554
- 'salmex-select-option',
555
- isActive && 'salmex-select-option-active',
556
- isSelected && 'salmex-select-option-selected',
557
- opt.disabled && 'salmex-select-option-disabled'
554
+ 'sx-select-option',
555
+ isActive && 'sx-select-option-active',
556
+ isSelected && 'sx-select-option-selected',
557
+ opt.disabled && 'sx-select-option-disabled'
558
558
  )}
559
559
  role="option"
560
560
  tabindex="-1"
@@ -565,15 +565,15 @@ onMount(() => {
565
565
  onmousedown={(e) => handleOptionMouseDown(e, opt)}
566
566
  >
567
567
  {#if multiple}
568
- <span class="salmex-select-check" aria-hidden="true">
568
+ <span class="sx-select-check" aria-hidden="true">
569
569
  {#if isSelected}
570
570
  <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M2.5 6L5 8.5L9.5 3.5" /></svg>
571
571
  {/if}
572
572
  </span>
573
573
  {/if}
574
- <span class="salmex-select-option-label">{opt.label}</span>
574
+ <span class="sx-select-option-label">{opt.label}</span>
575
575
  {#if !multiple && isSelected}
576
- <span class="salmex-select-checkmark" aria-hidden="true">
576
+ <span class="sx-select-checkmark" aria-hidden="true">
577
577
  <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M2.5 6L5 8.5L9.5 3.5" /></svg>
578
578
  </span>
579
579
  {/if}
@@ -587,29 +587,28 @@ onMount(() => {
587
587
  /* ========================================
588
588
  WRAPPER
589
589
  ======================================== */
590
- .salmex-select-wrapper {
590
+ .sx-select-wrapper {
591
591
  display: flex;
592
592
  flex-direction: column;
593
- gap: var(--salmex-space-1);
594
- font-family: var(--salmex-font-system);
593
+ gap: var(--sx-space-1);
594
+ font-family: var(--sx-font-body);
595
595
  }
596
596
 
597
597
  /* ========================================
598
598
  LABEL
599
599
  ======================================== */
600
- .salmex-select-label {
601
- font-size: var(--salmex-font-size-sm);
602
- font-weight: 700;
603
- letter-spacing: 0.3px;
604
- color: rgb(var(--salmex-text-primary));
600
+ .sx-select-label {
601
+ font-size: var(--sx-text-sm);
602
+ font-weight: 500;
603
+ color: var(--sx-color-text-secondary);
605
604
  }
606
605
 
607
- .salmex-select-required {
608
- color: rgb(var(--salmex-street-red));
606
+ .sx-select-required {
607
+ color: var(--sx-color-red);
609
608
  margin-left: 2px;
610
609
  }
611
610
 
612
- .salmex-sr-only {
611
+ .sx-sr-only {
613
612
  position: absolute;
614
613
  width: 1px;
615
614
  height: 1px;
@@ -622,177 +621,146 @@ onMount(() => {
622
621
  }
623
622
 
624
623
  /* ========================================
625
- TRIGGER Sunken field matching TextInput
624
+ TRIGGER -- Same style as TextInput
626
625
  ======================================== */
627
- .salmex-select-trigger {
626
+ .sx-select-trigger {
628
627
  display: flex;
629
628
  align-items: center;
630
629
  justify-content: space-between;
631
- gap: var(--salmex-space-2);
630
+ gap: var(--sx-space-2);
632
631
  width: 100%;
633
- border: 1px solid rgb(var(--salmex-border-dark));
634
- border-radius: var(--salmex-radius-sm);
635
- background: rgb(var(--salmex-bg-primary));
636
- color: rgb(var(--salmex-text-primary));
637
- font-family: var(--salmex-font-system);
638
- font-weight: 600;
632
+ border: 1px solid var(--sx-color-border-strong);
633
+ border-radius: var(--sx-radius-md);
634
+ background: var(--sx-color-surface);
635
+ color: var(--sx-color-text);
636
+ font-family: var(--sx-font-body);
637
+ font-weight: 500;
639
638
  cursor: pointer;
640
639
  text-align: left;
641
- transition: all var(--salmex-transition-fast);
642
- /* Sunken inset — same as TextInput */
643
- box-shadow:
644
- inset 1px 1px 0 rgb(var(--salmex-button-shadow)),
645
- inset -1px -1px 0 rgb(var(--salmex-button-highlight));
640
+ transition: border-color var(--sx-transition-fast), box-shadow var(--sx-transition-fast);
646
641
  }
647
642
 
648
- .salmex-select-trigger:hover:not(:disabled) {
649
- border-color: rgb(var(--salmex-text-primary));
643
+ .sx-select-trigger:hover:not(:disabled) {
644
+ border-color: var(--sx-color-border-hover);
650
645
  }
651
646
 
652
- .salmex-select-trigger:focus-visible {
647
+ .sx-select-trigger:focus-visible {
653
648
  outline: none;
654
- border-color: rgb(var(--salmex-text-primary));
655
- box-shadow:
656
- inset 1px 1px 0 rgb(var(--salmex-button-shadow)),
657
- inset -1px -1px 0 rgb(var(--salmex-button-highlight)),
658
- 0 0 0 2px rgb(var(--salmex-midnight-black)),
659
- 0 0 2px 4px rgb(var(--salmex-crown-yellow));
660
- }
661
-
662
- :global([data-theme='dark']) .salmex-select-trigger:focus-visible {
663
- box-shadow:
664
- inset 1px 1px 0 rgb(var(--salmex-button-shadow)),
665
- inset -1px -1px 0 rgb(var(--salmex-button-highlight)),
666
- 0 0 2px 3px rgb(var(--salmex-crown-yellow));
649
+ border-color: var(--sx-color-cyan);
650
+ box-shadow: 0 0 0 3px var(--sx-color-cyan-ring);
667
651
  }
668
652
 
669
- .salmex-select-trigger-open {
670
- border-color: rgb(var(--salmex-text-primary));
653
+ .sx-select-trigger-open {
654
+ border-color: var(--sx-color-cyan);
655
+ box-shadow: 0 0 0 3px var(--sx-color-cyan-ring);
671
656
  }
672
657
 
673
- .salmex-select-trigger-error {
674
- border-color: rgb(var(--salmex-street-red));
658
+ .sx-select-trigger-error {
659
+ border-color: var(--sx-color-red);
660
+ box-shadow: 0 0 0 3px var(--sx-color-red-ring);
675
661
  }
676
662
 
677
- .salmex-select-trigger-disabled {
663
+ .sx-select-trigger-disabled {
678
664
  opacity: 0.5;
679
665
  cursor: not-allowed;
680
- filter: grayscale(0.5);
681
666
  }
682
667
 
683
668
  /* ========================================
684
669
  SIZES
685
670
  ======================================== */
686
- .salmex-select-sm .salmex-select-trigger {
687
- min-height: 24px;
688
- padding: 0 var(--salmex-space-3);
689
- font-size: var(--salmex-font-size-xs);
690
- }
691
-
692
- .salmex-select-md .salmex-select-trigger {
671
+ .sx-select-sm .sx-select-trigger {
693
672
  min-height: 32px;
694
- padding: 0 var(--salmex-space-4);
695
- font-size: var(--salmex-font-size-base);
673
+ padding: 0 var(--sx-space-3);
674
+ font-size: var(--sx-text-xs);
696
675
  }
697
676
 
698
- .salmex-select-lg .salmex-select-trigger {
677
+ .sx-select-md .sx-select-trigger {
699
678
  min-height: 40px;
700
- padding: 0 var(--salmex-space-5);
701
- font-size: var(--salmex-font-size-md);
679
+ padding: 0 var(--sx-space-4);
680
+ font-size: var(--sx-text-sm);
681
+ }
682
+
683
+ .sx-select-lg .sx-select-trigger {
684
+ min-height: 48px;
685
+ padding: 0 var(--sx-space-5);
686
+ font-size: var(--sx-text-base);
702
687
  }
703
688
 
704
689
  /* ========================================
705
690
  VALUE DISPLAY
706
691
  ======================================== */
707
- .salmex-select-value {
692
+ .sx-select-value {
708
693
  flex: 1;
709
694
  overflow: hidden;
710
695
  text-overflow: ellipsis;
711
696
  white-space: nowrap;
712
697
  }
713
698
 
714
- .salmex-select-placeholder {
715
- color: rgb(var(--salmex-text-disabled));
699
+ .sx-select-placeholder {
700
+ color: var(--sx-color-text-disabled);
716
701
  }
717
702
 
718
- .salmex-select-chevron {
703
+ .sx-select-chevron {
719
704
  flex-shrink: 0;
720
705
  display: flex;
721
706
  align-items: center;
722
- transition: transform var(--salmex-transition-fast);
723
- color: rgb(var(--salmex-text-secondary));
707
+ transition: transform var(--sx-transition-fast);
708
+ color: var(--sx-color-text-secondary);
724
709
  }
725
710
 
726
- .salmex-select-trigger-open .salmex-select-chevron {
711
+ .sx-select-trigger-open .sx-select-chevron {
727
712
  transform: rotate(180deg);
728
713
  }
729
714
 
730
715
  /* ========================================
731
- DROPDOWN PANEL Raised, bold shadow, fixed position
716
+ DROPDOWN PANEL -- Glass surface, shadow, blur
732
717
  ======================================== */
733
- .salmex-select-panel {
734
- z-index: var(--salmex-z-dropdown);
718
+ .sx-select-panel {
719
+ z-index: var(--sx-z-dropdown);
735
720
  overflow-y: auto;
736
721
  overflow-x: hidden;
737
- background: rgb(var(--salmex-bg-primary));
738
- border: 2px solid rgb(var(--salmex-border-dark));
739
- border-radius: var(--salmex-radius-md);
740
- box-shadow:
741
- inset 1px 1px 0 rgb(var(--salmex-button-highlight)),
742
- inset -1px -1px 0 rgb(var(--salmex-button-shadow)),
743
- 4px 4px 2px rgb(0 0 0 / 0.3);
722
+ background: var(--sx-color-surface-2);
723
+ border: 1px solid var(--sx-color-border-strong);
724
+ border-radius: var(--sx-radius-md);
725
+ box-shadow: var(--sx-shadow-lg);
726
+ backdrop-filter: var(--sx-glass-blur);
727
+ -webkit-backdrop-filter: var(--sx-glass-blur);
744
728
  outline: none;
745
- padding: var(--salmex-space-1) 0;
746
- font-family: var(--salmex-font-system);
747
- }
748
-
749
- :global([data-theme='dark']) .salmex-select-panel {
750
- box-shadow:
751
- inset 1px 1px 0 rgb(var(--salmex-button-highlight)),
752
- inset -1px -1px 0 rgb(var(--salmex-button-shadow)),
753
- 4px 4px 2px rgb(0 0 0 / 0.6);
729
+ padding: var(--sx-space-1) 0;
730
+ font-family: var(--sx-font-body);
754
731
  }
755
732
 
756
733
  /* ========================================
757
734
  OPTION
758
735
  ======================================== */
759
- .salmex-select-option {
736
+ .sx-select-option {
760
737
  display: flex;
761
738
  align-items: center;
762
- gap: var(--salmex-space-2);
763
- padding: var(--salmex-space-2) var(--salmex-space-4);
764
- font-size: var(--salmex-font-size-sm);
765
- font-weight: 600;
766
- color: rgb(var(--salmex-text-primary));
739
+ gap: var(--sx-space-2);
740
+ padding: var(--sx-space-2) var(--sx-space-4);
741
+ font-size: var(--sx-text-sm);
742
+ font-weight: 500;
743
+ color: var(--sx-color-text);
767
744
  cursor: pointer;
768
745
  user-select: none;
769
- transition: background var(--salmex-transition-fast);
746
+ transition: background var(--sx-transition-fast), color var(--sx-transition-fast);
770
747
  }
771
748
 
772
- .salmex-select-option-active {
773
- background: rgb(var(--salmex-electric-blue));
774
- color: rgb(var(--salmex-chalk-white));
749
+ .sx-select-option-active {
750
+ background: var(--sx-color-cyan-hover);
751
+ color: var(--sx-color-cyan);
775
752
  }
776
753
 
777
- :global([data-theme='dark']) .salmex-select-option-active {
778
- background: rgb(var(--salmex-primary-light));
779
- color: rgb(var(--salmex-midnight-black));
754
+ .sx-select-option-selected:not(.sx-select-option-active) {
755
+ background: var(--sx-color-cyan-subtle);
780
756
  }
781
757
 
782
- .salmex-select-option-selected:not(.salmex-select-option-active) {
783
- background: rgb(var(--salmex-electric-blue) / 0.1);
784
- }
785
-
786
- :global([data-theme='dark']) .salmex-select-option-selected:not(.salmex-select-option-active) {
787
- background: rgb(var(--salmex-primary-light) / 0.15);
788
- }
789
-
790
- .salmex-select-option-disabled {
758
+ .sx-select-option-disabled {
791
759
  opacity: 0.4;
792
760
  cursor: not-allowed;
793
761
  }
794
762
 
795
- .salmex-select-option-label {
763
+ .sx-select-option-label {
796
764
  flex: 1;
797
765
  overflow: hidden;
798
766
  text-overflow: ellipsis;
@@ -800,74 +768,64 @@ onMount(() => {
800
768
  }
801
769
 
802
770
  /* Checkmark for single select */
803
- .salmex-select-checkmark {
771
+ .sx-select-checkmark {
804
772
  flex-shrink: 0;
805
773
  display: flex;
806
774
  align-items: center;
807
- color: rgb(var(--salmex-electric-blue));
808
- }
809
-
810
- .salmex-select-option-active .salmex-select-checkmark {
811
- color: rgb(var(--salmex-chalk-white));
775
+ color: var(--sx-color-cyan);
812
776
  }
813
777
 
814
- :global([data-theme='dark']) .salmex-select-option-active .salmex-select-checkmark {
815
- color: rgb(var(--salmex-midnight-black));
778
+ .sx-select-option-active .sx-select-checkmark {
779
+ color: var(--sx-color-cyan);
816
780
  }
817
781
 
818
782
  /* Checkbox square for multi select */
819
- .salmex-select-check {
783
+ .sx-select-check {
820
784
  flex-shrink: 0;
821
785
  display: flex;
822
786
  align-items: center;
823
787
  justify-content: center;
824
788
  width: 16px;
825
789
  height: 16px;
826
- border: 1px solid rgb(var(--salmex-border-dark));
827
- border-radius: var(--salmex-radius-sm);
828
- background: rgb(var(--salmex-bg-primary));
829
- box-shadow:
830
- inset 1px 1px 0 rgb(var(--salmex-button-shadow)),
831
- inset -1px -1px 0 rgb(var(--salmex-button-highlight));
832
- }
833
-
834
- .salmex-select-option-active .salmex-select-check {
835
- border-color: rgb(var(--salmex-chalk-white));
790
+ border: 1px solid var(--sx-color-border-strong);
791
+ border-radius: var(--sx-radius-sm);
792
+ background: var(--sx-color-surface);
836
793
  }
837
794
 
838
- :global([data-theme='dark']) .salmex-select-option-active .salmex-select-check {
839
- border-color: rgb(var(--salmex-midnight-black));
795
+ .sx-select-option-active .sx-select-check {
796
+ border-color: var(--sx-color-cyan);
840
797
  }
841
798
 
842
799
  /* ========================================
843
800
  GROUP LABELS
844
801
  ======================================== */
845
- .salmex-select-group-label {
846
- padding: var(--salmex-space-2) var(--salmex-space-4) var(--salmex-space-1);
847
- font-size: var(--salmex-font-size-xs);
848
- font-weight: 700;
849
- letter-spacing: 0.4px;
850
- color: rgb(var(--salmex-text-secondary));
802
+ .sx-select-group-label {
803
+ padding: var(--sx-space-2) var(--sx-space-4) var(--sx-space-1);
804
+ font-size: var(--sx-text-xs);
805
+ font-weight: 600;
806
+ letter-spacing: 0.05em;
807
+ text-transform: uppercase;
808
+ color: var(--sx-color-text-disabled);
851
809
  user-select: none;
852
810
  }
853
811
 
854
812
  /* ========================================
855
- FOOTER Error / Hint
813
+ FOOTER -- Error / Hint
856
814
  ======================================== */
857
- .salmex-select-footer {
815
+ .sx-select-footer {
858
816
  min-height: 18px;
859
817
  }
860
818
 
861
- .salmex-select-error {
862
- font-size: var(--salmex-font-size-xs);
863
- font-weight: 600;
864
- color: rgb(var(--salmex-street-red));
819
+ .sx-select-error {
820
+ font-size: var(--sx-text-xs);
821
+ font-weight: 500;
822
+ color: var(--sx-color-red);
865
823
  margin: 0;
866
824
  }
867
825
 
868
- .salmex-select-hint {
869
- font-size: var(--salmex-font-size-xs);
870
- color: rgb(var(--salmex-text-secondary));
826
+ .sx-select-hint {
827
+ font-size: var(--sx-text-xs);
828
+ color: var(--sx-color-text-secondary);
871
829
  margin: 0;
872
830
  }
873
831
 
@@ -875,9 +833,9 @@ onMount(() => {
875
833
  REDUCED MOTION
876
834
  ======================================== */
877
835
  @media (prefers-reduced-motion: reduce) {
878
- .salmex-select-trigger,
879
- .salmex-select-option,
880
- .salmex-select-chevron {
836
+ .sx-select-trigger,
837
+ .sx-select-option,
838
+ .sx-select-chevron {
881
839
  transition: none;
882
840
  }
883
841
  }
@@ -47,7 +47,7 @@ interface Props {
47
47
  /**
48
48
  * Select
49
49
  *
50
- * Win2K × Basquiat — Dropdown select with sunken trigger field, raised panel,
50
+ * Neo-Brutalist Dark — Dropdown select with clean trigger field, glass-blur panel,
51
51
  * keyboard-first navigation, type-ahead search, option groups, and multi-select.
52
52
  *
53
53
  * Follows WAI-ARIA APG Select-Only Combobox pattern: DOM focus stays on