@marianmeres/stuic 2.66.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/README.md +292 -4
  2. package/dist/README.md +41 -18
  3. package/dist/actions/index.d.ts +1 -0
  4. package/dist/actions/index.js +1 -0
  5. package/dist/actions/popover/README.md +19 -0
  6. package/dist/actions/popover/index.css +6 -9
  7. package/dist/actions/popover/popover.svelte.js +2 -2
  8. package/dist/actions/tooltip/README.md +18 -0
  9. package/dist/actions/tooltip/index.css +5 -8
  10. package/dist/actions/tooltip/tooltip.svelte.js +1 -1
  11. package/dist/actions/typeahead.svelte.d.ts +53 -0
  12. package/dist/actions/typeahead.svelte.js +328 -0
  13. package/dist/base.css +17 -0
  14. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte +10 -10
  15. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte.d.ts +4 -3
  16. package/dist/components/AlertConfirmPrompt/Current.svelte +15 -18
  17. package/dist/components/AlertConfirmPrompt/Current.svelte.d.ts +4 -3
  18. package/dist/components/AlertConfirmPrompt/acp-icons.js +5 -4
  19. package/dist/components/AlertConfirmPrompt/index.css +66 -0
  20. package/dist/components/AssetsPreview/AssetsPreview.svelte +91 -73
  21. package/dist/components/AssetsPreview/index.css +61 -0
  22. package/dist/components/Avatar/Avatar.svelte +31 -18
  23. package/dist/components/Avatar/README.md +166 -0
  24. package/dist/components/Avatar/index.css +130 -0
  25. package/dist/components/Backdrop/Backdrop.svelte +7 -2
  26. package/dist/components/Backdrop/README.md +71 -6
  27. package/dist/components/Backdrop/index.css +31 -0
  28. package/dist/components/Button/Button.svelte +116 -124
  29. package/dist/components/Button/Button.svelte.d.ts +35 -24
  30. package/dist/components/Button/README.md +87 -21
  31. package/dist/components/Button/index.css +475 -9
  32. package/dist/components/Button/index.d.ts +1 -1
  33. package/dist/components/Button/index.js +1 -1
  34. package/dist/components/ButtonGroupRadio/ButtonGroupRadio.svelte +7 -39
  35. package/dist/components/ButtonGroupRadio/ButtonGroupRadio.svelte.d.ts +0 -1
  36. package/dist/components/ButtonGroupRadio/README.md +82 -4
  37. package/dist/components/ButtonGroupRadio/index.css +158 -14
  38. package/dist/components/Collapsible/Collapsible.svelte +7 -7
  39. package/dist/components/Collapsible/Collapsible.svelte.d.ts +2 -2
  40. package/dist/components/Collapsible/README.md +34 -2
  41. package/dist/components/Collapsible/index.css +40 -0
  42. package/dist/components/CommandMenu/CommandMenu.svelte +18 -26
  43. package/dist/components/CommandMenu/CommandMenu.svelte.d.ts +0 -1
  44. package/dist/components/CommandMenu/README.md +39 -0
  45. package/dist/components/CommandMenu/index.css +47 -2
  46. package/dist/components/DismissibleMessage/DismissibleMessage.svelte +53 -51
  47. package/dist/components/DismissibleMessage/DismissibleMessage.svelte.d.ts +6 -6
  48. package/dist/components/DismissibleMessage/README.md +93 -11
  49. package/dist/components/DismissibleMessage/index.css +128 -8
  50. package/dist/components/DismissibleMessage/index.d.ts +1 -1
  51. package/dist/components/DropdownMenu/DropdownMenu.svelte +14 -51
  52. package/dist/components/DropdownMenu/DropdownMenu.svelte.d.ts +6 -7
  53. package/dist/components/DropdownMenu/README.md +132 -0
  54. package/dist/components/DropdownMenu/index.css +258 -52
  55. package/dist/components/Input/FieldAssets.svelte +8 -5
  56. package/dist/components/Input/FieldCheckbox.svelte +7 -44
  57. package/dist/components/Input/FieldFile.svelte +1 -6
  58. package/dist/components/Input/FieldInput.svelte +9 -1
  59. package/dist/components/Input/FieldInput.svelte.d.ts +2 -0
  60. package/dist/components/Input/FieldOptions.svelte +42 -39
  61. package/dist/components/Input/FieldRadios.svelte +7 -16
  62. package/dist/components/Input/FieldSelect.svelte +1 -1
  63. package/dist/components/Input/FieldSwitch.svelte +1 -5
  64. package/dist/components/Input/FieldTextarea.svelte +1 -1
  65. package/dist/components/Input/README.md +194 -0
  66. package/dist/components/Input/_internal/FieldRadioInternal.svelte +2 -40
  67. package/dist/components/Input/_internal/InputWrap.svelte +8 -48
  68. package/dist/components/Input/index.css +524 -116
  69. package/dist/components/KbdShortcut/KbdShortcut.svelte +4 -12
  70. package/dist/components/KbdShortcut/README.md +34 -0
  71. package/dist/components/KbdShortcut/index.css +55 -0
  72. package/dist/components/ListItemButton/ListItemButton.svelte +37 -74
  73. package/dist/components/ListItemButton/ListItemButton.svelte.d.ts +1 -10
  74. package/dist/components/ListItemButton/README.md +100 -45
  75. package/dist/components/ListItemButton/index.css +173 -52
  76. package/dist/components/ListItemButton/index.d.ts +1 -1
  77. package/dist/components/ListItemButton/index.js +1 -1
  78. package/dist/components/Modal/Modal.svelte +1 -8
  79. package/dist/components/Modal/README.md +29 -0
  80. package/dist/components/Modal/index.css +38 -0
  81. package/dist/components/ModalDialog/ModalDialog.svelte +2 -21
  82. package/dist/components/ModalDialog/README.md +35 -0
  83. package/dist/components/ModalDialog/index.css +59 -0
  84. package/dist/components/Nav/Nav.svelte +732 -0
  85. package/dist/components/Nav/Nav.svelte.d.ts +110 -0
  86. package/dist/components/Nav/README.md +334 -0
  87. package/dist/components/Nav/index.css +318 -0
  88. package/dist/components/Nav/index.d.ts +1 -0
  89. package/dist/components/Nav/index.js +1 -0
  90. package/dist/components/Notifications/Notifications.svelte +44 -129
  91. package/dist/components/Notifications/Notifications.svelte.d.ts +9 -18
  92. package/dist/components/Notifications/README.md +186 -70
  93. package/dist/components/Notifications/index.css +212 -15
  94. package/dist/components/Notifications/notifications-stack.svelte.d.ts +4 -0
  95. package/dist/components/Notifications/notifications-stack.svelte.js +8 -0
  96. package/dist/components/Progress/Progress.svelte +4 -2
  97. package/dist/components/Progress/Progress.svelte.d.ts +1 -0
  98. package/dist/components/Progress/README.md +97 -11
  99. package/dist/components/Progress/_internal/Bar.svelte +4 -15
  100. package/dist/components/Progress/_internal/Bar.svelte.d.ts +1 -1
  101. package/dist/components/Progress/_internal/Circle.svelte +30 -2
  102. package/dist/components/Progress/_internal/Circle.svelte.d.ts +1 -0
  103. package/dist/components/Progress/index.css +50 -4
  104. package/dist/components/Skeleton/README.md +152 -0
  105. package/dist/components/Skeleton/Skeleton.svelte +9 -9
  106. package/dist/components/Skeleton/Skeleton.svelte.d.ts +0 -1
  107. package/dist/components/Skeleton/index.css +72 -45
  108. package/dist/components/Spinner/README.md +149 -37
  109. package/dist/components/Spinner/Spinner.svelte +14 -38
  110. package/dist/components/Spinner/Spinner.svelte.d.ts +2 -1
  111. package/dist/components/Spinner/SpinnerCircle.svelte +6 -34
  112. package/dist/components/Spinner/SpinnerCircle.svelte.d.ts +1 -0
  113. package/dist/components/Spinner/SpinnerCircleOscillate.svelte +10 -5
  114. package/dist/components/Spinner/SpinnerUnicode.svelte +3 -1
  115. package/dist/components/Spinner/SpinnerUnicode.svelte.d.ts +1 -0
  116. package/dist/components/Spinner/index.css +104 -0
  117. package/dist/components/Switch/README.md +45 -14
  118. package/dist/components/Switch/Switch.svelte +23 -48
  119. package/dist/components/Switch/Switch.svelte.d.ts +4 -2
  120. package/dist/components/Switch/index.css +121 -4
  121. package/dist/components/Switch/index.d.ts +1 -2
  122. package/dist/components/Switch/index.js +1 -2
  123. package/dist/components/TabbedMenu/README.md +37 -21
  124. package/dist/components/TabbedMenu/TabbedMenu.svelte +5 -46
  125. package/dist/components/TabbedMenu/TabbedMenu.svelte.d.ts +0 -1
  126. package/dist/components/TabbedMenu/index.css +84 -17
  127. package/dist/components/ThemePreview/README.md +289 -0
  128. package/dist/components/ThemePreview/ThemePreview.svelte +394 -0
  129. package/dist/components/ThemePreview/ThemePreview.svelte.d.ts +35 -0
  130. package/dist/components/ThemePreview/index.css +509 -0
  131. package/dist/components/ThemePreview/index.d.ts +1 -0
  132. package/dist/components/ThemePreview/index.js +1 -0
  133. package/dist/components/TwCheck/README.md +32 -13
  134. package/dist/components/TwCheck/TwCheck.svelte +11 -9
  135. package/dist/components/TwCheck/TwCheck.svelte.d.ts +0 -1
  136. package/dist/components/TwCheck/index.css +17 -2
  137. package/dist/components/TypeaheadInput/TypeaheadInput.svelte +20 -188
  138. package/dist/components/TypeaheadInput/TypeaheadInput.svelte.d.ts +4 -2
  139. package/dist/components/X/X.svelte +12 -5
  140. package/dist/components/X/X.svelte.d.ts +1 -0
  141. package/dist/icons/index.d.ts +1 -0
  142. package/dist/icons/index.js +1 -0
  143. package/dist/index.css +46 -26
  144. package/dist/index.d.ts +2 -0
  145. package/dist/index.js +2 -0
  146. package/dist/themes/blue-orange.css +217 -0
  147. package/dist/themes/blue-orange.d.ts +6 -0
  148. package/dist/themes/blue-orange.js +175 -0
  149. package/dist/themes/cyan-red.css +217 -0
  150. package/dist/themes/cyan-red.d.ts +6 -0
  151. package/dist/themes/cyan-red.js +175 -0
  152. package/dist/themes/cyan-slate.css +217 -0
  153. package/dist/themes/cyan-slate.d.ts +6 -0
  154. package/dist/themes/cyan-slate.js +175 -0
  155. package/dist/themes/emerald-pink.css +217 -0
  156. package/dist/themes/emerald-pink.d.ts +6 -0
  157. package/dist/themes/emerald-pink.js +175 -0
  158. package/dist/themes/fuchsia-emerald.css +217 -0
  159. package/dist/themes/fuchsia-emerald.d.ts +6 -0
  160. package/dist/themes/fuchsia-emerald.js +175 -0
  161. package/dist/themes/gray.css +217 -0
  162. package/dist/themes/gray.d.ts +6 -0
  163. package/dist/themes/gray.js +175 -0
  164. package/dist/themes/indigo-amber.css +217 -0
  165. package/dist/themes/indigo-amber.d.ts +6 -0
  166. package/dist/themes/indigo-amber.js +175 -0
  167. package/dist/themes/neutral.css +217 -0
  168. package/dist/themes/neutral.d.ts +6 -0
  169. package/dist/themes/neutral.js +175 -0
  170. package/dist/themes/pink-emerald.css +217 -0
  171. package/dist/themes/pink-emerald.d.ts +6 -0
  172. package/dist/themes/pink-emerald.js +175 -0
  173. package/dist/themes/purple-yellow.css +217 -0
  174. package/dist/themes/purple-yellow.d.ts +6 -0
  175. package/dist/themes/purple-yellow.js +175 -0
  176. package/dist/themes/rainbow.css +217 -0
  177. package/dist/themes/rainbow.d.ts +6 -0
  178. package/dist/themes/rainbow.js +180 -0
  179. package/dist/themes/red-blue.css +217 -0
  180. package/dist/themes/red-blue.d.ts +6 -0
  181. package/dist/themes/red-blue.js +175 -0
  182. package/dist/themes/red-cyan.css +217 -0
  183. package/dist/themes/red-cyan.d.ts +6 -0
  184. package/dist/themes/red-cyan.js +175 -0
  185. package/dist/themes/rose-teal.css +217 -0
  186. package/dist/themes/rose-teal.d.ts +6 -0
  187. package/dist/themes/rose-teal.js +175 -0
  188. package/dist/themes/sky-amber.css +217 -0
  189. package/dist/themes/sky-amber.d.ts +6 -0
  190. package/dist/themes/sky-amber.js +175 -0
  191. package/dist/themes/slate-cyan.css +217 -0
  192. package/dist/themes/slate-cyan.d.ts +6 -0
  193. package/dist/themes/slate-cyan.js +175 -0
  194. package/dist/themes/tailwind-color-pairs.md +31 -0
  195. package/dist/themes/teal-rose.css +217 -0
  196. package/dist/themes/teal-rose.d.ts +6 -0
  197. package/dist/themes/teal-rose.js +175 -0
  198. package/dist/themes/violet-lime.css +217 -0
  199. package/dist/themes/violet-lime.d.ts +6 -0
  200. package/dist/themes/violet-lime.js +175 -0
  201. package/dist/utils/design-tokens.d.ts +43 -0
  202. package/dist/utils/design-tokens.js +127 -0
  203. package/dist/utils/index.d.ts +1 -0
  204. package/dist/utils/index.js +1 -0
  205. package/dist/utils/storage-abstraction.js +1 -1
  206. package/package.json +14 -11
  207. package/dist/components/Switch/SwitchButton.svelte +0 -135
  208. package/dist/components/Switch/SwitchButton.svelte.d.ts +0 -21
@@ -147,13 +147,12 @@ export interface Props extends Omit<HTMLButtonAttributes, "children"> {
147
147
  /** Optional, used only when css positioning not supported (iPhone)*/
148
148
  noScrollLock?: boolean;
149
149
  }
150
- export declare const DROPDOWN_MENU_BASE_CLASSES = "stuic-dropdown-menu relative inline-block";
151
- export declare const DROPDOWN_MENU_TRIGGER_CLASSES = "\n\t\tinline-flex items-center justify-center gap-2\n\t\tpx-3 py-2\n\t\trounded-md border\n\t\tbg-white dark:bg-neutral-800\n\t\ttext-neutral-900 dark:text-neutral-100\n\t\tborder-neutral-200 dark:border-neutral-700\n\t\thover:brightness-95 dark:hover:brightness-110\n\t\tcursor-pointer\n\t\t";
152
- export declare const DROPDOWN_MENU_DROPDOWN_CLASSES = "\n\t\tstuic-dropdown-menu-dropdown\n\t\tbg-white dark:bg-neutral-800\n\t\ttext-neutral-900 dark:text-neutral-100\n\t\tborder border-neutral-200 dark:border-neutral-700\n\t\trounded-md shadow-sm\n\t\tp-1\n\t\toverflow-y-auto\n\t\tz-50\n\t\tmin-w-48\n\t";
153
- export declare const DROPDOWN_MENU_DIVIDER_CLASSES = "\n\t\th-px my-1\n\t\tbg-neutral-200 dark:bg-neutral-700\n\t";
154
- export declare const DROPDOWN_MENU_HEADER_CLASSES = "\n\t\tpx-2 py-1.5\n\t\ttext-xs font-semibold uppercase tracking-wide\n\t\ttext-neutral-500 dark:text-neutral-400\n\t\tselect-none\n\t";
155
- export declare const DROPDOWN_MENU_BACKDROP_CLASSES = "\n\t\tstuic-dropdown-menu-backdrop\n\t\tfixed inset-0 bg-black/25\n\t\tz-40\n\t";
156
- import "./index.css";
150
+ export declare const DROPDOWN_MENU_BASE_CLASSES = "stuic-dropdown-menu";
151
+ export declare const DROPDOWN_MENU_TRIGGER_CLASSES = "stuic-dropdown-menu-trigger";
152
+ export declare const DROPDOWN_MENU_DROPDOWN_CLASSES = "stuic-dropdown-menu-dropdown";
153
+ export declare const DROPDOWN_MENU_DIVIDER_CLASSES = "stuic-dropdown-menu-divider";
154
+ export declare const DROPDOWN_MENU_HEADER_CLASSES = "stuic-dropdown-menu-header";
155
+ export declare const DROPDOWN_MENU_BACKDROP_CLASSES = "stuic-dropdown-menu-backdrop";
157
156
  declare const DropdownMenu: import("svelte").Component<Props, {}, "isOpen" | "triggerEl" | "dropdownEl">;
158
157
  type DropdownMenu = ReturnType<typeof DropdownMenu>;
159
158
  export default DropdownMenu;
@@ -313,3 +313,135 @@ interface DropdownMenuExpandableItem {
313
313
  - **Reduced Motion**: Respects user's reduced motion preference
314
314
  - **Click Outside**: Automatically closes when clicking outside
315
315
  - **Focus Management**: Returns focus to trigger on close
316
+
317
+ ## CSS Variables
318
+
319
+ Override these tokens globally in `:root` or locally via inline `style`:
320
+
321
+ ### Structure Tokens
322
+
323
+ | Variable | Default | Description |
324
+ |----------|---------|-------------|
325
+ | `--stuic-dropdown-menu-radius` | `--radius-md` | Border radius for trigger and dropdown |
326
+ | `--stuic-dropdown-menu-padding` | `--spacing * 1` | Inner padding of dropdown container |
327
+ | `--stuic-dropdown-menu-gap` | `--spacing * 0.5` | Gap between trigger content |
328
+ | `--stuic-dropdown-menu-min-width` | `12rem` | Minimum width of dropdown |
329
+ | `--stuic-dropdown-menu-transition` | `150ms` | Transition duration |
330
+
331
+ ### Container Colors
332
+
333
+ | Variable | Default | Description |
334
+ |----------|---------|-------------|
335
+ | `--stuic-dropdown-menu-bg` | `--stuic-color-surface` | Dropdown background color |
336
+ | `--stuic-dropdown-menu-text` | `--stuic-color-surface-foreground` | Dropdown text color |
337
+ | `--stuic-dropdown-menu-border` | `--stuic-color-border` | Dropdown border color |
338
+ | `--stuic-dropdown-menu-shadow` | subtle shadow | Dropdown shadow |
339
+
340
+ ### Trigger Button
341
+
342
+ | Variable | Default | Description |
343
+ |----------|---------|-------------|
344
+ | `--stuic-dropdown-menu-trigger-bg` | `--stuic-color-surface` | Trigger background |
345
+ | `--stuic-dropdown-menu-trigger-bg-hover` | `--stuic-color-surface-hover` | Trigger hover background |
346
+ | `--stuic-dropdown-menu-trigger-bg-active` | `--stuic-color-surface-active` | Trigger active background |
347
+ | `--stuic-dropdown-menu-trigger-text` | `--stuic-color-surface-foreground` | Trigger text color |
348
+ | `--stuic-dropdown-menu-trigger-text-hover` | `--stuic-color-surface-foreground-hover` | Trigger hover text color |
349
+ | `--stuic-dropdown-menu-trigger-text-active` | `--stuic-color-surface-foreground-active` | Trigger active text color |
350
+ | `--stuic-dropdown-menu-trigger-border` | `--stuic-color-border` | Trigger border color |
351
+ | `--stuic-dropdown-menu-trigger-border-hover` | `--stuic-color-border-hover` | Trigger hover border |
352
+ | `--stuic-dropdown-menu-trigger-border-active` | `--stuic-color-border-active` | Trigger active border |
353
+ | `--stuic-dropdown-menu-trigger-padding-x` | `--spacing * 3` | Trigger horizontal padding |
354
+ | `--stuic-dropdown-menu-trigger-padding-y` | `--spacing * 2` | Trigger vertical padding |
355
+
356
+ ### Focus Ring
357
+
358
+ | Variable | Default | Description |
359
+ |----------|---------|-------------|
360
+ | `--stuic-dropdown-menu-ring-width` | `3px` | Focus ring width |
361
+ | `--stuic-dropdown-menu-ring-offset` | `0px` | Focus ring offset |
362
+ | `--stuic-dropdown-menu-ring-color` | `--stuic-color-ring` | Focus ring color |
363
+
364
+ ### Divider
365
+
366
+ | Variable | Default | Description |
367
+ |----------|---------|-------------|
368
+ | `--stuic-dropdown-menu-divider-bg` | `--stuic-color-border` | Divider color |
369
+ | `--stuic-dropdown-menu-divider-height` | `1px` | Divider height |
370
+ | `--stuic-dropdown-menu-divider-margin-y` | `--spacing * 1` | Divider vertical margin |
371
+
372
+ ### Header (Section Label)
373
+
374
+ | Variable | Default | Description |
375
+ |----------|---------|-------------|
376
+ | `--stuic-dropdown-menu-header-text` | `--stuic-color-muted-foreground` | Header text color |
377
+ | `--stuic-dropdown-menu-header-font-size` | `--text-xs` | Header font size |
378
+ | `--stuic-dropdown-menu-header-font-weight` | `--font-weight-semibold` | Header font weight |
379
+ | `--stuic-dropdown-menu-header-padding-x` | `--spacing * 2` | Header horizontal padding |
380
+ | `--stuic-dropdown-menu-header-padding-y` | `--spacing * 1.5` | Header vertical padding |
381
+ | `--stuic-dropdown-menu-header-letter-spacing` | `0.05em` | Header letter spacing |
382
+ | `--stuic-dropdown-menu-header-text-transform` | `uppercase` | Header text transform |
383
+
384
+ ### Backdrop (Fallback Mode)
385
+
386
+ | Variable | Default | Description |
387
+ |----------|---------|-------------|
388
+ | `--stuic-dropdown-menu-backdrop-bg` | `rgb(0 0 0 / 0.25)` | Backdrop color |
389
+ | `--stuic-dropdown-menu-backdrop-z-index` | `40` | Backdrop z-index |
390
+
391
+ ### Close Button (Fallback Mode)
392
+
393
+ | Variable | Default | Description |
394
+ |----------|---------|-------------|
395
+ | `--stuic-dropdown-menu-close-bg` | `--stuic-color-foreground` | Close button background |
396
+ | `--stuic-dropdown-menu-close-text` | `--stuic-color-background` | Close button text color |
397
+ | `--stuic-dropdown-menu-close-opacity` | `0.6` | Close button opacity |
398
+ | `--stuic-dropdown-menu-close-opacity-hover` | `1` | Close button hover opacity |
399
+
400
+ ### Expandable Section
401
+
402
+ | Variable | Default | Description |
403
+ |----------|---------|-------------|
404
+ | `--stuic-dropdown-menu-expandable-indent` | `--spacing * 4` | Expandable content indent |
405
+
406
+ ## Customization Examples
407
+
408
+ ### Global Override
409
+
410
+ ```css
411
+ /* Custom theme: pill-shaped dropdowns with more padding */
412
+ :root {
413
+ --stuic-dropdown-menu-radius: 9999px;
414
+ --stuic-dropdown-menu-padding: 1rem;
415
+ --stuic-dropdown-menu-trigger-bg: var(--color-blue-500);
416
+ --stuic-dropdown-menu-trigger-text: white;
417
+ }
418
+ ```
419
+
420
+ ### Local Override
421
+
422
+ ```svelte
423
+ <DropdownMenu
424
+ style="--stuic-dropdown-menu-radius: 0; --stuic-dropdown-menu-shadow: none;"
425
+ items={items}
426
+ >
427
+ Sharp Corners, No Shadow
428
+ </DropdownMenu>
429
+ ```
430
+
431
+ ### Using Class Props
432
+
433
+ Class props override default styling with Tailwind classes:
434
+
435
+ ```svelte
436
+ <!-- Blue-themed dropdown -->
437
+ <DropdownMenu
438
+ items={items}
439
+ classTrigger="bg-blue-500 text-white hover:bg-blue-600 border-blue-600"
440
+ classDropdown="bg-blue-50 dark:bg-blue-950 border-blue-200"
441
+ classItem="hover:bg-blue-100 dark:hover:bg-blue-900"
442
+ >
443
+ Blue Theme
444
+ </DropdownMenu>
445
+ ```
446
+
447
+ Class props always win over CSS variables due to Tailwind's specificity.
@@ -1,63 +1,269 @@
1
- /* Base dropdown styles */
2
- .stuic-dropdown-menu-dropdown {
3
- scrollbar-width: thin;
4
- }
1
+ /* =============================================================================
2
+ DROPDOWN MENU COMPONENT TOKENS
3
+ Override globally: :root { --stuic-dropdown-menu-radius: 0; }
4
+ Override locally: <DropdownMenu style="--stuic-dropdown-menu-radius: 9999px;">
5
+ ============================================================================= */
5
6
 
6
- /* Override ListItemButton defaults for dropdown context */
7
- .stuic-dropdown-menu-dropdown .stuic-list-item-button {
8
- --color-lib-bg: transparent;
9
- --color-lib-bg-dark: transparent;
10
- --color-lib-border: transparent;
11
- --color-lib-border-dark: transparent;
12
- }
7
+ :root {
8
+ /* Structure tokens */
9
+ --stuic-dropdown-menu-radius: var(--radius-md);
10
+ --stuic-dropdown-menu-padding: calc(var(--spacing) * 1);
11
+ --stuic-dropdown-menu-gap: calc(var(--spacing) * 0.5);
12
+ --stuic-dropdown-menu-min-width: 12rem;
13
+ --stuic-dropdown-menu-transition: 150ms;
13
14
 
14
- @position-try --pop-top {
15
- position-area: top; /* above, centered */
16
- }
17
- @position-try --pop-top-span-right {
18
- position-area: top span-right; /* above, aligned to anchor's left edge */
19
- }
20
- @position-try --pop-top-span-left {
21
- position-area: top span-left; /* above, aligned to anchor's right edge */
22
- }
23
- @position-try --pop-bottom {
24
- position-area: bottom; /* below, centered */
25
- }
26
- @position-try --pop-bottom-span-right {
27
- position-area: bottom span-right;
28
- }
29
- @position-try --pop-bottom-span-left {
30
- position-area: bottom span-left;
31
- }
32
- @position-try --pop-left {
33
- position-area: left;
34
- }
35
- @position-try --pop-right {
36
- position-area: right;
15
+ /* Dropdown container colors */
16
+ --stuic-dropdown-menu-bg: var(--stuic-color-surface);
17
+ --stuic-dropdown-menu-text: var(--stuic-color-surface-foreground);
18
+ --stuic-dropdown-menu-border: var(--stuic-color-border);
19
+ --stuic-dropdown-menu-shadow: var(--shadow-lg);
20
+
21
+ /* Trigger button colors */
22
+ --stuic-dropdown-menu-trigger-bg: var(--stuic-color-surface);
23
+ --stuic-dropdown-menu-trigger-bg-hover: var(--stuic-color-surface-hover);
24
+ --stuic-dropdown-menu-trigger-bg-active: var(--stuic-color-surface-active);
25
+ --stuic-dropdown-menu-trigger-text: var(--stuic-color-surface-foreground);
26
+ --stuic-dropdown-menu-trigger-text-hover: var(--stuic-color-surface-foreground-hover);
27
+ --stuic-dropdown-menu-trigger-text-active: var(--stuic-color-surface-foreground-active);
28
+ --stuic-dropdown-menu-trigger-border: var(--stuic-color-border);
29
+ --stuic-dropdown-menu-trigger-border-hover: var(--stuic-color-border-hover);
30
+ --stuic-dropdown-menu-trigger-border-active: var(--stuic-color-border-active);
31
+
32
+ /* Trigger sizing */
33
+ --stuic-dropdown-menu-trigger-padding-x: calc(var(--spacing) * 3);
34
+ --stuic-dropdown-menu-trigger-padding-y: calc(var(--spacing) * 2);
35
+
36
+ /* Focus ring */
37
+ --stuic-dropdown-menu-ring-width: 3px;
38
+ --stuic-dropdown-menu-ring-offset: 0px;
39
+ --stuic-dropdown-menu-ring-color: var(--stuic-color-ring);
40
+
41
+ /* Divider */
42
+ --stuic-dropdown-menu-divider-bg: var(--stuic-color-border);
43
+ --stuic-dropdown-menu-divider-height: 1px;
44
+ --stuic-dropdown-menu-divider-margin-y: calc(var(--spacing) * 1);
45
+
46
+ /* Header (section label) */
47
+ --stuic-dropdown-menu-header-text: var(--stuic-color-muted-foreground);
48
+ --stuic-dropdown-menu-header-font-size: var(--text-xs);
49
+ --stuic-dropdown-menu-header-font-weight: var(--font-weight-semibold);
50
+ --stuic-dropdown-menu-header-padding-x: calc(var(--spacing) * 2);
51
+ --stuic-dropdown-menu-header-padding-y: calc(var(--spacing) * 1.5);
52
+ --stuic-dropdown-menu-header-letter-spacing: 0.05em;
53
+ --stuic-dropdown-menu-header-text-transform: uppercase;
54
+
55
+ /* Backdrop (fallback mode) */
56
+ --stuic-dropdown-menu-backdrop-bg: rgb(0 0 0 / 0.25);
57
+ --stuic-dropdown-menu-backdrop-z-index: 40;
58
+
59
+ /* Close button (fallback mode) */
60
+ --stuic-dropdown-menu-close-bg: var(--stuic-color-foreground);
61
+ --stuic-dropdown-menu-close-text: var(--stuic-color-background);
62
+ --stuic-dropdown-menu-close-opacity: 0.6;
63
+ --stuic-dropdown-menu-close-opacity-hover: 1;
64
+
65
+ /* Expandable section indent */
66
+ --stuic-dropdown-menu-expandable-indent: calc(var(--spacing) * 4);
37
67
  }
38
68
 
39
- /* CSS Anchor Positioning supported mode - flip only when viewport overflow */
40
- @supports (anchor-name: --anchor) {
69
+ @layer components {
70
+ /* =============================================================================
71
+ BASE STYLES
72
+ ============================================================================= */
73
+
74
+ .stuic-dropdown-menu {
75
+ position: relative;
76
+ display: inline-block;
77
+ }
78
+
79
+ /* =============================================================================
80
+ TRIGGER BUTTON
81
+ ============================================================================= */
82
+
83
+ .stuic-dropdown-menu-trigger {
84
+ /* Layout */
85
+ display: inline-flex;
86
+ align-items: center;
87
+ justify-content: center;
88
+ gap: var(--stuic-dropdown-menu-gap);
89
+
90
+ /* Sizing */
91
+ padding: var(--stuic-dropdown-menu-trigger-padding-y)
92
+ var(--stuic-dropdown-menu-trigger-padding-x);
93
+
94
+ /* Box model */
95
+ border-width: 1px;
96
+ border-style: solid;
97
+ border-radius: var(--stuic-dropdown-menu-radius);
98
+
99
+ /* Colors */
100
+ background: var(--stuic-dropdown-menu-trigger-bg);
101
+ color: var(--stuic-dropdown-menu-trigger-text);
102
+ border-color: var(--stuic-dropdown-menu-trigger-border);
103
+
104
+ /* Interaction */
105
+ cursor: pointer;
106
+ user-select: none;
107
+ -webkit-tap-highlight-color: transparent;
108
+ touch-action: manipulation;
109
+ transition:
110
+ background var(--stuic-dropdown-menu-transition),
111
+ color var(--stuic-dropdown-menu-transition),
112
+ border-color var(--stuic-dropdown-menu-transition);
113
+ }
114
+
115
+ .stuic-dropdown-menu-trigger:hover:not(:disabled) {
116
+ background: var(--stuic-dropdown-menu-trigger-bg-hover);
117
+ color: var(--stuic-dropdown-menu-trigger-text-hover);
118
+ border-color: var(--stuic-dropdown-menu-trigger-border-hover);
119
+ }
120
+
121
+ .stuic-dropdown-menu-trigger:active:not(:disabled) {
122
+ background: var(--stuic-dropdown-menu-trigger-bg-active);
123
+ color: var(--stuic-dropdown-menu-trigger-text-active);
124
+ border-color: var(--stuic-dropdown-menu-trigger-border-active);
125
+ }
126
+
127
+ .stuic-dropdown-menu-trigger:focus-visible {
128
+ outline: var(--stuic-dropdown-menu-ring-width) solid
129
+ var(--stuic-dropdown-menu-ring-color);
130
+ outline-offset: var(--stuic-dropdown-menu-ring-offset);
131
+ }
132
+
133
+ /* =============================================================================
134
+ DROPDOWN CONTAINER
135
+ ============================================================================= */
136
+
41
137
  .stuic-dropdown-menu-dropdown {
42
- /* position-try-fallbacks: flip-block, flip-inline; */
138
+ /* Colors */
139
+ background: var(--stuic-dropdown-menu-bg);
140
+ color: var(--stuic-dropdown-menu-text);
141
+ border: 1px solid var(--stuic-dropdown-menu-border);
142
+ box-shadow: var(--stuic-dropdown-menu-shadow);
43
143
 
44
- /* position-area is set via inline style based on position param */
144
+ /* Box model */
145
+ border-radius: var(--stuic-dropdown-menu-radius);
146
+ padding: var(--stuic-dropdown-menu-padding);
45
147
 
46
- /* fallbacks ensure popover stays within viewport */
47
- /* order: try other bottom positions first, then top, then left/right */
48
- position-try-fallbacks:
49
- flip-inline, --pop-bottom-span-right, --pop-bottom-span-left, --pop-bottom,
50
- flip-block, --pop-top-span-right, --pop-top-span-left, --pop-top, --pop-left,
51
- --pop-right;
148
+ /* Layout */
149
+ min-width: var(--stuic-dropdown-menu-min-width);
150
+ overflow-y: auto;
151
+ scrollbar-width: thin;
152
+
153
+ /* Stacking */
154
+ z-index: 50;
52
155
  }
53
- }
54
156
 
55
- /* Expandable section animation handled by Svelte slide transition */
56
- .stuic-dropdown-menu-expandable-content {
57
- overflow: hidden;
58
- }
157
+ /* =============================================================================
158
+ DIVIDER
159
+ ============================================================================= */
160
+
161
+ .stuic-dropdown-menu-divider {
162
+ height: var(--stuic-dropdown-menu-divider-height);
163
+ margin: var(--stuic-dropdown-menu-divider-margin-y) 0;
164
+ background: var(--stuic-dropdown-menu-divider-bg);
165
+ }
166
+
167
+ /* =============================================================================
168
+ HEADER (Section Label)
169
+ ============================================================================= */
170
+
171
+ .stuic-dropdown-menu-header {
172
+ padding: var(--stuic-dropdown-menu-header-padding-y)
173
+ var(--stuic-dropdown-menu-header-padding-x);
174
+ font-size: var(--stuic-dropdown-menu-header-font-size);
175
+ font-weight: var(--stuic-dropdown-menu-header-font-weight);
176
+ letter-spacing: var(--stuic-dropdown-menu-header-letter-spacing);
177
+ text-transform: var(--stuic-dropdown-menu-header-text-transform);
178
+ color: var(--stuic-dropdown-menu-header-text);
179
+ user-select: none;
180
+ }
181
+
182
+ /* =============================================================================
183
+ BACKDROP (Fallback Mode)
184
+ ============================================================================= */
185
+
186
+ .stuic-dropdown-menu-backdrop {
187
+ position: fixed;
188
+ inset: 0;
189
+ background: var(--stuic-dropdown-menu-backdrop-bg);
190
+ z-index: var(--stuic-dropdown-menu-backdrop-z-index);
191
+ transition-property: opacity;
192
+ }
193
+
194
+ /* =============================================================================
195
+ CLOSE BUTTON (Fallback Mode)
196
+ ============================================================================= */
197
+
198
+ .stuic-dropdown-menu-close {
199
+ background: var(--stuic-dropdown-menu-close-bg);
200
+ color: var(--stuic-dropdown-menu-close-text);
201
+ opacity: var(--stuic-dropdown-menu-close-opacity);
202
+ border-radius: var(--stuic-dropdown-menu-radius);
203
+ padding: calc(var(--spacing) * 2);
204
+ cursor: pointer;
205
+ line-height: 1;
206
+ transition: opacity var(--stuic-dropdown-menu-transition);
207
+ }
208
+
209
+ .stuic-dropdown-menu-close:hover {
210
+ opacity: var(--stuic-dropdown-menu-close-opacity-hover);
211
+ }
212
+
213
+ /* =============================================================================
214
+ EXPANDABLE SECTION
215
+ ============================================================================= */
59
216
 
60
- /* Backdrop for fallback mode */
61
- .stuic-dropdown-menu-backdrop {
62
- transition-property: opacity;
217
+ .stuic-dropdown-menu-expandable-content {
218
+ padding-left: var(--stuic-dropdown-menu-expandable-indent);
219
+ overflow: hidden;
220
+ }
221
+
222
+ /* =============================================================================
223
+ LIST ITEM BUTTON OVERRIDES FOR DROPDOWN CONTEXT
224
+ Reset default ListItemButton background to transparent within dropdown.
225
+ ============================================================================= */
226
+
227
+ .stuic-dropdown-menu-dropdown .stuic-list-item-button {
228
+ --stuic-list-item-button-bg: transparent;
229
+ --stuic-list-item-button-border: transparent;
230
+ }
231
+
232
+ /* =============================================================================
233
+ CSS ANCHOR POSITIONING (when supported)
234
+ ============================================================================= */
235
+
236
+ @position-try --pop-top {
237
+ position-area: top;
238
+ }
239
+ @position-try --pop-top-span-right {
240
+ position-area: top span-right;
241
+ }
242
+ @position-try --pop-top-span-left {
243
+ position-area: top span-left;
244
+ }
245
+ @position-try --pop-bottom {
246
+ position-area: bottom;
247
+ }
248
+ @position-try --pop-bottom-span-right {
249
+ position-area: bottom span-right;
250
+ }
251
+ @position-try --pop-bottom-span-left {
252
+ position-area: bottom span-left;
253
+ }
254
+ @position-try --pop-left {
255
+ position-area: left;
256
+ }
257
+ @position-try --pop-right {
258
+ position-area: right;
259
+ }
260
+
261
+ @supports (anchor-name: --anchor) {
262
+ .stuic-dropdown-menu-dropdown {
263
+ position-try-fallbacks:
264
+ flip-inline, --pop-bottom-span-right, --pop-bottom-span-left, --pop-bottom,
265
+ flip-block, --pop-top-span-right, --pop-top-span-left, --pop-top, --pop-left,
266
+ --pop-right;
267
+ }
268
+ }
63
269
  }
@@ -37,6 +37,7 @@
37
37
  import SpinnerCircleOscillate from "../Spinner/SpinnerCircleOscillate.svelte";
38
38
  import { isTHCNotEmpty, type THC } from "../Thc/Thc.svelte";
39
39
  import InputWrap from "./_internal/InputWrap.svelte";
40
+ import Button from "../Button/Button.svelte";
40
41
 
41
42
  const clog = createClog("FieldAssets");
42
43
 
@@ -324,7 +325,6 @@
324
325
  clog.warn(`${e}`);
325
326
  }
326
327
  });
327
-
328
328
  </script>
329
329
 
330
330
  {#snippet default_render()}
@@ -386,17 +386,20 @@
386
386
  </button>
387
387
  </div>
388
388
  {/each}
389
- <button
389
+ <Button
390
390
  type="button"
391
391
  onclick={(e) => {
392
392
  e.preventDefault();
393
393
  e.stopPropagation();
394
394
  inputEl.click();
395
395
  }}
396
- class={[objectSize, " grid place-content-center group", classControls]}
396
+ class={["m-4", classControls].join(" ")}
397
+ roundedFull
398
+ aspect1
399
+ variant="ghost"
397
400
  >
398
- {@html iconAdd({ size: 32, class: "opacity-75 group-hover:opacity-100" })}
399
- </button>
401
+ {@html iconAdd({ size: 24 })}
402
+ </Button>
400
403
  </div>
401
404
  {/if}
402
405
  {/snippet}
@@ -70,23 +70,7 @@
70
70
 
71
71
  // $inspect(33333, invalid, validation);
72
72
 
73
- //
74
- let _classCommon = $derived(
75
- [invalid && "invalid", disabled && "disabled", required && "required", renderSize]
76
- .filter(Boolean)
77
- .join(" ")
78
- );
79
73
 
80
- const _preset = {
81
- labelBox: {
82
- label: {
83
- size: {
84
- sm: "text-sm mt-0.5",
85
- lg: "font-bold",
86
- } as any,
87
- },
88
- },
89
- };
90
74
  </script>
91
75
 
92
76
  {#snippet snippetOrThc({ id, value }: { id: string; value?: SnippetWithId | THC })}
@@ -99,17 +83,18 @@
99
83
 
100
84
  <label
101
85
  class={twMerge(
102
- `stuic-checkbox`,
103
- _classCommon,
86
+ "stuic-checkbox",
104
87
  "flex items-start mb-4 text-base",
88
+ invalid && "invalid",
89
+ disabled && "disabled",
105
90
  classProp
106
91
  )}
92
+ data-size={renderSize}
107
93
  {style}
108
94
  >
109
95
  <div
110
96
  class={twMerge(
111
97
  "input-box",
112
- _classCommon,
113
98
  "flex h-6 items-center ml-1",
114
99
  classInputBox
115
100
  )}
@@ -126,40 +111,20 @@
126
111
  ...(typeof validate === "boolean" ? {} : validate),
127
112
  setValidationResult,
128
113
  })}
129
- class={twMerge(
130
- _classCommon,
131
- `size-5 rounded
132
- bg-neutral-100
133
- border-neutral-300
134
- text-input-accent dark:text-input-accent-dark
135
- cursor-pointer
136
-
137
- checked:border-input-accent checked:bg-input-accent
138
- checked:dark:border-input-accent-dark checked:dark:bg-input-accent-dark
139
-
140
- focus:border-input-accent
141
- focus:ring-4
142
- focus:ring-offset-0
143
- focus:ring-input-accent/20 focus:dark:ring-input-accent-dark/20
144
-
145
- disabled:cursor-not-allowed`,
146
- classInput
147
- )}
114
+ class={twMerge(classInput)}
148
115
  {required}
149
116
  {disabled}
150
117
  {...rest}
151
118
  />
152
119
  </div>
153
- <div class={twMerge("label-box", _classCommon, "ml-3 w-full", classLabelBox)}>
120
+ <div class={twMerge("label-box", "ml-3 w-full", classLabelBox)}>
154
121
  {#if label}
155
122
  <div
156
123
  class={twMerge(
157
124
  "label",
158
- _classCommon,
159
125
  "block w-full cursor-pointer",
160
126
  disabled && "cursor-not-allowed",
161
127
  required && "after:content-['*'] after:opacity-40 after:pl-1",
162
- _preset.labelBox.label.size[renderSize],
163
128
  classLabel
164
129
  )}
165
130
  >
@@ -175,8 +140,7 @@
175
140
  transition:slide={{ duration: 150 }}
176
141
  class={twMerge(
177
142
  "validation-box",
178
- _classCommon,
179
- "text-sm text-input-accent-invalid dark:text-input-accent-invalid-dark tracking-tight",
143
+ "text-sm tracking-tight",
180
144
  classValidationBox
181
145
  )}
182
146
  >
@@ -187,7 +151,6 @@
187
151
  <Collapsible
188
152
  class={twMerge(
189
153
  "desc-box",
190
- _classCommon,
191
154
  "text-sm opacity-50 cursor-pointer font-normal",
192
155
  disabled && "cursor-not-allowed",
193
156
  classDescBox
@@ -126,12 +126,7 @@
126
126
  bind:this={input}
127
127
  {id}
128
128
  class={twMerge(
129
- "form-input",
130
- "block border-0 w-full",
131
- "file:rounded file:border-0 file:mr-4 file:bg-neutral-200",
132
- "file:px-2 file:cursor-pointer",
133
- "focus-visible:ring-0 focus:ring-0 focus:leading-0",
134
- renderSize,
129
+ "block w-full",
135
130
  classInput
136
131
  )}
137
132
  use:highlightDragover={() => ({ classes: ["outline-dashed"] })}