@selvajs/ui 6.5.1-beta.1 → 6.6.0-beta.12

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 (446) hide show
  1. package/dist/components/ConfirmDialog.svelte +2 -10
  2. package/dist/components/ErrorScreen.svelte +21 -27
  3. package/dist/components/compute/AppLayout.svelte +298 -128
  4. package/dist/components/compute/AppLayout.svelte.d.ts +22 -0
  5. package/dist/components/compute/CollapsedPanelStrip.svelte +4 -2
  6. package/dist/components/compute/ComputeApp.svelte +45 -24
  7. package/dist/components/compute/ComputeApp.svelte.d.ts +19 -2
  8. package/dist/components/compute/ComputeMessagesDialog.svelte +47 -83
  9. package/dist/components/compute/ParameterPresetManager.svelte +37 -130
  10. package/dist/components/compute/ParameterPresetManager.svelte.d.ts +4 -5
  11. package/dist/components/compute/SolveMessages.svelte +131 -77
  12. package/dist/components/compute/SolveMessages.svelte.d.ts +7 -12
  13. package/dist/components/layout/AppShell.svelte +10 -6
  14. package/dist/components/layout/PageFooter.svelte +23 -11
  15. package/dist/components/layout/PageHeader.svelte +11 -7
  16. package/dist/components/layout/Pagination.svelte +2 -4
  17. package/dist/components/layout/SectionHeader.svelte +4 -2
  18. package/dist/components/layout/SideNav.svelte +56 -7
  19. package/dist/components/preview/ChartOutput.svelte +91 -48
  20. package/dist/components/preview/Group.svelte +92 -103
  21. package/dist/components/preview/Group.svelte.d.ts +1 -1
  22. package/dist/components/preview/HelpButton.svelte +36 -0
  23. package/dist/components/preview/HelpButton.svelte.d.ts +8 -0
  24. package/dist/components/preview/ImageOutput.svelte +434 -72
  25. package/dist/components/preview/InputControl.svelte +163 -90
  26. package/dist/components/preview/InputControl.svelte.d.ts +5 -1
  27. package/dist/components/preview/OutputDisplay.svelte +44 -42
  28. package/dist/components/preview/TabBar.svelte +106 -22
  29. package/dist/components/preview/TabBar.svelte.d.ts +1 -0
  30. package/dist/components/preview/TabContent.svelte +63 -57
  31. package/dist/components/preview/TabContent.svelte.d.ts +5 -1
  32. package/dist/components/preview/TabLayout.svelte +27 -5
  33. package/dist/components/preview/TabLayout.svelte.d.ts +5 -0
  34. package/dist/components/preview/inputs/CheckboxInput.svelte +7 -7
  35. package/dist/components/preview/inputs/CheckboxInput.svelte.d.ts +3 -0
  36. package/dist/components/preview/inputs/ChecklistInput.svelte +7 -2
  37. package/dist/components/preview/inputs/ChecklistInput.svelte.d.ts +2 -1
  38. package/dist/components/preview/inputs/ColorInput.svelte +4 -2
  39. package/dist/components/preview/inputs/ColorInput.svelte.d.ts +1 -0
  40. package/dist/components/preview/inputs/DropdownInput.svelte +19 -4
  41. package/dist/components/preview/inputs/DropdownInput.svelte.d.ts +2 -1
  42. package/dist/components/preview/inputs/FileInput.svelte +112 -108
  43. package/dist/components/preview/inputs/GeometryInput.svelte +128 -0
  44. package/dist/components/preview/inputs/GeometryInput.svelte.d.ts +21 -0
  45. package/dist/components/preview/inputs/NumberInput.svelte +123 -61
  46. package/dist/components/preview/inputs/NumberInput.svelte.d.ts +2 -0
  47. package/dist/components/preview/inputs/OptionGlyph.svelte +29 -0
  48. package/dist/components/preview/inputs/OptionGlyph.svelte.d.ts +8 -0
  49. package/dist/components/preview/inputs/SegmentedInput.svelte +44 -0
  50. package/dist/components/preview/inputs/SegmentedInput.svelte.d.ts +12 -0
  51. package/dist/components/preview/inputs/TextInput.svelte +8 -4
  52. package/dist/components/preview/inputs/TileInput.svelte +80 -0
  53. package/dist/components/preview/inputs/TileInput.svelte.d.ts +12 -0
  54. package/dist/components/preview/inputs/index.d.ts +3 -0
  55. package/dist/components/preview/inputs/index.js +3 -0
  56. package/dist/components/primitives/CalculateButton.svelte +56 -24
  57. package/dist/components/primitives/CalculateButton.svelte.d.ts +3 -0
  58. package/dist/components/primitives/Callout.svelte +11 -18
  59. package/dist/components/primitives/DataTable.svelte +38 -5
  60. package/dist/components/primitives/DataTable.svelte.d.ts +2 -0
  61. package/dist/components/primitives/FilterableDropdown.svelte +42 -129
  62. package/dist/components/primitives/FilterableDropdown.svelte.d.ts +1 -1
  63. package/dist/components/primitives/IssueList.svelte +56 -0
  64. package/dist/components/primitives/IssueList.svelte.d.ts +20 -0
  65. package/dist/components/primitives/SeverityIcon.svelte +15 -0
  66. package/dist/components/primitives/SeverityIcon.svelte.d.ts +8 -0
  67. package/dist/components/primitives/SolvingIndicator.svelte +43 -42
  68. package/dist/components/primitives/SolvingIndicator.svelte.d.ts +6 -0
  69. package/dist/components/primitives/StateDisplay.svelte +19 -79
  70. package/dist/components/primitives/ViewToggle.svelte +18 -33
  71. package/dist/components/primitives/alert-dialog/alert-dialog-action.svelte +9 -3
  72. package/dist/components/primitives/alert-dialog/alert-dialog-action.svelte.d.ts +6 -1
  73. package/dist/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
  74. package/dist/components/primitives/alert-dialog/alert-dialog-overlay.svelte +1 -1
  75. package/dist/components/primitives/badge/badge.svelte +2 -2
  76. package/dist/components/primitives/badge/badge.svelte.d.ts +4 -4
  77. package/dist/components/primitives/button/button.svelte +6 -2
  78. package/dist/components/primitives/button/button.svelte.d.ts +10 -4
  79. package/dist/components/primitives/card/card-header.svelte +1 -1
  80. package/dist/components/primitives/card/card.svelte +21 -5
  81. package/dist/components/primitives/card/card.svelte.d.ts +25 -1
  82. package/dist/components/primitives/card/index.d.ts +1 -2
  83. package/dist/components/primitives/card/index.js +2 -3
  84. package/dist/components/primitives/checkbox/checkbox.svelte +1 -1
  85. package/dist/components/primitives/command/command-dialog.svelte +42 -0
  86. package/dist/components/primitives/command/command-dialog.svelte.d.ts +14 -0
  87. package/dist/components/primitives/command/command-empty.svelte +17 -0
  88. package/dist/components/primitives/command/command-empty.svelte.d.ts +4 -0
  89. package/dist/components/primitives/command/command-group.svelte +33 -0
  90. package/dist/components/primitives/command/command-group.svelte.d.ts +7 -0
  91. package/dist/components/primitives/command/command-input.svelte +36 -0
  92. package/dist/components/primitives/command/command-input.svelte.d.ts +4 -0
  93. package/dist/components/primitives/command/command-item.svelte +28 -0
  94. package/dist/components/primitives/command/command-item.svelte.d.ts +4 -0
  95. package/dist/components/primitives/command/command-link-item.svelte +21 -0
  96. package/dist/components/primitives/command/command-link-item.svelte.d.ts +4 -0
  97. package/dist/components/primitives/command/command-list.svelte +20 -0
  98. package/dist/components/primitives/command/command-list.svelte.d.ts +4 -0
  99. package/dist/components/primitives/command/command-loading.svelte +7 -0
  100. package/dist/components/primitives/command/command-loading.svelte.d.ts +4 -0
  101. package/dist/components/primitives/command/command-separator.svelte +17 -0
  102. package/dist/components/primitives/command/command-separator.svelte.d.ts +4 -0
  103. package/dist/components/primitives/command/command-shortcut.svelte +23 -0
  104. package/dist/components/primitives/command/command-shortcut.svelte.d.ts +5 -0
  105. package/dist/components/primitives/command/command.svelte +28 -0
  106. package/dist/components/primitives/command/command.svelte.d.ts +8 -0
  107. package/dist/components/primitives/command/index.d.ts +12 -0
  108. package/dist/components/primitives/command/index.js +14 -0
  109. package/dist/components/primitives/context-menu/context-menu-content.svelte +1 -1
  110. package/dist/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
  111. package/dist/components/primitives/dialog/dialog-content.svelte +11 -3
  112. package/dist/components/primitives/dialog/dialog-content.svelte.d.ts +2 -0
  113. package/dist/components/primitives/dialog/dialog-overlay.svelte +1 -1
  114. package/dist/components/primitives/dialog/dialog-title.svelte +6 -2
  115. package/dist/components/primitives/dialog/dialog-title.svelte.d.ts +5 -1
  116. package/dist/components/primitives/drawer/Drawer.svelte +2 -2
  117. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
  118. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-group.svelte.d.ts +4 -0
  119. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +46 -0
  120. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +9 -0
  121. package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte +31 -0
  122. package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte.d.ts +10 -0
  123. package/dist/components/primitives/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
  124. package/dist/components/primitives/dropdown-menu/dropdown-menu-group-heading.svelte.d.ts +8 -0
  125. package/dist/components/primitives/dropdown-menu/dropdown-menu-group.svelte +7 -0
  126. package/dist/components/primitives/dropdown-menu/dropdown-menu-group.svelte.d.ts +4 -0
  127. package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte +27 -0
  128. package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte.d.ts +8 -0
  129. package/dist/components/primitives/dropdown-menu/dropdown-menu-label.svelte +24 -0
  130. package/dist/components/primitives/dropdown-menu/dropdown-menu-label.svelte.d.ts +8 -0
  131. package/dist/components/primitives/dropdown-menu/dropdown-menu-portal.svelte +7 -0
  132. package/dist/components/primitives/dropdown-menu/dropdown-menu-portal.svelte.d.ts +3 -0
  133. package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
  134. package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +4 -0
  135. package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +36 -0
  136. package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte.d.ts +4 -0
  137. package/dist/components/primitives/dropdown-menu/dropdown-menu-separator.svelte +17 -0
  138. package/dist/components/primitives/dropdown-menu/dropdown-menu-separator.svelte.d.ts +4 -0
  139. package/dist/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +23 -0
  140. package/dist/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte.d.ts +5 -0
  141. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +31 -0
  142. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +10 -0
  143. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
  144. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +7 -0
  145. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub.svelte +7 -0
  146. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub.svelte.d.ts +3 -0
  147. package/dist/components/primitives/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
  148. package/dist/components/primitives/dropdown-menu/dropdown-menu-trigger.svelte.d.ts +4 -0
  149. package/dist/components/primitives/dropdown-menu/dropdown-menu.svelte +7 -0
  150. package/dist/components/primitives/dropdown-menu/dropdown-menu.svelte.d.ts +3 -0
  151. package/dist/components/primitives/dropdown-menu/index.d.ts +18 -0
  152. package/dist/components/primitives/dropdown-menu/index.js +18 -0
  153. package/dist/components/primitives/{alert/alert-description.svelte → empty/empty-content.svelte} +3 -3
  154. package/dist/components/primitives/empty/empty-content.svelte.d.ts +5 -0
  155. package/dist/components/primitives/empty/empty-description.svelte +23 -0
  156. package/dist/components/primitives/{alert/alert-description.svelte.d.ts → empty/empty-description.svelte.d.ts} +4 -4
  157. package/dist/components/primitives/{alert/alert-title.svelte → empty/empty-header.svelte} +3 -3
  158. package/dist/components/primitives/empty/empty-header.svelte.d.ts +5 -0
  159. package/dist/components/primitives/empty/empty-media.svelte +41 -0
  160. package/dist/components/primitives/empty/empty-media.svelte.d.ts +26 -0
  161. package/dist/components/primitives/{card/card-action.svelte → empty/empty-title.svelte} +2 -2
  162. package/dist/components/primitives/{card/card-action.svelte.d.ts → empty/empty-title.svelte.d.ts} +3 -3
  163. package/dist/components/primitives/empty/empty.svelte +23 -0
  164. package/dist/components/primitives/empty/empty.svelte.d.ts +5 -0
  165. package/dist/components/primitives/empty/index.d.ts +7 -0
  166. package/dist/components/primitives/empty/index.js +9 -0
  167. package/dist/components/primitives/index.d.ts +10 -1
  168. package/dist/components/primitives/index.js +10 -1
  169. package/dist/components/primitives/input/input.svelte +4 -4
  170. package/dist/components/primitives/input-group/index.d.ts +7 -0
  171. package/dist/components/primitives/input-group/index.js +9 -0
  172. package/dist/components/primitives/input-group/input-group-addon.svelte +53 -0
  173. package/dist/components/primitives/input-group/input-group-addon.svelte.d.ts +32 -0
  174. package/dist/components/primitives/input-group/input-group-button.svelte +49 -0
  175. package/dist/components/primitives/input-group/input-group-button.svelte.d.ts +32 -0
  176. package/dist/components/primitives/input-group/input-group-input.svelte +25 -0
  177. package/dist/components/primitives/input-group/input-group-input.svelte.d.ts +11 -0
  178. package/dist/components/primitives/input-group/input-group-text.svelte +22 -0
  179. package/dist/components/primitives/input-group/input-group-text.svelte.d.ts +5 -0
  180. package/dist/components/primitives/input-group/input-group-textarea.svelte +23 -0
  181. package/dist/components/primitives/input-group/input-group-textarea.svelte.d.ts +3 -0
  182. package/dist/components/primitives/input-group/input-group.svelte +24 -0
  183. package/dist/components/primitives/{alert/alert-title.svelte.d.ts → input-group/input-group.svelte.d.ts} +4 -4
  184. package/dist/components/primitives/mode-toggle/mode-toggle.svelte +6 -7
  185. package/dist/components/primitives/popover/index.d.ts +9 -0
  186. package/dist/components/primitives/popover/index.js +11 -0
  187. package/dist/components/primitives/popover/popover-close.svelte +7 -0
  188. package/dist/components/primitives/popover/popover-close.svelte.d.ts +4 -0
  189. package/dist/components/primitives/popover/popover-content.svelte +31 -0
  190. package/dist/components/primitives/popover/popover-content.svelte.d.ts +10 -0
  191. package/dist/components/primitives/popover/popover-description.svelte +20 -0
  192. package/dist/components/primitives/popover/popover-description.svelte.d.ts +5 -0
  193. package/dist/components/primitives/popover/popover-header.svelte +20 -0
  194. package/dist/components/primitives/popover/popover-header.svelte.d.ts +5 -0
  195. package/dist/components/primitives/popover/popover-portal.svelte +7 -0
  196. package/dist/components/primitives/popover/popover-portal.svelte.d.ts +3 -0
  197. package/dist/components/primitives/popover/popover-title.svelte +15 -0
  198. package/dist/components/primitives/popover/popover-title.svelte.d.ts +5 -0
  199. package/dist/components/primitives/popover/popover-trigger.svelte +17 -0
  200. package/dist/components/primitives/popover/popover-trigger.svelte.d.ts +4 -0
  201. package/dist/components/primitives/popover/popover.svelte +7 -0
  202. package/dist/components/primitives/popover/popover.svelte.d.ts +3 -0
  203. package/dist/components/primitives/resizable/resizable-handle.svelte +6 -2
  204. package/dist/components/primitives/resizable/resizable-handle.svelte.d.ts +2 -0
  205. package/dist/components/primitives/resizable/resizable-pane-group.svelte +1 -4
  206. package/dist/components/primitives/scroll-area/scroll-area.svelte +1 -1
  207. package/dist/components/primitives/search/search.svelte +3 -3
  208. package/dist/components/primitives/select/select-content.svelte +1 -1
  209. package/dist/components/primitives/select/select-trigger.svelte +1 -1
  210. package/dist/components/primitives/severity.d.ts +7 -0
  211. package/dist/components/primitives/severity.js +19 -0
  212. package/dist/components/primitives/slider/slider.svelte +8 -3
  213. package/dist/components/primitives/slider/slider.svelte.d.ts +5 -1
  214. package/dist/components/primitives/sonner/sonner.svelte +1 -1
  215. package/dist/components/primitives/spinner/index.d.ts +1 -0
  216. package/dist/components/primitives/spinner/index.js +1 -0
  217. package/dist/components/primitives/spinner/spinner.svelte +29 -0
  218. package/dist/components/primitives/spinner/spinner.svelte.d.ts +4 -0
  219. package/dist/components/primitives/switch/switch.svelte +2 -2
  220. package/dist/components/primitives/tabs/tabs-list.svelte +27 -5
  221. package/dist/components/primitives/tabs/tabs-list.svelte.d.ts +22 -1
  222. package/dist/components/primitives/tabs/tabs-trigger.svelte +23 -5
  223. package/dist/components/primitives/tabs/tabs-trigger.svelte.d.ts +22 -1
  224. package/dist/components/primitives/tabs/tabs.svelte +6 -2
  225. package/dist/components/primitives/tabs/tabs.svelte.d.ts +5 -1
  226. package/dist/components/primitives/textarea/textarea.svelte +1 -1
  227. package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte +1 -1
  228. package/dist/components/primitives/toggle/index.d.ts +3 -0
  229. package/dist/components/primitives/toggle/index.js +5 -0
  230. package/dist/components/primitives/toggle/toggle.svelte +54 -0
  231. package/dist/components/primitives/toggle/toggle.svelte.d.ts +46 -0
  232. package/dist/components/primitives/toggle-group/index.d.ts +3 -0
  233. package/dist/components/primitives/toggle-group/index.js +5 -0
  234. package/dist/components/primitives/toggle-group/toggle-group-item.svelte +35 -0
  235. package/dist/components/primitives/toggle-group/toggle-group-item.svelte.d.ts +6 -0
  236. package/dist/components/primitives/toggle-group/toggle-group.svelte +75 -0
  237. package/dist/components/primitives/toggle-group/toggle-group.svelte.d.ts +17 -0
  238. package/dist/components/viewer/MeshMetadataPanel.svelte +119 -0
  239. package/dist/components/viewer/MeshMetadataPanel.svelte.d.ts +9 -0
  240. package/dist/components/viewer/SceneManager.svelte +14 -5
  241. package/dist/components/viewer/Viewer.svelte +243 -221
  242. package/dist/components/viewer/Viewer.svelte.d.ts +3 -0
  243. package/dist/compute/run-panel-action.d.ts +8 -0
  244. package/dist/compute/run-panel-action.js +12 -0
  245. package/dist/compute/solving.svelte.d.ts +11 -7
  246. package/dist/compute/solving.svelte.js +64 -45
  247. package/dist/compute/useSolveSession.svelte.js +3 -0
  248. package/dist/constants.d.ts +6 -8
  249. package/dist/constants.js +7 -9
  250. package/dist/contexts/hostContext.svelte.d.ts +39 -0
  251. package/dist/contexts/hostContext.svelte.js +9 -0
  252. package/dist/i18n/localeContext.svelte.d.ts +10 -3
  253. package/dist/i18n/localeContext.svelte.js +27 -5
  254. package/dist/i18n/messages.d.ts +150 -2
  255. package/dist/i18n/messages.js +261 -11
  256. package/dist/index.d.ts +4 -1
  257. package/dist/index.js +3 -0
  258. package/dist/public.d.ts +1 -1
  259. package/dist/schema/host-support.d.ts +29 -0
  260. package/dist/schema/host-support.js +97 -0
  261. package/dist/schema/option-display.d.ts +12 -0
  262. package/dist/schema/option-display.js +29 -0
  263. package/dist/schema/param-exporter.d.ts +4 -1
  264. package/dist/schema/param-exporter.js +10 -6
  265. package/dist/schema/visibility-rules.js +21 -0
  266. package/dist/styles/base.css +80 -10
  267. package/dist/types/actionButton.d.ts +17 -3
  268. package/dist/types/presetLabels.d.ts +3 -2
  269. package/dist/types/presetLabels.js +9 -8
  270. package/dist/utils/file-download.js +10 -22
  271. package/dist/utils/host-files.d.ts +12 -0
  272. package/dist/utils/host-files.js +46 -0
  273. package/dist/utils/loadScript.d.ts +2 -0
  274. package/dist/utils/loadScript.js +2 -0
  275. package/dist/utils/webp-to-png.d.ts +10 -0
  276. package/dist/utils/webp-to-png.js +41 -0
  277. package/package.json +19 -15
  278. package/src/lib/components/ConfirmDialog.svelte +2 -10
  279. package/src/lib/components/ErrorScreen.svelte +21 -27
  280. package/src/lib/components/compute/AppLayout.svelte +298 -128
  281. package/src/lib/components/compute/CollapsedPanelStrip.svelte +4 -2
  282. package/src/lib/components/compute/ComputeApp.svelte +45 -24
  283. package/src/lib/components/compute/ComputeMessagesDialog.svelte +47 -83
  284. package/src/lib/components/compute/ParameterPresetManager.svelte +37 -130
  285. package/src/lib/components/compute/SolveMessages.svelte +131 -77
  286. package/src/lib/components/layout/AppShell.svelte +10 -6
  287. package/src/lib/components/layout/PageFooter.svelte +23 -11
  288. package/src/lib/components/layout/PageHeader.svelte +11 -7
  289. package/src/lib/components/layout/Pagination.svelte +2 -4
  290. package/src/lib/components/layout/SectionHeader.svelte +4 -2
  291. package/src/lib/components/layout/SideNav.svelte +56 -7
  292. package/src/lib/components/preview/ChartOutput.svelte +91 -48
  293. package/src/lib/components/preview/Group.svelte +92 -103
  294. package/src/lib/components/preview/HelpButton.svelte +36 -0
  295. package/src/lib/components/preview/ImageOutput.svelte +434 -72
  296. package/src/lib/components/preview/InputControl.svelte +163 -90
  297. package/src/lib/components/preview/OutputDisplay.svelte +44 -42
  298. package/src/lib/components/preview/TabBar.svelte +106 -22
  299. package/src/lib/components/preview/TabContent.svelte +63 -57
  300. package/src/lib/components/preview/TabLayout.svelte +27 -5
  301. package/src/lib/components/preview/inputs/CheckboxInput.svelte +7 -7
  302. package/src/lib/components/preview/inputs/ChecklistInput.svelte +7 -2
  303. package/src/lib/components/preview/inputs/ColorInput.svelte +4 -2
  304. package/src/lib/components/preview/inputs/DropdownInput.svelte +19 -4
  305. package/src/lib/components/preview/inputs/FileInput.svelte +112 -108
  306. package/src/lib/components/preview/inputs/GeometryInput.svelte +128 -0
  307. package/src/lib/components/preview/inputs/NumberInput.svelte +123 -61
  308. package/src/lib/components/preview/inputs/OptionGlyph.svelte +29 -0
  309. package/src/lib/components/preview/inputs/SegmentedInput.svelte +44 -0
  310. package/src/lib/components/preview/inputs/TextInput.svelte +8 -4
  311. package/src/lib/components/preview/inputs/TileInput.svelte +80 -0
  312. package/src/lib/components/preview/inputs/index.ts +3 -0
  313. package/src/lib/components/primitives/CalculateButton.svelte +56 -24
  314. package/src/lib/components/primitives/Callout.svelte +11 -18
  315. package/src/lib/components/primitives/DataTable.svelte +38 -5
  316. package/src/lib/components/primitives/FilterableDropdown.svelte +42 -129
  317. package/src/lib/components/primitives/IssueList.svelte +56 -0
  318. package/src/lib/components/primitives/SeverityIcon.svelte +15 -0
  319. package/src/lib/components/primitives/SolvingIndicator.svelte +43 -42
  320. package/src/lib/components/primitives/StateDisplay.svelte +19 -79
  321. package/src/lib/components/primitives/ViewToggle.svelte +18 -33
  322. package/src/lib/components/primitives/alert-dialog/alert-dialog-action.svelte +9 -3
  323. package/src/lib/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
  324. package/src/lib/components/primitives/alert-dialog/alert-dialog-overlay.svelte +1 -1
  325. package/src/lib/components/primitives/badge/badge.svelte +2 -2
  326. package/src/lib/components/primitives/button/button.svelte +6 -2
  327. package/src/lib/components/primitives/card/card-header.svelte +1 -1
  328. package/src/lib/components/primitives/card/card.svelte +21 -5
  329. package/src/lib/components/primitives/card/index.ts +1 -4
  330. package/src/lib/components/primitives/checkbox/checkbox.svelte +1 -1
  331. package/src/lib/components/primitives/command/command-dialog.svelte +42 -0
  332. package/src/lib/components/primitives/command/command-empty.svelte +17 -0
  333. package/src/lib/components/primitives/command/command-group.svelte +33 -0
  334. package/src/lib/components/primitives/command/command-input.svelte +36 -0
  335. package/src/lib/components/primitives/command/command-item.svelte +28 -0
  336. package/src/lib/components/primitives/command/command-link-item.svelte +21 -0
  337. package/src/lib/components/primitives/command/command-list.svelte +20 -0
  338. package/src/lib/components/primitives/command/command-loading.svelte +7 -0
  339. package/src/lib/components/primitives/command/command-separator.svelte +17 -0
  340. package/src/lib/components/primitives/command/command-shortcut.svelte +23 -0
  341. package/src/lib/components/primitives/command/command.svelte +28 -0
  342. package/src/lib/components/primitives/command/index.ts +37 -0
  343. package/src/lib/components/primitives/context-menu/context-menu-content.svelte +1 -1
  344. package/src/lib/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
  345. package/src/lib/components/primitives/dialog/dialog-content.svelte +11 -3
  346. package/src/lib/components/primitives/dialog/dialog-overlay.svelte +1 -1
  347. package/src/lib/components/primitives/dialog/dialog-title.svelte +6 -2
  348. package/src/lib/components/primitives/drawer/Drawer.svelte +2 -2
  349. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
  350. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +46 -0
  351. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-content.svelte +31 -0
  352. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
  353. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-group.svelte +7 -0
  354. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-item.svelte +27 -0
  355. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-label.svelte +24 -0
  356. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-portal.svelte +7 -0
  357. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
  358. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +36 -0
  359. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-separator.svelte +17 -0
  360. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +23 -0
  361. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +31 -0
  362. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
  363. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub.svelte +7 -0
  364. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
  365. package/src/lib/components/primitives/dropdown-menu/dropdown-menu.svelte +7 -0
  366. package/src/lib/components/primitives/dropdown-menu/index.ts +54 -0
  367. package/src/lib/components/primitives/{alert/alert-description.svelte → empty/empty-content.svelte} +3 -3
  368. package/src/lib/components/primitives/empty/empty-description.svelte +23 -0
  369. package/src/lib/components/primitives/{alert/alert-title.svelte → empty/empty-header.svelte} +3 -3
  370. package/src/lib/components/primitives/empty/empty-media.svelte +41 -0
  371. package/src/lib/components/primitives/{card/card-action.svelte → empty/empty-title.svelte} +2 -2
  372. package/src/lib/components/primitives/empty/empty.svelte +23 -0
  373. package/src/lib/components/primitives/empty/index.ts +22 -0
  374. package/src/lib/components/primitives/index.ts +10 -1
  375. package/src/lib/components/primitives/input/input.svelte +4 -4
  376. package/src/lib/components/primitives/input-group/index.ts +22 -0
  377. package/src/lib/components/primitives/input-group/input-group-addon.svelte +53 -0
  378. package/src/lib/components/primitives/input-group/input-group-button.svelte +49 -0
  379. package/src/lib/components/primitives/input-group/input-group-input.svelte +25 -0
  380. package/src/lib/components/primitives/input-group/input-group-text.svelte +22 -0
  381. package/src/lib/components/primitives/input-group/input-group-textarea.svelte +23 -0
  382. package/src/lib/components/primitives/input-group/input-group.svelte +24 -0
  383. package/src/lib/components/primitives/mode-toggle/mode-toggle.svelte +6 -7
  384. package/src/lib/components/primitives/popover/index.ts +28 -0
  385. package/src/lib/components/primitives/popover/popover-close.svelte +7 -0
  386. package/src/lib/components/primitives/popover/popover-content.svelte +31 -0
  387. package/src/lib/components/primitives/popover/popover-description.svelte +20 -0
  388. package/src/lib/components/primitives/popover/popover-header.svelte +20 -0
  389. package/src/lib/components/primitives/popover/popover-portal.svelte +7 -0
  390. package/src/lib/components/primitives/popover/popover-title.svelte +15 -0
  391. package/src/lib/components/primitives/popover/popover-trigger.svelte +17 -0
  392. package/src/lib/components/primitives/popover/popover.svelte +7 -0
  393. package/src/lib/components/primitives/resizable/resizable-handle.svelte +6 -2
  394. package/src/lib/components/primitives/resizable/resizable-pane-group.svelte +1 -4
  395. package/src/lib/components/primitives/scroll-area/scroll-area.svelte +1 -1
  396. package/src/lib/components/primitives/search/search.svelte +3 -3
  397. package/src/lib/components/primitives/select/select-content.svelte +1 -1
  398. package/src/lib/components/primitives/select/select-trigger.svelte +1 -1
  399. package/src/lib/components/primitives/severity.ts +26 -0
  400. package/src/lib/components/primitives/slider/slider.svelte +8 -3
  401. package/src/lib/components/primitives/sonner/sonner.svelte +1 -1
  402. package/src/lib/components/primitives/spinner/index.ts +1 -0
  403. package/src/lib/components/primitives/spinner/spinner.svelte +29 -0
  404. package/src/lib/components/primitives/switch/switch.svelte +2 -2
  405. package/src/lib/components/primitives/tabs/tabs-list.svelte +27 -5
  406. package/src/lib/components/primitives/tabs/tabs-trigger.svelte +23 -5
  407. package/src/lib/components/primitives/tabs/tabs.svelte +6 -2
  408. package/src/lib/components/primitives/textarea/textarea.svelte +1 -1
  409. package/src/lib/components/primitives/theme-switcher/ThemeSwitcher.svelte +1 -1
  410. package/src/lib/components/primitives/toggle/index.ts +13 -0
  411. package/src/lib/components/primitives/toggle/toggle.svelte +54 -0
  412. package/src/lib/components/primitives/toggle-group/index.ts +10 -0
  413. package/src/lib/components/primitives/toggle-group/toggle-group-item.svelte +35 -0
  414. package/src/lib/components/primitives/toggle-group/toggle-group.svelte +75 -0
  415. package/src/lib/components/viewer/MeshMetadataPanel.svelte +119 -0
  416. package/src/lib/components/viewer/SceneManager.svelte +14 -5
  417. package/src/lib/components/viewer/Viewer.svelte +243 -221
  418. package/src/lib/compute/run-panel-action.ts +16 -0
  419. package/src/lib/compute/solving.svelte.ts +66 -50
  420. package/src/lib/compute/useSolveSession.svelte.ts +3 -0
  421. package/src/lib/constants.ts +7 -9
  422. package/src/lib/contexts/hostContext.svelte.ts +51 -0
  423. package/src/lib/i18n/localeContext.svelte.ts +40 -5
  424. package/src/lib/i18n/messages.ts +453 -13
  425. package/src/lib/index.ts +21 -0
  426. package/src/lib/public.ts +1 -0
  427. package/src/lib/schema/host-support.ts +129 -0
  428. package/src/lib/schema/option-display.ts +44 -0
  429. package/src/lib/schema/param-exporter.ts +10 -7
  430. package/src/lib/schema/visibility-rules.ts +23 -0
  431. package/src/lib/styles/base.css +80 -10
  432. package/src/lib/types/actionButton.ts +16 -3
  433. package/src/lib/types/presetLabels.ts +13 -11
  434. package/src/lib/utils/file-download.ts +11 -21
  435. package/src/lib/utils/host-files.ts +61 -0
  436. package/src/lib/utils/loadScript.ts +3 -0
  437. package/src/lib/utils/webp-to-png.ts +48 -0
  438. package/dist/components/primitives/alert/alert.svelte +0 -44
  439. package/dist/components/primitives/alert/alert.svelte.d.ts +0 -26
  440. package/dist/components/primitives/alert/index.d.ts +0 -5
  441. package/dist/components/primitives/alert/index.js +0 -7
  442. package/dist/components/viewer/MeshMetadataDialog.svelte +0 -126
  443. package/dist/components/viewer/MeshMetadataDialog.svelte.d.ts +0 -10
  444. package/src/lib/components/primitives/alert/alert.svelte +0 -44
  445. package/src/lib/components/primitives/alert/index.ts +0 -14
  446. package/src/lib/components/viewer/MeshMetadataDialog.svelte +0 -126
@@ -1,14 +1,16 @@
1
1
  <script lang="ts">
2
2
  import type { Component } from 'svelte';
3
- import { Search, ChevronDown, Check } from '@lucide/svelte';
3
+ import { ChevronDown } from '@lucide/svelte';
4
4
  import { cn } from '$lib/utils.js';
5
+ import { buttonVariants } from './button';
6
+ import * as Popover from './popover';
7
+ import * as Command from './command';
5
8
 
6
9
  export interface FilterableDropdownItem {
7
10
  id: string;
8
11
  label: string;
9
12
  icon?: Component;
10
13
  iconClass?: string;
11
- iconStyle?: string;
12
14
  }
13
15
 
14
16
  interface Props {
@@ -19,6 +21,7 @@
19
21
  placeholder?: string;
20
22
  triggerIcon?: Component;
21
23
  searchPlaceholder?: string;
24
+ /** Above this many items the list gets a filter box. */
22
25
  searchThreshold?: number;
23
26
  disabled?: boolean;
24
27
  class?: string;
@@ -38,149 +41,59 @@
38
41
  }: Props = $props();
39
42
 
40
43
  let open = $state(false);
41
- let query = $state('');
42
- let highlighted = $state(0);
43
- let inputRef = $state<HTMLInputElement>();
44
- let containerRef = $state<HTMLDivElement>();
45
44
 
46
45
  const selected = $derived(items.find((item) => item.id === value) ?? null);
47
- const showSearch = $derived(items.length > searchThreshold);
48
-
49
- const matches = $derived.by(() => {
50
- const q = query.trim().toLowerCase();
51
- if (!q) return items;
52
- return items.filter((item) => item.label.toLowerCase().includes(q));
53
- });
54
-
55
- $effect(() => {
56
- void matches;
57
- highlighted = 0;
58
- });
59
-
60
- $effect(() => {
61
- if (open) {
62
- queueMicrotask(() => inputRef?.focus());
63
- } else {
64
- query = '';
65
- }
66
- });
46
+ const SelectedIcon = $derived(selected?.icon ?? TriggerIcon);
67
47
 
68
48
  function pick(item: FilterableDropdownItem) {
69
49
  onChange(item.id);
70
50
  open = false;
71
51
  }
72
-
73
- function handleKey(e: KeyboardEvent) {
74
- if (e.key === 'ArrowDown') {
75
- e.preventDefault();
76
- highlighted = Math.min(highlighted + 1, matches.length - 1);
77
- } else if (e.key === 'ArrowUp') {
78
- e.preventDefault();
79
- highlighted = Math.max(highlighted - 1, 0);
80
- } else if (e.key === 'Enter') {
81
- e.preventDefault();
82
- const m = matches[highlighted];
83
- if (m) pick(m);
84
- } else if (e.key === 'Escape') {
85
- e.preventDefault();
86
- open = false;
87
- }
88
- }
89
-
90
- function handleDocClick(e: MouseEvent) {
91
- if (!open) return;
92
- if (containerRef && !containerRef.contains(e.target as Node)) open = false;
93
- }
94
-
95
- $effect(() => {
96
- if (!open) return;
97
- document.addEventListener('mousedown', handleDocClick);
98
- return () => document.removeEventListener('mousedown', handleDocClick);
99
- });
100
-
101
- const SelectedIcon = $derived(selected?.icon);
102
52
  </script>
103
53
 
104
- <div bind:this={containerRef} class={cn('relative', className)}>
105
- <button
106
- type="button"
54
+ <Popover.Root bind:open>
55
+ <Popover.Trigger
107
56
  {id}
108
57
  {disabled}
109
- onclick={() => (open = !open)}
58
+ role="combobox"
59
+ aria-expanded={open}
110
60
  class={cn(
111
- 'h-10 gap-2 px-3 text-sm flex w-full items-center rounded-md border bg-background text-left transition-colors disabled:cursor-not-allowed disabled:opacity-50',
112
- open ? 'border-ring ring-2 ring-ring/30' : 'border-input hover:bg-muted/40'
61
+ buttonVariants({ variant: 'outline' }),
62
+ 'font-normal w-full justify-start',
63
+ className
113
64
  )}
114
65
  >
115
66
  {#if SelectedIcon}
116
- <SelectedIcon
117
- class={cn('h-3.5 w-3.5 shrink-0', selected?.iconClass ?? 'text-muted-foreground')}
118
- style={selected?.iconStyle}
119
- />
120
- {:else if TriggerIcon}
121
- <TriggerIcon class="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
67
+ <SelectedIcon class={cn('size-3.5', selected?.iconClass ?? 'text-muted-foreground')} />
122
68
  {/if}
123
- <span class={cn('min-w-0 flex-1 truncate', selected ? '' : 'text-muted-foreground')}>
69
+ <span class={cn('min-w-0 flex-1 truncate text-left', !selected && 'text-muted-foreground')}>
124
70
  {selected ? selected.label : placeholder}
125
71
  </span>
126
- <ChevronDown
127
- class={cn(
128
- 'h-3.5 w-3.5 shrink-0 text-muted-foreground transition-transform',
129
- open ? 'rotate-180' : ''
130
- )}
131
- />
132
- </button>
133
-
134
- {#if open}
135
- <div
136
- class="right-0 left-0 mt-1 shadow-md absolute top-full z-50 overflow-hidden rounded-md border border-border bg-popover"
137
- >
138
- {#if showSearch}
139
- <div class="relative border-b border-border">
140
- <Search
141
- class="left-3 h-3.5 w-3.5 pointer-events-none absolute top-1/2 -translate-y-1/2 text-muted-foreground"
142
- />
143
- <input
144
- bind:this={inputRef}
145
- bind:value={query}
146
- onkeydown={handleKey}
147
- placeholder={searchPlaceholder}
148
- class="h-8 pr-3 pl-9 text-sm w-full bg-transparent outline-none placeholder:text-muted-foreground"
149
- />
150
- </div>
72
+ <ChevronDown class="size-3.5 text-muted-foreground" />
73
+ </Popover.Trigger>
74
+ <Popover.Content align="start" class="p-0 w-(--bits-popover-anchor-width)">
75
+ <Command.Root>
76
+ {#if items.length > searchThreshold}
77
+ <Command.Input placeholder={searchPlaceholder} />
151
78
  {/if}
152
-
153
- <div class="max-h-60 overflow-y-auto">
154
- {#if matches.length === 0}
155
- <p class="px-3 py-3 text-xs text-center text-muted-foreground">
156
- No matches for "{query}"
157
- </p>
158
- {:else}
159
- {#each matches as item, i (item.id)}
160
- {@const ItemIcon = item.icon}
161
- <button
162
- type="button"
163
- onclick={() => pick(item)}
164
- onmouseenter={() => (highlighted = i)}
165
- class={cn(
166
- 'gap-2 px-3 py-1.5 text-sm flex w-full items-center text-left transition-colors',
167
- highlighted === i ? 'bg-accent text-accent-foreground' : 'hover:bg-muted/60'
168
- )}
169
- >
170
- {#if ItemIcon}
171
- <ItemIcon
172
- class={cn('h-3.5 w-3.5 shrink-0', item.iconClass ?? 'text-muted-foreground')}
173
- style={item.iconStyle}
174
- />
175
- {/if}
176
- <span class="flex-1 truncate">{item.label}</span>
177
- {#if item.id === value}
178
- <Check class="h-3.5 w-3.5 shrink-0 text-primary" />
179
- {/if}
180
- </button>
181
- {/each}
182
- {/if}
183
- </div>
184
- </div>
185
- {/if}
186
- </div>
79
+ <Command.List>
80
+ <Command.Empty>No matches.</Command.Empty>
81
+ {#each items as item (item.id)}
82
+ {@const ItemIcon = item.icon}
83
+ <!-- Filter on the label; the id is only the key. -->
84
+ <Command.Item
85
+ value={item.id}
86
+ keywords={[item.label]}
87
+ data-checked={item.id === value}
88
+ onSelect={() => pick(item)}
89
+ >
90
+ {#if ItemIcon}
91
+ <ItemIcon class={cn('size-3.5', item.iconClass ?? 'text-muted-foreground')} />
92
+ {/if}
93
+ <span class="truncate">{item.label}</span>
94
+ </Command.Item>
95
+ {/each}
96
+ </Command.List>
97
+ </Command.Root>
98
+ </Popover.Content>
99
+ </Popover.Root>
@@ -0,0 +1,56 @@
1
+ <script lang="ts" module>
2
+ import type { Severity } from './severity';
3
+
4
+ export interface Issue {
5
+ severity: Severity;
6
+ message: string;
7
+ /** A second, quieter line: expected vs actual, a path, a hint. */
8
+ detail?: string;
9
+ /** What raised it, such as the component's nickname. */
10
+ source?: string;
11
+ /** How many times the same message came in; shown as ×n above 1. */
12
+ count?: number;
13
+ }
14
+ </script>
15
+
16
+ <script lang="ts">
17
+ import { cn } from '$lib/utils.js';
18
+ import SeverityIcon from './SeverityIcon.svelte';
19
+
20
+ interface Props {
21
+ issues: readonly Issue[];
22
+ /** `boxed` draws a bordered, divided list; `plain` is for surfaces that already have a frame. */
23
+ variant?: 'boxed' | 'plain';
24
+ class?: string;
25
+ }
26
+
27
+ let { issues, variant = 'boxed', class: className }: Props = $props();
28
+ </script>
29
+
30
+ <ul
31
+ class={cn(
32
+ 'text-sm',
33
+ variant === 'boxed' ? 'divide-y rounded-lg border' : 'gap-2 flex flex-col',
34
+ className
35
+ )}
36
+ >
37
+ {#each issues as issue, i (i)}
38
+ <li class={cn('gap-2 flex items-start', variant === 'boxed' && 'px-3 py-2')}>
39
+ <SeverityIcon severity={issue.severity} class="mt-0.5" />
40
+ <div class="min-w-0 flex-1">
41
+ <p class="wrap-anywhere">
42
+ {issue.message}
43
+ {#if issue.count && issue.count > 1}
44
+ <span class="ml-1 text-xs text-muted-foreground tabular-nums">×{issue.count}</span>
45
+ {/if}
46
+ </p>
47
+ {#if issue.source}
48
+ <p class="text-xs text-muted-foreground">{issue.source}</p>
49
+ {/if}
50
+ {#if issue.detail}
51
+ <p class="mt-0.5 text-xs wrap-anywhere text-muted-foreground">{issue.detail}</p>
52
+ {/if}
53
+ </div>
54
+ </li>
55
+ {/each}
56
+ </ul>
@@ -0,0 +1,15 @@
1
+ <script lang="ts">
2
+ import { cn } from '$lib/utils.js';
3
+ import { SEVERITY_ICON, SEVERITY_TEXT, type Severity } from './severity';
4
+
5
+ interface Props {
6
+ severity: Severity;
7
+ class?: string;
8
+ }
9
+
10
+ let { severity, class: className }: Props = $props();
11
+
12
+ const Icon = $derived(SEVERITY_ICON[severity]);
13
+ </script>
14
+
15
+ <Icon class={cn('size-4 shrink-0', SEVERITY_TEXT[severity], className)} aria-hidden="true" />
@@ -3,57 +3,58 @@
3
3
 
4
4
  interface Props {
5
5
  show: boolean;
6
+ /**
7
+ * `floating` overlays the bottom-left corner. `inline` is a compact chip the size of an
8
+ * icon button, for a narrow host whose corner holds its content and whose action row
9
+ * already reserves the chip's place. Both say Esc aborts, as every host does.
10
+ */
11
+ placement?: 'floating' | 'inline';
6
12
  }
7
13
 
8
- let { show }: Props = $props();
14
+ let { show, placement = 'floating' }: Props = $props();
9
15
 
10
16
  const locale = getLocaleContext();
11
17
  const t = $derived(locale.messages);
12
18
  </script>
13
19
 
14
- {#if show}
15
- <div
16
- class="bottom-6 left-6 gap-3 px-5 py-3 shadow-xl fixed z-50 flex animate-[selva-slideInLeft_0.2s_ease-out] items-center rounded-lg border border-primary/20 bg-primary text-primary-foreground"
17
- >
18
- <div class="h-5 w-5 relative flex shrink-0 items-center justify-center">
19
- <div
20
- class="animate-ping absolute h-full w-full rounded-full bg-primary-foreground opacity-30"
21
- ></div>
20
+ <!-- The live region stays mounted: a screen reader only announces text that changes inside a
21
+ region it already knows about, so one created together with its text says nothing. -->
22
+ <div
23
+ role="status"
24
+ aria-live="polite"
25
+ aria-atomic="true"
26
+ class={placement === 'inline' ? 'h-10 gap-3 min-w-0 flex items-center' : undefined}
27
+ >
28
+ {#if show && placement === 'inline'}
29
+ <div
30
+ class="gap-2 px-3 h-10 text-sm font-semibold flex shrink-0 items-center rounded-md bg-primary text-primary-foreground"
31
+ >
22
32
  <div
23
33
  class="h-3 w-3 animate-spin rounded-full border-2 border-primary-foreground border-t-transparent"
34
+ aria-hidden="true"
24
35
  ></div>
36
+ {t.solvingEllipsis}
25
37
  </div>
26
- <div class="leading-tight flex flex-col">
27
- <span class="text-sm font-semibold">{t.solving}</span>
28
- <span class="text-xs opacity-70">{t.solvingSubtitle}</span>
38
+ <span class="text-xs min-w-0 truncate text-muted-foreground" data-testid="solve-esc-hint">
39
+ {t.solveMessagesEscHint}
40
+ </span>
41
+ {:else if show}
42
+ <div
43
+ class="bottom-6 left-6 gap-3 px-5 py-3 shadow-xl animate-in fade-in slide-in-from-left fixed z-50 flex items-center rounded-lg border border-primary/20 bg-primary text-primary-foreground duration-200"
44
+ >
45
+ <div class="h-5 w-5 relative flex shrink-0 items-center justify-center" aria-hidden="true">
46
+ <div
47
+ class="animate-ping absolute h-full w-full rounded-full bg-primary-foreground opacity-30"
48
+ ></div>
49
+ <div
50
+ class="h-3 w-3 animate-spin rounded-full border-2 border-primary-foreground border-t-transparent"
51
+ ></div>
52
+ </div>
53
+ <div class="leading-tight flex flex-col">
54
+ <span class="text-sm font-semibold">{t.solving}</span>
55
+ <span class="text-xs opacity-70" data-testid="solve-esc-hint">{t.solveMessagesEscHint}</span
56
+ >
57
+ </div>
29
58
  </div>
30
- </div>
31
- {/if}
32
-
33
- <style>
34
- @keyframes selva-slideInLeft {
35
- from {
36
- transform: translateX(-110%);
37
- opacity: 0;
38
- }
39
- to {
40
- transform: translateX(0);
41
- opacity: 1;
42
- }
43
- }
44
-
45
- @keyframes selva-sweep {
46
- 0% {
47
- width: 0%;
48
- margin-left: 0%;
49
- }
50
- 50% {
51
- width: 60%;
52
- margin-left: 20%;
53
- }
54
- 100% {
55
- width: 0%;
56
- margin-left: 100%;
57
- }
58
- }
59
- </style>
59
+ {/if}
60
+ </div>
@@ -1,6 +1,9 @@
1
1
  <script lang="ts">
2
- import { Loader, AlertCircle, AlertTriangle, Inbox } from '@lucide/svelte';
3
- import * as Card from '$lib/components/primitives/card';
2
+ import { Inbox } from '@lucide/svelte';
3
+ import { cn } from '$lib/utils.js';
4
+ import * as Empty from './empty';
5
+ import { Spinner } from './spinner';
6
+ import SeverityIcon from './SeverityIcon.svelte';
4
7
 
5
8
  interface StateDisplayProps {
6
9
  type: 'loading' | 'error' | 'warning' | 'empty';
@@ -18,89 +21,26 @@
18
21
  class: className = ''
19
22
  }: StateDisplayProps = $props();
20
23
 
21
- const sizeClasses = {
22
- small: {
23
- container: 'p-6 gap-3',
24
- icon: 'w-8 h-8',
25
- title: 'text-sm font-semibold',
26
- message: 'text-xs'
27
- },
28
- medium: {
29
- container: 'p-12 gap-4',
30
- icon: 'w-12 h-12',
31
- title: 'text-lg font-semibold',
32
- message: 'text-sm'
33
- },
34
- large: {
35
- container: 'p-16 gap-6',
36
- icon: 'w-16 h-16',
37
- title: 'text-2xl font-bold',
38
- message: 'text-base'
39
- }
40
- };
41
-
42
- /* Fully semantic, contrast-safe mappings */
43
- const typeClasses = {
44
- loading: {
45
- icon: 'text-primary',
46
- title: 'text-primary-foreground',
47
- message: 'text-primary-foreground/80',
48
- border: 'border-primary',
49
- background: 'bg-primary/15'
50
- },
51
- error: {
52
- icon: 'text-destructive',
53
- title: 'text-destructive-foreground',
54
- message: 'text-destructive-foreground/80',
55
- border: 'border-destructive',
56
- background: 'bg-destructive/15'
57
- },
58
- warning: {
59
- icon: 'text-accent',
60
- title: 'text-accent-foreground',
61
- message: 'text-accent-foreground/80',
62
- border: 'border-accent',
63
- background: 'bg-accent/15'
64
- },
65
- empty: {
66
- icon: 'text-neutral',
67
- title: 'text-neutral-foreground',
68
- message: 'text-neutral-foreground/80',
69
- border: 'border-neutral',
70
- background: 'bg-neutral/15'
71
- }
72
- };
73
-
74
- const sizeConfig = $derived(sizeClasses[size]);
75
- const typeConfig = $derived(typeClasses[type]);
24
+ // Size only changes the breathing room; the look comes from Empty and the severity tokens.
25
+ const PADDING = { small: 'p-4', medium: 'p-8', large: 'p-12' } as const;
76
26
  </script>
77
27
 
78
- <Card.Root class="rounded-lg border-2 {typeConfig.border} {typeConfig.background} {className}">
79
- <Card.Content
80
- class="flex flex-col items-center justify-center text-center {sizeConfig.container}"
81
- >
82
- <div class="{sizeConfig.icon} {typeConfig.icon}">
28
+ <Empty.Root class={cn(PADDING[size], className)}>
29
+ <Empty.Header>
30
+ <Empty.Media variant="icon">
83
31
  {#if type === 'loading'}
84
- <Loader class="animate-spin h-full w-full" />
85
- {:else if type === 'error'}
86
- <AlertCircle class="h-full w-full" />
87
- {:else if type === 'warning'}
88
- <AlertTriangle class="h-full w-full" />
32
+ <Spinner />
89
33
  {:else if type === 'empty'}
90
- <Inbox class="h-full w-full" />
34
+ <Inbox />
35
+ {:else}
36
+ <SeverityIcon severity={type} />
91
37
  {/if}
92
- </div>
93
-
38
+ </Empty.Media>
94
39
  {#if title}
95
- <h3 class="{sizeConfig.title} {typeConfig.title} mt-1">
96
- {title}
97
- </h3>
40
+ <Empty.Title>{title}</Empty.Title>
98
41
  {/if}
99
-
100
42
  {#if message}
101
- <p class="{sizeConfig.message} {typeConfig.message} max-w-md leading-relaxed">
102
- {message}
103
- </p>
43
+ <Empty.Description>{message}</Empty.Description>
104
44
  {/if}
105
- </Card.Content>
106
- </Card.Root>
45
+ </Empty.Header>
46
+ </Empty.Root>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { Grid2x2, List } from '@lucide/svelte';
3
+ import * as ToggleGroup from './toggle-group';
3
4
 
4
5
  type ViewMode = 'grid' | 'list';
5
6
 
@@ -10,38 +11,22 @@
10
11
  }
11
12
 
12
13
  let { mode, onChange, size = 'md' }: Props = $props();
13
-
14
- const btnClass = $derived(
15
- size === 'sm'
16
- ? 'flex h-7 w-7 items-center justify-center rounded-md transition-colors'
17
- : 'flex h-8 w-8 items-center justify-center rounded-md transition-colors'
18
- );
19
- const iconClass = $derived(size === 'sm' ? 'h-3.5 w-3.5' : 'h-4 w-4');
20
14
  </script>
21
15
 
22
- <div class="gap-0.5 p-0.5 inline-flex rounded-md border border-border bg-card">
23
- <button
24
- type="button"
25
- title="Grid view"
26
- aria-label="Grid view"
27
- aria-pressed={mode === 'grid'}
28
- onclick={() => onChange('grid')}
29
- class="{btnClass} {mode === 'grid'
30
- ? 'bg-muted text-foreground'
31
- : 'text-muted-foreground hover:text-foreground'}"
32
- >
33
- <Grid2x2 class={iconClass} />
34
- </button>
35
- <button
36
- type="button"
37
- title="List view"
38
- aria-label="List view"
39
- aria-pressed={mode === 'list'}
40
- onclick={() => onChange('list')}
41
- class="{btnClass} {mode === 'list'
42
- ? 'bg-muted text-foreground'
43
- : 'text-muted-foreground hover:text-foreground'}"
44
- >
45
- <List class={iconClass} />
46
- </button>
47
- </div>
16
+ <ToggleGroup.Root
17
+ type="single"
18
+ variant="outline"
19
+ size={size === 'sm' ? 'sm' : 'default'}
20
+ value={mode}
21
+ onValueChange={(next) => {
22
+ // A single-select group emits '' when the active item is clicked again; keep the mode.
23
+ if (next === 'grid' || next === 'list') onChange(next);
24
+ }}
25
+ >
26
+ <ToggleGroup.Item value="grid" aria-label="Grid view" title="Grid view">
27
+ <Grid2x2 />
28
+ </ToggleGroup.Item>
29
+ <ToggleGroup.Item value="list" aria-label="List view" title="List view">
30
+ <List />
31
+ </ToggleGroup.Item>
32
+ </ToggleGroup.Root>
@@ -1,18 +1,24 @@
1
1
  <script lang="ts">
2
2
  import { AlertDialog as AlertDialogPrimitive } from 'bits-ui';
3
- import { buttonVariants } from '$lib/components/primitives/button/index.js';
3
+ import {
4
+ buttonVariants,
5
+ type ButtonSize,
6
+ type ButtonVariant
7
+ } from '$lib/components/primitives/button/index.js';
4
8
  import { cn } from '$lib/utils.js';
5
9
 
6
10
  let {
7
11
  ref = $bindable(null),
8
12
  class: className,
13
+ variant = 'default',
14
+ size = 'default',
9
15
  ...restProps
10
- }: AlertDialogPrimitive.ActionProps = $props();
16
+ }: AlertDialogPrimitive.ActionProps & { variant?: ButtonVariant; size?: ButtonSize } = $props();
11
17
  </script>
12
18
 
13
19
  <AlertDialogPrimitive.Action
14
20
  bind:ref
15
21
  data-slot="alert-dialog-action"
16
- class={cn(buttonVariants(), className)}
22
+ class={cn(buttonVariants({ variant, size }), className)}
17
23
  {...restProps}
18
24
  />
@@ -19,7 +19,7 @@
19
19
  bind:ref
20
20
  data-slot="alert-dialog-content"
21
21
  class={cn(
22
- 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 gap-4 p-6 shadow-lg sm:max-w-lg fixed start-[50%] top-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] rounded-lg border bg-background duration-200',
22
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 gap-4 p-6 shadow-lg sm:max-w-lg fixed start-1/2 top-1/2 z-50 grid max-h-dialog w-screen-inset -translate-x-1/2 -translate-y-1/2 overflow-y-auto rounded-lg border bg-background duration-200',
23
23
  className
24
24
  )}
25
25
  {...restProps}
@@ -13,7 +13,7 @@
13
13
  bind:ref
14
14
  data-slot="alert-dialog-overlay"
15
15
  class={cn(
16
- 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 inset-0 bg-black/50 fixed z-50',
16
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 inset-0 fixed z-50 bg-overlay',
17
17
  className
18
18
  )}
19
19
  {...restProps}
@@ -2,14 +2,14 @@
2
2
  import { type VariantProps, tv } from 'tailwind-variants';
3
3
 
4
4
  export const badgeVariants = tv({
5
- base: 'focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] [&>svg]:pointer-events-none [&>svg]:size-3',
5
+ base: 'focus-visible:border-ring focus-visible:ring-ring aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border px-2 py-0.5 text-xs font-medium whitespace-nowrap transition focus-visible:ring-3 [&>svg]:pointer-events-none [&>svg]:size-3',
6
6
  variants: {
7
7
  variant: {
8
8
  default: 'bg-primary text-primary-foreground [a&]:hover:bg-primary/90 border-transparent',
9
9
  secondary:
10
10
  'bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90 border-transparent',
11
11
  destructive:
12
- 'bg-destructive [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/70 border-transparent text-white',
12
+ 'bg-destructive [a&]:hover:bg-destructive/90 dark:bg-destructive/70 border-transparent text-destructive-foreground',
13
13
  outline: 'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground'
14
14
  }
15
15
  },
@@ -4,14 +4,17 @@
4
4
  import { type VariantProps, tv } from 'tailwind-variants';
5
5
 
6
6
  export const buttonVariants = tv({
7
- base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium outline-none transition-all focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
7
+ base: "focus-visible:border-ring focus-visible:ring-ring aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium outline-none transition-all focus-visible:ring-3 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
8
8
  variants: {
9
9
  variant: {
10
10
  default: 'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',
11
11
  destructive:
12
- 'bg-destructive shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 text-white',
12
+ 'bg-destructive shadow-xs hover:bg-destructive/90 dark:bg-destructive/60 text-destructive-foreground',
13
13
  outline:
14
14
  'bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 border',
15
+ // Outline with an opaque dark fill: the translucent one washes out over the light 3D canvas.
16
+ overlay:
17
+ 'bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input border',
15
18
  secondary: 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
16
19
  ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
17
20
  dashed:
@@ -20,6 +23,7 @@
20
23
  },
21
24
  size: {
22
25
  default: 'h-9 px-4 py-2 has-[>svg]:px-3',
26
+ xs: 'h-7 gap-1 rounded-md px-3 text-xs has-[>svg]:px-2',
23
27
  sm: 'h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5',
24
28
  lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
25
29
  icon: 'size-9',