@selvajs/ui 6.6.0-beta.15 → 6.6.0-beta.16

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 (204) hide show
  1. package/README.md +0 -3
  2. package/dist/components/compute/AppLayout.svelte +5 -3
  3. package/dist/components/compute/CollapsedPanelStrip.svelte +1 -1
  4. package/dist/components/compute/ParameterPresetManager.svelte +1 -1
  5. package/dist/components/compute/SolveMessages.svelte +2 -2
  6. package/dist/components/layout/FooterItemRenderer.svelte +1 -1
  7. package/dist/components/layout/PageFooter.svelte +2 -2
  8. package/dist/components/layout/PageHeader.svelte +1 -1
  9. package/dist/components/layout/SideNav.svelte +3 -3
  10. package/dist/components/layout/SubNav.svelte +2 -2
  11. package/dist/components/preview/ChartOutput.svelte +3 -3
  12. package/dist/components/preview/Group.svelte +7 -7
  13. package/dist/components/preview/ImageOutput.svelte +6 -6
  14. package/dist/components/preview/InputControl.svelte +1 -0
  15. package/dist/components/preview/OutputDisplay.svelte +8 -6
  16. package/dist/components/preview/TabBar.svelte +6 -4
  17. package/dist/components/preview/TabBar.svelte.d.ts +2 -0
  18. package/dist/components/preview/TabContent.svelte +1 -1
  19. package/dist/components/preview/TabLayout.svelte +3 -4
  20. package/dist/components/preview/inputs/ChecklistInput.svelte +3 -3
  21. package/dist/components/preview/inputs/ColorInput.svelte +356 -14
  22. package/dist/components/preview/inputs/ColorInput.svelte.d.ts +1 -0
  23. package/dist/components/preview/inputs/FileInput.svelte +3 -3
  24. package/dist/components/preview/inputs/SegmentedInput.svelte +2 -1
  25. package/dist/components/preview/inputs/TileInput.svelte +1 -1
  26. package/dist/components/primitives/CalculateButton.svelte +2 -2
  27. package/dist/components/primitives/Callout.svelte +7 -5
  28. package/dist/components/primitives/Callout.svelte.d.ts +4 -4
  29. package/dist/components/primitives/DataTable.svelte +1 -1
  30. package/dist/components/primitives/ImageUploadField.svelte +1 -1
  31. package/dist/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
  32. package/dist/components/primitives/badge/badge.svelte +2 -2
  33. package/dist/components/primitives/badge/badge.svelte.d.ts +6 -6
  34. package/dist/components/primitives/button/button.svelte +6 -7
  35. package/dist/components/primitives/button/button.svelte.d.ts +18 -18
  36. package/dist/components/primitives/card/card.svelte +1 -1
  37. package/dist/components/primitives/card/card.svelte.d.ts +1 -1
  38. package/dist/components/primitives/checkbox/checkbox.svelte +1 -1
  39. package/dist/components/primitives/command/command-input.svelte +1 -1
  40. package/dist/components/primitives/command/command-item.svelte +1 -1
  41. package/dist/components/primitives/command/command-link-item.svelte +1 -1
  42. package/dist/components/primitives/command/command.svelte +1 -1
  43. package/dist/components/primitives/context-menu/context-menu-checkbox-item.svelte +1 -1
  44. package/dist/components/primitives/context-menu/context-menu-content.svelte +1 -1
  45. package/dist/components/primitives/context-menu/context-menu-item.svelte +1 -1
  46. package/dist/components/primitives/context-menu/context-menu-radio-item.svelte +1 -1
  47. package/dist/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
  48. package/dist/components/primitives/context-menu/context-menu-sub-trigger.svelte +1 -1
  49. package/dist/components/primitives/dialog/dialog-content.svelte +2 -2
  50. package/dist/components/primitives/drawer/Drawer.svelte +1 -1
  51. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +31 -11
  52. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +2 -0
  53. package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte +5 -1
  54. package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte.d.ts +2 -0
  55. package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte +4 -2
  56. package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte.d.ts +2 -1
  57. package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +1 -1
  58. package/dist/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +1 -1
  59. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
  60. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +1 -1
  61. package/dist/components/primitives/index.d.ts +1 -1
  62. package/dist/components/primitives/index.js +1 -1
  63. package/dist/components/primitives/input/input.svelte +2 -2
  64. package/dist/components/primitives/input-group/input-group.svelte +1 -1
  65. package/dist/components/primitives/popover/popover-content.svelte +1 -1
  66. package/dist/components/primitives/resizable/resizable-handle.svelte +2 -2
  67. package/dist/components/primitives/search/search.svelte +1 -1
  68. package/dist/components/primitives/select/select-content.svelte +1 -1
  69. package/dist/components/primitives/select/select-item.svelte +1 -1
  70. package/dist/components/primitives/select/select-trigger.svelte +1 -1
  71. package/dist/components/primitives/slider/slider.svelte +1 -1
  72. package/dist/components/primitives/switch/switch.svelte +1 -1
  73. package/dist/components/primitives/tabs/tabs-list.svelte +1 -1
  74. package/dist/components/primitives/tabs/tabs-list.svelte.d.ts +3 -3
  75. package/dist/components/primitives/tabs/tabs-trigger.svelte +1 -1
  76. package/dist/components/primitives/tabs/tabs-trigger.svelte.d.ts +3 -3
  77. package/dist/components/primitives/textarea/textarea.svelte +1 -1
  78. package/dist/components/primitives/toggle/toggle.svelte +6 -3
  79. package/dist/components/primitives/toggle/toggle.svelte.d.ts +10 -7
  80. package/dist/components/primitives/toggle-group/toggle-group-item.svelte +1 -1
  81. package/dist/components/primitives/toggle-group/toggle-group.svelte +1 -1
  82. package/dist/components/primitives/tooltip/index.d.ts +6 -0
  83. package/dist/components/primitives/tooltip/index.js +8 -0
  84. package/dist/components/primitives/tooltip/tooltip-content.svelte +34 -0
  85. package/dist/components/primitives/tooltip/tooltip-content.svelte.d.ts +10 -0
  86. package/dist/components/primitives/tooltip/tooltip-portal.svelte +7 -0
  87. package/dist/components/primitives/tooltip/tooltip-portal.svelte.d.ts +4 -0
  88. package/dist/components/primitives/tooltip/tooltip-provider.svelte +7 -0
  89. package/dist/components/primitives/tooltip/tooltip-provider.svelte.d.ts +4 -0
  90. package/dist/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
  91. package/dist/components/primitives/tooltip/tooltip-trigger.svelte.d.ts +4 -0
  92. package/dist/components/primitives/tooltip/tooltip.svelte +7 -0
  93. package/dist/components/primitives/tooltip/tooltip.svelte.d.ts +4 -0
  94. package/dist/components/viewer/MeshMetadataPanel.svelte +1 -1
  95. package/dist/components/viewer/SceneManager.svelte +19 -19
  96. package/dist/components/viewer/Viewer.svelte +68 -157
  97. package/dist/components/viewer/ViewerDock.svelte +404 -0
  98. package/dist/components/viewer/ViewerDock.svelte.d.ts +42 -0
  99. package/dist/i18n/messages.d.ts +11 -0
  100. package/dist/i18n/messages.js +18 -0
  101. package/dist/styles/base.css +81 -80
  102. package/dist/utils/color-space.d.ts +21 -0
  103. package/dist/utils/color-space.js +90 -0
  104. package/package.json +9 -10
  105. package/src/lib/components/compute/AppLayout.svelte +5 -3
  106. package/src/lib/components/compute/CollapsedPanelStrip.svelte +1 -1
  107. package/src/lib/components/compute/ParameterPresetManager.svelte +1 -1
  108. package/src/lib/components/compute/SolveMessages.svelte +2 -2
  109. package/src/lib/components/layout/FooterItemRenderer.svelte +1 -1
  110. package/src/lib/components/layout/PageFooter.svelte +2 -2
  111. package/src/lib/components/layout/PageHeader.svelte +1 -1
  112. package/src/lib/components/layout/SideNav.svelte +3 -3
  113. package/src/lib/components/layout/SubNav.svelte +2 -2
  114. package/src/lib/components/preview/ChartOutput.svelte +3 -3
  115. package/src/lib/components/preview/Group.svelte +7 -7
  116. package/src/lib/components/preview/ImageOutput.svelte +6 -6
  117. package/src/lib/components/preview/InputControl.svelte +1 -0
  118. package/src/lib/components/preview/OutputDisplay.svelte +8 -6
  119. package/src/lib/components/preview/TabBar.svelte +6 -4
  120. package/src/lib/components/preview/TabContent.svelte +1 -1
  121. package/src/lib/components/preview/TabLayout.svelte +3 -4
  122. package/src/lib/components/preview/inputs/ChecklistInput.svelte +3 -3
  123. package/src/lib/components/preview/inputs/ColorInput.svelte +356 -14
  124. package/src/lib/components/preview/inputs/FileInput.svelte +3 -3
  125. package/src/lib/components/preview/inputs/SegmentedInput.svelte +2 -1
  126. package/src/lib/components/preview/inputs/TileInput.svelte +1 -1
  127. package/src/lib/components/primitives/CalculateButton.svelte +2 -2
  128. package/src/lib/components/primitives/Callout.svelte +7 -5
  129. package/src/lib/components/primitives/DataTable.svelte +1 -1
  130. package/src/lib/components/primitives/ImageUploadField.svelte +1 -1
  131. package/src/lib/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
  132. package/src/lib/components/primitives/badge/badge.svelte +2 -2
  133. package/src/lib/components/primitives/button/button.svelte +6 -7
  134. package/src/lib/components/primitives/card/card.svelte +1 -1
  135. package/src/lib/components/primitives/checkbox/checkbox.svelte +1 -1
  136. package/src/lib/components/primitives/command/command-input.svelte +1 -1
  137. package/src/lib/components/primitives/command/command-item.svelte +1 -1
  138. package/src/lib/components/primitives/command/command-link-item.svelte +1 -1
  139. package/src/lib/components/primitives/command/command.svelte +1 -1
  140. package/src/lib/components/primitives/context-menu/context-menu-checkbox-item.svelte +1 -1
  141. package/src/lib/components/primitives/context-menu/context-menu-content.svelte +1 -1
  142. package/src/lib/components/primitives/context-menu/context-menu-item.svelte +1 -1
  143. package/src/lib/components/primitives/context-menu/context-menu-radio-item.svelte +1 -1
  144. package/src/lib/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
  145. package/src/lib/components/primitives/context-menu/context-menu-sub-trigger.svelte +1 -1
  146. package/src/lib/components/primitives/dialog/dialog-content.svelte +2 -2
  147. package/src/lib/components/primitives/drawer/Drawer.svelte +1 -1
  148. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +31 -11
  149. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-content.svelte +5 -1
  150. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-item.svelte +4 -2
  151. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +1 -1
  152. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +1 -1
  153. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
  154. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +1 -1
  155. package/src/lib/components/primitives/index.ts +1 -1
  156. package/src/lib/components/primitives/input/input.svelte +2 -2
  157. package/src/lib/components/primitives/input-group/input-group.svelte +1 -1
  158. package/src/lib/components/primitives/popover/popover-content.svelte +1 -1
  159. package/src/lib/components/primitives/resizable/resizable-handle.svelte +2 -2
  160. package/src/lib/components/primitives/search/search.svelte +1 -1
  161. package/src/lib/components/primitives/select/select-content.svelte +1 -1
  162. package/src/lib/components/primitives/select/select-item.svelte +1 -1
  163. package/src/lib/components/primitives/select/select-trigger.svelte +1 -1
  164. package/src/lib/components/primitives/slider/slider.svelte +1 -1
  165. package/src/lib/components/primitives/switch/switch.svelte +1 -1
  166. package/src/lib/components/primitives/tabs/tabs-list.svelte +1 -1
  167. package/src/lib/components/primitives/tabs/tabs-trigger.svelte +1 -1
  168. package/src/lib/components/primitives/textarea/textarea.svelte +1 -1
  169. package/src/lib/components/primitives/toggle/toggle.svelte +6 -3
  170. package/src/lib/components/primitives/toggle-group/toggle-group-item.svelte +1 -1
  171. package/src/lib/components/primitives/toggle-group/toggle-group.svelte +1 -1
  172. package/src/lib/components/primitives/tooltip/index.ts +19 -0
  173. package/src/lib/components/primitives/tooltip/tooltip-content.svelte +34 -0
  174. package/src/lib/components/primitives/tooltip/tooltip-portal.svelte +7 -0
  175. package/src/lib/components/primitives/tooltip/tooltip-provider.svelte +7 -0
  176. package/src/lib/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
  177. package/src/lib/components/primitives/tooltip/tooltip.svelte +7 -0
  178. package/src/lib/components/viewer/MeshMetadataPanel.svelte +1 -1
  179. package/src/lib/components/viewer/SceneManager.svelte +19 -19
  180. package/src/lib/components/viewer/Viewer.svelte +68 -157
  181. package/src/lib/components/viewer/ViewerDock.svelte +404 -0
  182. package/src/lib/i18n/messages.ts +29 -0
  183. package/src/lib/styles/base.css +81 -80
  184. package/src/lib/utils/color-space.ts +107 -0
  185. package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
  186. package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte.d.ts +0 -3
  187. package/dist/components/primitives/theme-switcher/index.d.ts +0 -1
  188. package/dist/components/primitives/theme-switcher/index.js +0 -1
  189. package/dist/styles/themes/cyberpunk.css +0 -98
  190. package/dist/styles/themes/neutral.css +0 -72
  191. package/dist/styles/themes/ocean.css +0 -75
  192. package/dist/styles/themes/selva.css +0 -105
  193. package/dist/theme/themeStore.svelte.d.ts +0 -12
  194. package/dist/theme/themeStore.svelte.js +0 -40
  195. package/dist/theme/themes.d.ts +0 -5
  196. package/dist/theme/themes.js +0 -13
  197. package/src/lib/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
  198. package/src/lib/components/primitives/theme-switcher/index.ts +0 -1
  199. package/src/lib/styles/themes/cyberpunk.css +0 -98
  200. package/src/lib/styles/themes/neutral.css +0 -72
  201. package/src/lib/styles/themes/ocean.css +0 -75
  202. package/src/lib/styles/themes/selva.css +0 -105
  203. package/src/lib/theme/themeStore.svelte.ts +0 -50
  204. package/src/lib/theme/themes.ts +0 -18
@@ -1,81 +1,92 @@
1
1
  @custom-variant dark (&:where(.dark, .dark *));
2
2
 
3
+ /* Surfaces, edges and states share one set of names in both modes; each mode only changes the
4
+ values. Ratios are WCAG 2.x. The roles and when to use each: docs/contributing/design-system.md. */
3
5
  :root {
4
- --radius: 0.625rem;
5
6
  --header-h: 3.5rem;
6
7
  --below-header-h: calc(100svh - var(--header-h));
7
8
  --page-px: 1rem;
8
9
  --page-py: 1.75rem;
9
- --background: oklch(0.99 0 0);
10
- --foreground: oklch(0.22 0 0);
11
- /* White, so a card stands apart from background and muted; Group adds a border, since
12
- white on background alone is too close to see. */
10
+ /* Canvas, then surface (cards, panels), then raised (rows, menus, popovers). Light can't go
11
+ lighter than white, so raised is white too and lifts with a border and a shadow instead. */
12
+ --background: oklch(0.91 0 0);
13
13
  --card: oklch(1 0 0);
14
+ --raised: oklch(1 0 0);
15
+ /* Recessed fill for trays, table heads, code and skeletons: darker than the surface around it. */
16
+ --muted: oklch(0.94 0 0);
17
+ /* Fill of anything you type into, on a card: the same step as raised, in both modes. The edge
18
+ (`--input`) carries the boundary. A recessed fill reads as a disabled control. */
19
+ --field: var(--raised);
20
+ --foreground: oklch(0.22 0 0);
14
21
  --card-foreground: oklch(0.22 0 0);
15
- --popover: oklch(0.99 0 0);
16
22
  --popover-foreground: oklch(0.22 0 0);
17
- /* 4.5:1 as text on background, card and muted, and under white text. */
18
- --primary: oklch(0.52 0.07 135);
19
- --primary-foreground: oklch(0.985 0 0);
20
- --secondary: oklch(0.94 0 0);
21
- --secondary-foreground: oklch(0.28 0 0);
22
- --muted: oklch(0.95 0 0);
23
- --muted-foreground: oklch(0.5 0 0);
24
- --accent: oklch(0.93 0 0);
25
- --accent-foreground: oklch(0.3 0 0);
26
- /* 4.5:1 as small text on background, card and muted, and under white text. */
27
- --destructive: oklch(0.55 0.19 27);
28
- --destructive-foreground: oklch(0.985 0 0);
29
- --border: oklch(0.86 0 0);
30
- /* Field borders and unchecked boxes: at least 3:1 against background, card and muted, the
31
- WCAG minimum for a control's boundary. Same for the focus ring, which is drawn opaque. */
32
- --input: oklch(0.62 0 0);
23
+ /* 4.5:1 on every surface. */
24
+ --muted-foreground: oklch(0.48 0 0);
25
+ /* Icons, placeholders, disabled text: 3:1 on every surface. */
26
+ --faint-foreground: oklch(0.6 0 0);
27
+ /* State overlays, laid over whatever surface is underneath. */
28
+ --hover: oklch(0 0 0 / 6%);
29
+ --selected: oklch(0 0 0 / 12%);
30
+ /* Rest fill of a neutral filled control; its hover is `selected`. */
31
+ --secondary: oklch(0 0 0 / 7%);
32
+ --secondary-foreground: oklch(0.22 0 0);
33
+ /* Outlines and separators. */
34
+ --border: oklch(0 0 0 / 11%);
35
+ /* Popovers, outline buttons, dashed drop zones. */
36
+ --border-strong: oklch(0 0 0 / 24%);
37
+ /* Edge of anything you type into or toggle, slider tracks included: at least 3:1 against the
38
+ surfaces around it, the WCAG minimum for a control's boundary. */
39
+ --input: oklch(0 0 0 / 44%);
33
40
  --ring: oklch(0.55 0 0);
34
- --success: oklch(0.66 0.14 145);
41
+ --elevation-raised: 0 1px 2px oklch(0 0 0 / 6%);
42
+ --elevation-popover: 0 8px 24px oklch(0 0 0 / 12%);
43
+ /* 4.5:1 as text on a card and under its foreground; 3:1 as a fill on every surface. */
44
+ --primary: #4a7c52;
45
+ --primary-foreground: oklch(0.985 0 0);
46
+ --destructive: #c9302d;
47
+ --destructive-foreground: #fbfbfb;
48
+ /* 3:1 on every surface, as icons and dots. */
49
+ --success: #51a556;
35
50
  --success-foreground: oklch(0.99 0 0);
36
- --warning: oklch(0.78 0.12 75);
51
+ --warning: #bd8630;
37
52
  --warning-foreground: oklch(0.25 0.04 75);
38
- --info: oklch(0.68 0.11 245);
53
+ --info: #5399d1;
39
54
  --info-foreground: oklch(0.99 0 0);
40
55
  --chart-1: oklch(0.65 0.14 135);
41
56
  --chart-2: oklch(0.7 0.11 200);
42
57
  --chart-3: oklch(0.6 0.13 260);
43
58
  --chart-4: oklch(0.78 0.13 80);
44
59
  --chart-5: oklch(0.68 0.15 30);
45
- --sidebar: oklch(0.96 0 0);
46
- --sidebar-foreground: oklch(0.25 0 0);
47
- --sidebar-primary: oklch(0.52 0.07 135);
48
- --sidebar-primary-foreground: oklch(0.985 0 0);
49
- --sidebar-accent: oklch(0.93 0 0);
50
- --sidebar-accent-foreground: oklch(0.3 0 0);
51
- --sidebar-border: oklch(0.88 0 0);
52
- --sidebar-ring: oklch(0.55 0 0);
53
- --inputparam: oklch(1 0 0);
54
- --outputparam: oklch(1 0 0);
55
60
  /* Scrim behind modal dialogs and drawers. */
56
61
  --overlay: oklch(0 0 0 / 50%);
57
62
  }
58
63
 
59
64
  .dark {
60
- --background: oklch(0.17 0 0);
65
+ --background: oklch(0.155 0 0);
66
+ --card: oklch(0.235 0 0);
67
+ --raised: oklch(0.275 0 0);
68
+ --muted: oklch(0.18 0 0);
61
69
  --foreground: oklch(0.96 0 0);
62
- --card: oklch(0.23 0 0);
63
70
  --card-foreground: oklch(0.96 0 0);
64
- --popover: oklch(0.23 0 0);
65
71
  --popover-foreground: oklch(0.96 0 0);
66
- --primary: oklch(0.74 0.07 135);
67
- --primary-foreground: oklch(0.18 0 0);
68
- --secondary: oklch(0.3 0 0);
69
- --secondary-foreground: oklch(0.96 0 0);
70
- --muted: oklch(0.27 0 0);
71
72
  --muted-foreground: oklch(0.72 0 0);
72
- --accent: oklch(0.36 0 0);
73
- --accent-foreground: oklch(0.92 0 0);
74
- --destructive: oklch(0.7 0.17 22);
75
- --destructive-foreground: oklch(0.985 0 0);
76
- --border: oklch(1 0 0 / 14%);
77
- --input: oklch(1 0 0 / 36%);
73
+ --faint-foreground: oklch(0.56 0 0);
74
+ --hover: oklch(1 0 0 / 6%);
75
+ --selected: oklch(1 0 0 / 12%);
76
+ --secondary: oklch(1 0 0 / 8%);
77
+ --secondary-foreground: oklch(0.96 0 0);
78
+ --border: oklch(1 0 0 / 11%);
79
+ --border-strong: oklch(1 0 0 / 24%);
80
+ --input: oklch(1 0 0 / 41%);
78
81
  --ring: oklch(0.74 0 0);
82
+ /* Shadows barely show on a dark canvas, so raised things catch a top highlight instead. */
83
+ --elevation-raised: inset 0 1px 0 oklch(1 0 0 / 5%);
84
+ --elevation-popover: 0 8px 24px oklch(0 0 0 / 50%), inset 0 1px 0 oklch(1 0 0 / 6%);
85
+ --primary: #86ab78;
86
+ --primary-foreground: oklch(0.18 0 0);
87
+ /* White text can't reach 4.5:1 on a red light enough to also be text on the dark card. */
88
+ --destructive: oklch(0.7 0.17 22);
89
+ --destructive-foreground: oklch(0.18 0 0);
79
90
  --success: oklch(0.74 0.15 145);
80
91
  --success-foreground: oklch(0.18 0.03 145);
81
92
  --warning: oklch(0.8 0.14 75);
@@ -87,41 +98,39 @@
87
98
  --chart-3: oklch(0.68 0.14 260);
88
99
  --chart-4: oklch(0.78 0.14 80);
89
100
  --chart-5: oklch(0.7 0.16 30);
90
- --sidebar: oklch(0.21 0 0);
91
- --sidebar-foreground: oklch(0.96 0 0);
92
- --sidebar-primary: oklch(0.74 0.07 135);
93
- --sidebar-primary-foreground: oklch(0.18 0 0);
94
- --sidebar-accent: oklch(0.32 0 0);
95
- --sidebar-accent-foreground: oklch(0.92 0 0);
96
- --sidebar-border: oklch(1 0 0 / 10%);
97
- --sidebar-ring: oklch(0.74 0 0);
98
- --inputparam: oklch(0.15 0 0);
99
- --outputparam: oklch(0.25 0 0);
100
101
  }
101
102
 
102
103
  @theme inline {
103
- --radius-sm: calc(var(--radius) - 4px);
104
- --radius-md: calc(var(--radius) - 2px);
105
- --radius-lg: var(--radius);
106
- --radius-xl: calc(var(--radius) + 4px);
104
+ /* Concentric: an item inside a padded container takes the container's radius minus the
105
+ padding. A 12px menu with 4px padding holds 8px items; a 10px control with 2px padding
106
+ holds 8px segments. */
107
+ --radius-sm: 6px;
108
+ --radius-inner: 8px;
109
+ --radius-md: 10px;
110
+ --radius-lg: 12px;
111
+ --radius-xl: 16px;
107
112
  --color-background: var(--background);
108
113
  --color-foreground: var(--foreground);
109
114
  --color-card: var(--card);
110
115
  --color-card-foreground: var(--card-foreground);
111
- --color-popover: var(--popover);
116
+ --color-raised: var(--raised);
117
+ --color-popover: var(--raised);
112
118
  --color-popover-foreground: var(--popover-foreground);
113
- --color-primary: var(--primary);
114
- --color-primary-foreground: var(--primary-foreground);
115
- --color-secondary: var(--secondary);
116
- --color-secondary-foreground: var(--secondary-foreground);
119
+ --color-field: var(--field);
117
120
  --color-muted: var(--muted);
118
121
  --color-muted-foreground: var(--muted-foreground);
119
- --color-accent: var(--accent);
120
- --color-accent-foreground: var(--accent-foreground);
122
+ --color-faint-foreground: var(--faint-foreground);
123
+ --color-hover: var(--hover);
124
+ --color-selected: var(--selected);
125
+ --color-secondary: var(--secondary);
126
+ --color-secondary-foreground: var(--secondary-foreground);
127
+ --color-primary: var(--primary);
128
+ --color-primary-foreground: var(--primary-foreground);
121
129
  --color-destructive: var(--destructive);
122
130
  --color-destructive-foreground: var(--destructive-foreground);
123
131
  --color-overlay: var(--overlay);
124
132
  --color-border: var(--border);
133
+ --color-border-strong: var(--border-strong);
125
134
  --color-input: var(--input);
126
135
  --color-ring: var(--ring);
127
136
  --color-success: var(--success);
@@ -135,16 +144,8 @@
135
144
  --color-chart-3: var(--chart-3);
136
145
  --color-chart-4: var(--chart-4);
137
146
  --color-chart-5: var(--chart-5);
138
- --color-sidebar: var(--sidebar);
139
- --color-sidebar-foreground: var(--sidebar-foreground);
140
- --color-sidebar-primary: var(--sidebar-primary);
141
- --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
142
- --color-sidebar-accent: var(--sidebar-accent);
143
- --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
144
- --color-sidebar-border: var(--sidebar-border);
145
- --color-sidebar-ring: var(--sidebar-ring);
146
- --color-inputparam: var(--inputparam);
147
- --color-outputparam: var(--outputparam);
147
+ --shadow-raised: var(--elevation-raised);
148
+ --shadow-popover: var(--elevation-popover);
148
149
  }
149
150
 
150
151
  /* Design tokens beyond Tailwind's defaults. Reach for these before an arbitrary value: the
@@ -0,0 +1,21 @@
1
+ export interface Rgb {
2
+ r: number;
3
+ g: number;
4
+ b: number;
5
+ }
6
+ /** h in [0, 360), s and v in [0, 1]. */
7
+ export interface Hsv {
8
+ h: number;
9
+ s: number;
10
+ v: number;
11
+ }
12
+ /** Accepts `#rgb`, `#rrggbb` and the same without `#`. Returns lowercase `#rrggbb`, or null. */
13
+ export declare function normalizeHex(input: string): string | null;
14
+ export declare function hexToRgb(hex: string): Rgb | null;
15
+ export declare function rgbToHex({ r, g, b }: Rgb): string;
16
+ export declare function rgbToHsv({ r, g, b }: Rgb): Hsv;
17
+ export declare function hsvToRgb({ h, s, v }: Hsv): Rgb;
18
+ export declare const hexToHsv: (hex: string) => Hsv | null;
19
+ export declare const hsvToHex: (hsv: Hsv) => string;
20
+ /** WCAG contrast ratio between two hex colors, 1 to 21. Null if either isn't a hex color. */
21
+ export declare function contrastRatio(a: string, b: string): number | null;
@@ -0,0 +1,90 @@
1
+ const clamp = (n, min, max) => Math.min(max, Math.max(min, n));
2
+ /** Accepts `#rgb`, `#rrggbb` and the same without `#`. Returns lowercase `#rrggbb`, or null. */
3
+ export function normalizeHex(input) {
4
+ const raw = input.trim().replace(/^#/, '');
5
+ if (/^[0-9a-f]{3}$/i.test(raw)) {
6
+ return `#${raw
7
+ .split('')
8
+ .map((c) => c + c)
9
+ .join('')
10
+ .toLowerCase()}`;
11
+ }
12
+ if (/^[0-9a-f]{6}$/i.test(raw))
13
+ return `#${raw.toLowerCase()}`;
14
+ return null;
15
+ }
16
+ export function hexToRgb(hex) {
17
+ const normalized = normalizeHex(hex);
18
+ if (!normalized)
19
+ return null;
20
+ return {
21
+ r: parseInt(normalized.slice(1, 3), 16),
22
+ g: parseInt(normalized.slice(3, 5), 16),
23
+ b: parseInt(normalized.slice(5, 7), 16)
24
+ };
25
+ }
26
+ export function rgbToHex({ r, g, b }) {
27
+ const channel = (n) => clamp(Math.round(n), 0, 255).toString(16).padStart(2, '0');
28
+ return `#${channel(r)}${channel(g)}${channel(b)}`;
29
+ }
30
+ export function rgbToHsv({ r, g, b }) {
31
+ const rn = r / 255;
32
+ const gn = g / 255;
33
+ const bn = b / 255;
34
+ const max = Math.max(rn, gn, bn);
35
+ const delta = max - Math.min(rn, gn, bn);
36
+ let h = 0;
37
+ if (delta !== 0) {
38
+ if (max === rn)
39
+ h = ((gn - bn) / delta) % 6;
40
+ else if (max === gn)
41
+ h = (bn - rn) / delta + 2;
42
+ else
43
+ h = (rn - gn) / delta + 4;
44
+ h *= 60;
45
+ if (h < 0)
46
+ h += 360;
47
+ }
48
+ return { h, s: max === 0 ? 0 : delta / max, v: max };
49
+ }
50
+ export function hsvToRgb({ h, s, v }) {
51
+ const c = v * s;
52
+ const hp = (((h % 360) + 360) % 360) / 60;
53
+ const x = c * (1 - Math.abs((hp % 2) - 1));
54
+ const [r1, g1, b1] = hp < 1
55
+ ? [c, x, 0]
56
+ : hp < 2
57
+ ? [x, c, 0]
58
+ : hp < 3
59
+ ? [0, c, x]
60
+ : hp < 4
61
+ ? [0, x, c]
62
+ : hp < 5
63
+ ? [x, 0, c]
64
+ : [c, 0, x];
65
+ const m = v - c;
66
+ return { r: (r1 + m) * 255, g: (g1 + m) * 255, b: (b1 + m) * 255 };
67
+ }
68
+ export const hexToHsv = (hex) => {
69
+ const rgb = hexToRgb(hex);
70
+ return rgb ? rgbToHsv(rgb) : null;
71
+ };
72
+ export const hsvToHex = (hsv) => rgbToHex(hsvToRgb(hsv));
73
+ /** WCAG relative luminance of an sRGB color. */
74
+ function luminance({ r, g, b }) {
75
+ const lin = (c) => {
76
+ const n = c / 255;
77
+ return n <= 0.04045 ? n / 12.92 : Math.pow((n + 0.055) / 1.055, 2.4);
78
+ };
79
+ return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b);
80
+ }
81
+ /** WCAG contrast ratio between two hex colors, 1 to 21. Null if either isn't a hex color. */
82
+ export function contrastRatio(a, b) {
83
+ const ra = hexToRgb(a);
84
+ const rb = hexToRgb(b);
85
+ if (!ra || !rb)
86
+ return null;
87
+ const la = luminance(ra);
88
+ const lb = luminance(rb);
89
+ return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
90
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@selvajs/ui",
3
- "version": "6.6.0-beta.15",
3
+ "version": "6.6.0-beta.16",
4
4
  "description": "Shared UI components and utilities for Selva applications",
5
5
  "license": "MIT",
6
6
  "author": "VektorNode",
@@ -44,8 +44,7 @@
44
44
  "types": "./dist/external/storage.d.ts",
45
45
  "svelte": "./dist/external/storage.js"
46
46
  },
47
- "./styles/base.css": "./src/lib/styles/base.css",
48
- "./styles/themes/*": "./src/lib/styles/themes/*"
47
+ "./styles/base.css": "./src/lib/styles/base.css"
49
48
  },
50
49
  "files": [
51
50
  "dist",
@@ -62,11 +61,11 @@
62
61
  "bits-ui": "^2.18.0",
63
62
  "svelte": "^5",
64
63
  "tailwind-variants": "^3.3.1",
65
- "three": "^0.186.1",
64
+ "three": "^0.187.0",
66
65
  "@selvajs/compute": "^5.0.0-beta.9",
67
- "@selvajs/visualization": "^1.6.0-beta.9",
66
+ "@selvajs/solve": "^2.0.0-beta.12",
68
67
  "@selvajs/schemas": "^5.3.0-beta.2",
69
- "@selvajs/solve": "^2.0.0-beta.12"
68
+ "@selvajs/visualization": "^1.6.0-beta.9"
70
69
  },
71
70
  "peerDependenciesMeta": {
72
71
  "three": {
@@ -88,17 +87,17 @@
88
87
  "@internationalized/date": "^3.12.4",
89
88
  "@sveltejs/kit": "2.70.3",
90
89
  "@sveltejs/vite-plugin-svelte": "^7.3.1",
91
- "@types/three": "^0.186.0",
90
+ "@types/three": "^0.187.0",
92
91
  "bits-ui": "^2.20.2",
93
92
  "rimraf": "^6.1.3",
94
93
  "svelte": "5.57.2",
95
94
  "tailwind-variants": "^3.3.1",
96
95
  "vitest": "^5.0.5",
97
96
  "@selvajs/compute": "5.0.0-beta.9",
98
- "@selvajs/visualization": "1.6.0-beta.9",
99
- "@selvajs/solve": "2.0.0-beta.12",
100
97
  "@selvajs/config": "0.0.4",
101
- "@selvajs/schemas": "5.3.0-beta.2"
98
+ "@selvajs/visualization": "1.6.0-beta.9",
99
+ "@selvajs/schemas": "5.3.0-beta.2",
100
+ "@selvajs/solve": "2.0.0-beta.12"
102
101
  },
103
102
  "scripts": {
104
103
  "predev": "node ../../scripts/sync-shared-assets.js",
@@ -284,7 +284,7 @@
284
284
  trailing={hasMenu ? actionsMenu : undefined}
285
285
  />
286
286
  {:else if hasMenu || solvingIndicatorPlacement === 'inline'}
287
- <div class="mt-3 pb-3 pt-2 px-2 gap-2 flex items-center border-t border-border/50">
287
+ <div class="mt-3 pb-3 pt-2 px-2 gap-2 flex items-center border-t border-border">
288
288
  {#if solvingIndicatorPlacement === 'inline'}
289
289
  <SolvingIndicator show={showSolvingChip} placement="inline" />
290
290
  {/if}
@@ -325,7 +325,7 @@
325
325
  data-layout-root
326
326
  class="min-h-0 flex flex-1 flex-col overflow-hidden {stacked
327
327
  ? ''
328
- : `sm:flex-row sm:py-(--page-py) ${leftCollapsed ? 'sm:pl-0' : 'sm:pl-(--page-px)'} ${rightCollapsed ? 'sm:pr-0' : 'sm:pr-(--page-px)'}`}"
328
+ : `sm:flex-row sm:py-2 ${leftCollapsed ? 'sm:pl-0' : 'sm:pl-2'} ${rightCollapsed ? 'sm:pr-0' : 'sm:pr-2'}`}"
329
329
  class:fullscreen-layout={isViewerFullscreen}
330
330
  class:relative={isMobile}
331
331
  class:mobile-root={stacked}
@@ -355,7 +355,7 @@
355
355
  </div>
356
356
 
357
357
  <div
358
- class="drawer-container rounded-t-2xl z-40 border-t bg-background shadow-sheet drawer-{drawer}"
358
+ class="drawer-container z-40 rounded-t-xl border-t bg-background shadow-sheet drawer-{drawer}"
359
359
  >
360
360
  <!-- Named by its visible label; aria-expanded carries the open/closed state. -->
361
361
  <button
@@ -473,6 +473,7 @@
473
473
  <Resizable.Handle
474
474
  withHandle
475
475
  line={false}
476
+ class="translate-x-1.5 z-20"
476
477
  data-collapsed={leftCollapsed}
477
478
  onclick={() => {
478
479
  if (leftCollapsed) leftPaneRef?.expand();
@@ -504,6 +505,7 @@
504
505
  <Resizable.Handle
505
506
  withHandle
506
507
  line={false}
508
+ class="-translate-x-1.5 z-20"
507
509
  data-collapsed={rightCollapsed}
508
510
  onclick={() => {
509
511
  if (rightCollapsed) rightPaneRef?.expand();
@@ -27,7 +27,7 @@
27
27
  );
28
28
 
29
29
  const tabButtonClass =
30
- 'w-8 h-8 rounded-md cursor-pointer flex shrink-0 items-center justify-center text-muted-foreground transition-colors hover:bg-accent hover:text-foreground';
30
+ 'w-8 h-8 rounded-md cursor-pointer flex shrink-0 items-center justify-center text-muted-foreground transition-colors hover:bg-hover hover:text-foreground';
31
31
  </script>
32
32
 
33
33
  <div
@@ -203,7 +203,7 @@
203
203
  <button
204
204
  type="button"
205
205
  onclick={() => selectListedState(preset)}
206
- class="p-3 w-full rounded-lg border text-left transition-colors hover:bg-muted"
206
+ class="p-3 w-full rounded-lg border text-left transition-colors hover:bg-hover"
207
207
  >
208
208
  <div class="text-sm font-medium">{preset.name}</div>
209
209
  {#if preset.description}
@@ -291,7 +291,7 @@
291
291
  framed box inside an edge-to-edge column reads as a dialog glued into the page. -->
292
292
  <div
293
293
  class={placement === 'inline'
294
- ? `px-2 py-2 border-t ${view === 'blocked' ? 'border-destructive/40' : 'border-border/50'}`
294
+ ? `px-2 py-2 border-t ${view === 'blocked' ? 'border-destructive/40' : 'border-border'}`
295
295
  : `p-3 bottom-4 shadow-lg w-lg fixed left-1/2 z-50 max-w-screen-inset -translate-x-1/2 rounded-lg border bg-background ${view === 'blocked' ? 'border-destructive/50' : ''}`}
296
296
  role={view === 'review' || view === 'blocked' ? 'alert' : undefined}
297
297
  data-testid="solve-messages"
@@ -319,7 +319,7 @@
319
319
  title={t.solveMessagesEscHint}
320
320
  >
321
321
  {t.solveMessagesAbort}
322
- <kbd class="px-1 font-sans rounded border border-border/60 text-2xs opacity-70">
322
+ <kbd class="px-1 font-sans rounded-sm border border-border text-2xs opacity-70">
323
323
  Esc
324
324
  </kbd>
325
325
  </Button>
@@ -9,7 +9,7 @@
9
9
  {#if item.onClick}
10
10
  <button
11
11
  onclick={item.onClick}
12
- class="gap-1.5 px-2 py-0.5 rounded flex cursor-pointer items-center transition-colors hover:bg-muted"
12
+ class="gap-1.5 px-2 py-0.5 flex cursor-pointer items-center rounded-sm transition-colors hover:bg-hover"
13
13
  >
14
14
  <item.component {...itemProps} />
15
15
  </button>
@@ -88,12 +88,12 @@
88
88
  <ComputeMessagesDialog {errors} {warnings} {diagnostics}>
89
89
  {#snippet trigger()}
90
90
  <div
91
- class="gap-1.5 px-2 py-1 rounded flex cursor-pointer items-center transition-colors hover:bg-muted {errorCount >
91
+ class="gap-1.5 px-2 py-1 flex cursor-pointer items-center rounded-sm transition-colors hover:bg-hover {errorCount >
92
92
  0
93
93
  ? 'text-destructive hover:bg-destructive/10'
94
94
  : warningCount > 0
95
95
  ? 'text-warning hover:bg-warning/10'
96
- : 'hover:bg-muted'}"
96
+ : 'hover:bg-hover'}"
97
97
  title={formatCount(totalCount, t.lastSolveMessagesOne, t.lastSolveMessagesOther)}
98
98
  >
99
99
  {#if errorCount > 0}
@@ -66,7 +66,7 @@
66
66
  </div>
67
67
 
68
68
  {#if subnav}
69
- <div class="h-10 flex items-center border-t border-border/60 px-(--page-px)">
69
+ <div class="h-10 flex items-center border-t border-border px-(--page-px)">
70
70
  {@render subnav()}
71
71
  </div>
72
72
  {/if}
@@ -119,8 +119,8 @@
119
119
  aria-current={active ? 'page' : undefined}
120
120
  class={`group gap-2 py-1.5 pr-2.5 relative flex w-full items-center text-left transition-colors ${
121
121
  active
122
- ? 'pl-4 rounded-r-md bg-accent text-accent-foreground'
123
- : 'mx-2 pl-2.5 rounded-md text-muted-foreground hover:bg-muted/60 hover:text-foreground'
122
+ ? 'pl-4 rounded-r-md bg-selected text-foreground'
123
+ : 'mx-2 pl-2.5 rounded-md text-muted-foreground hover:bg-hover hover:text-foreground'
124
124
  }`}
125
125
  >
126
126
  {#if active}
@@ -138,7 +138,7 @@
138
138
  </nav>
139
139
 
140
140
  {#if footer}
141
- <div class="px-3 py-3 sm:block hidden border-t border-border/60">
141
+ <div class="px-3 py-3 sm:block hidden border-t border-border">
142
142
  {@render footer()}
143
143
  </div>
144
144
  {/if}
@@ -31,8 +31,8 @@
31
31
  class={[
32
32
  'h-7 px-3 gap-1.5 text-sm font-medium flex items-center rounded-md transition-colors',
33
33
  active
34
- ? 'bg-accent text-accent-foreground'
35
- : 'text-muted-foreground hover:bg-accent/50 hover:text-foreground'
34
+ ? 'bg-selected text-foreground'
35
+ : 'text-muted-foreground hover:bg-hover hover:text-foreground'
36
36
  ].join(' ')}
37
37
  >
38
38
  {#if item.icon}
@@ -222,7 +222,7 @@
222
222
 
223
223
  <div
224
224
  bind:this={wrapperEl}
225
- class="group relative overflow-hidden rounded-lg border border-border {isFullscreen
225
+ class="group relative overflow-hidden rounded-lg border border-border-strong {isFullscreen
226
226
  ? 'bg-background'
227
227
  : ''}"
228
228
  >
@@ -241,7 +241,7 @@
241
241
  >
242
242
  {#if loading}
243
243
  <div
244
- class="rounded p-1.5 backdrop-blur-sm flex items-center border border-border bg-background/80 text-muted-foreground"
244
+ class="p-1.5 backdrop-blur-sm flex items-center rounded-sm border border-border-strong bg-background/80 text-muted-foreground"
245
245
  >
246
246
  <Loader size={14} class="animate-spin" />
247
247
  </div>
@@ -253,7 +253,7 @@
253
253
  disabled={loading}
254
254
  title={isFullscreen ? t.exitFullscreen : t.fullscreen}
255
255
  aria-label={isFullscreen ? t.exitFullscreen : t.fullscreen}
256
- class="rounded p-1.5 backdrop-blur-sm flex items-center border border-border bg-background/80 text-foreground transition-colors hover:bg-background disabled:cursor-not-allowed disabled:opacity-50"
256
+ class="p-1.5 backdrop-blur-sm flex items-center rounded-sm border border-border-strong bg-background/80 text-foreground transition-colors hover:bg-background disabled:cursor-not-allowed disabled:opacity-50"
257
257
  >
258
258
  {#if isFullscreen}
259
259
  <Minimize size={14} />
@@ -69,7 +69,7 @@
69
69
  </div>
70
70
  {/snippet}
71
71
 
72
- <section class="shadow-xs rounded-xl border bg-card">
72
+ <section class="rounded-xl border bg-card shadow-raised">
73
73
  {#if flat}
74
74
  <div class="p-4">
75
75
  {@render grid()}
@@ -80,18 +80,18 @@
80
80
  <h3>
81
81
  <button
82
82
  type="button"
83
- class="gap-3 px-4 pt-3.5 flex w-full items-start text-left outline-none select-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset {description
83
+ class="gap-3 px-4 pt-4 flex w-full items-start text-left outline-none select-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset {description
84
84
  ? 'pb-0'
85
- : 'pb-3.5'}"
85
+ : 'pb-3'}"
86
86
  aria-expanded={!collapsed}
87
87
  aria-describedby={description ? descriptionId : undefined}
88
88
  onclick={onToggle}
89
89
  >
90
- <span class="min-w-0 text-base font-semibold leading-snug flex-1 text-foreground"
90
+ <span class="min-w-0 text-sm font-semibold leading-snug flex-1 text-foreground"
91
91
  >{label}</span
92
92
  >
93
93
  <ChevronDown
94
- class="mt-1 h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200 {collapsed
94
+ class="mt-0.5 h-4 w-4 shrink-0 text-faint-foreground transition-transform duration-200 {collapsed
95
95
  ? '-rotate-90'
96
96
  : ''}"
97
97
  />
@@ -100,14 +100,14 @@
100
100
  {#if description}
101
101
  <p
102
102
  id={descriptionId}
103
- class="pl-4 pr-11 pt-0.5 pb-3.5 text-xs leading-snug text-muted-foreground"
103
+ class="pl-4 pr-11 pt-0.5 pb-3 text-xs leading-snug text-muted-foreground"
104
104
  >
105
105
  {description}
106
106
  </p>
107
107
  {/if}
108
108
  <div class="content-wrapper" class:collapsed inert={collapsed}>
109
109
  <div class="content-inner">
110
- <div class="px-4 pt-1 pb-5">
110
+ <div class="px-4 pt-1 pb-4">
111
111
  {@render grid()}
112
112
  </div>
113
113
  </div>