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

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 (444) 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 +286 -116
  4. package/dist/components/compute/AppLayout.svelte.d.ts +22 -0
  5. package/dist/components/compute/ComputeApp.svelte +45 -24
  6. package/dist/components/compute/ComputeApp.svelte.d.ts +19 -2
  7. package/dist/components/compute/ComputeMessagesDialog.svelte +47 -83
  8. package/dist/components/compute/ParameterPresetManager.svelte +37 -130
  9. package/dist/components/compute/ParameterPresetManager.svelte.d.ts +4 -5
  10. package/dist/components/compute/SolveMessages.svelte +131 -77
  11. package/dist/components/compute/SolveMessages.svelte.d.ts +7 -12
  12. package/dist/components/layout/AppShell.svelte +10 -6
  13. package/dist/components/layout/PageFooter.svelte +23 -11
  14. package/dist/components/layout/PageHeader.svelte +11 -7
  15. package/dist/components/layout/Pagination.svelte +2 -4
  16. package/dist/components/layout/SectionHeader.svelte +4 -2
  17. package/dist/components/layout/SideNav.svelte +56 -7
  18. package/dist/components/preview/ChartOutput.svelte +35 -25
  19. package/dist/components/preview/Group.svelte +92 -103
  20. package/dist/components/preview/Group.svelte.d.ts +1 -1
  21. package/dist/components/preview/HelpButton.svelte +36 -0
  22. package/dist/components/preview/HelpButton.svelte.d.ts +8 -0
  23. package/dist/components/preview/ImageOutput.svelte +430 -71
  24. package/dist/components/preview/InputControl.svelte +163 -90
  25. package/dist/components/preview/InputControl.svelte.d.ts +5 -1
  26. package/dist/components/preview/OutputDisplay.svelte +28 -33
  27. package/dist/components/preview/TabBar.svelte +106 -22
  28. package/dist/components/preview/TabBar.svelte.d.ts +1 -0
  29. package/dist/components/preview/TabContent.svelte +63 -57
  30. package/dist/components/preview/TabContent.svelte.d.ts +5 -1
  31. package/dist/components/preview/TabLayout.svelte +27 -5
  32. package/dist/components/preview/TabLayout.svelte.d.ts +5 -0
  33. package/dist/components/preview/inputs/CheckboxInput.svelte +7 -7
  34. package/dist/components/preview/inputs/CheckboxInput.svelte.d.ts +3 -0
  35. package/dist/components/preview/inputs/ChecklistInput.svelte +7 -2
  36. package/dist/components/preview/inputs/ChecklistInput.svelte.d.ts +2 -1
  37. package/dist/components/preview/inputs/ColorInput.svelte +4 -2
  38. package/dist/components/preview/inputs/ColorInput.svelte.d.ts +1 -0
  39. package/dist/components/preview/inputs/DropdownInput.svelte +19 -4
  40. package/dist/components/preview/inputs/DropdownInput.svelte.d.ts +2 -1
  41. package/dist/components/preview/inputs/FileInput.svelte +112 -108
  42. package/dist/components/preview/inputs/GeometryInput.svelte +128 -0
  43. package/dist/components/preview/inputs/GeometryInput.svelte.d.ts +21 -0
  44. package/dist/components/preview/inputs/NumberInput.svelte +123 -61
  45. package/dist/components/preview/inputs/NumberInput.svelte.d.ts +2 -0
  46. package/dist/components/preview/inputs/OptionGlyph.svelte +29 -0
  47. package/dist/components/preview/inputs/OptionGlyph.svelte.d.ts +8 -0
  48. package/dist/components/preview/inputs/SegmentedInput.svelte +44 -0
  49. package/dist/components/preview/inputs/SegmentedInput.svelte.d.ts +12 -0
  50. package/dist/components/preview/inputs/TextInput.svelte +8 -4
  51. package/dist/components/preview/inputs/TileInput.svelte +80 -0
  52. package/dist/components/preview/inputs/TileInput.svelte.d.ts +12 -0
  53. package/dist/components/preview/inputs/index.d.ts +3 -0
  54. package/dist/components/preview/inputs/index.js +3 -0
  55. package/dist/components/primitives/CalculateButton.svelte +56 -24
  56. package/dist/components/primitives/CalculateButton.svelte.d.ts +3 -0
  57. package/dist/components/primitives/Callout.svelte +11 -18
  58. package/dist/components/primitives/DataTable.svelte +38 -5
  59. package/dist/components/primitives/DataTable.svelte.d.ts +2 -0
  60. package/dist/components/primitives/FilterableDropdown.svelte +42 -129
  61. package/dist/components/primitives/FilterableDropdown.svelte.d.ts +1 -1
  62. package/dist/components/primitives/IssueList.svelte +56 -0
  63. package/dist/components/primitives/IssueList.svelte.d.ts +20 -0
  64. package/dist/components/primitives/SeverityIcon.svelte +15 -0
  65. package/dist/components/primitives/SeverityIcon.svelte.d.ts +8 -0
  66. package/dist/components/primitives/SolvingIndicator.svelte +43 -42
  67. package/dist/components/primitives/SolvingIndicator.svelte.d.ts +6 -0
  68. package/dist/components/primitives/StateDisplay.svelte +19 -79
  69. package/dist/components/primitives/ViewToggle.svelte +18 -33
  70. package/dist/components/primitives/alert-dialog/alert-dialog-action.svelte +9 -3
  71. package/dist/components/primitives/alert-dialog/alert-dialog-action.svelte.d.ts +6 -1
  72. package/dist/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
  73. package/dist/components/primitives/alert-dialog/alert-dialog-overlay.svelte +1 -1
  74. package/dist/components/primitives/badge/badge.svelte +2 -2
  75. package/dist/components/primitives/badge/badge.svelte.d.ts +4 -4
  76. package/dist/components/primitives/button/button.svelte +6 -2
  77. package/dist/components/primitives/button/button.svelte.d.ts +10 -4
  78. package/dist/components/primitives/card/card-header.svelte +1 -1
  79. package/dist/components/primitives/card/card.svelte +21 -5
  80. package/dist/components/primitives/card/card.svelte.d.ts +25 -1
  81. package/dist/components/primitives/card/index.d.ts +1 -2
  82. package/dist/components/primitives/card/index.js +2 -3
  83. package/dist/components/primitives/checkbox/checkbox.svelte +1 -1
  84. package/dist/components/primitives/command/command-dialog.svelte +42 -0
  85. package/dist/components/primitives/command/command-dialog.svelte.d.ts +14 -0
  86. package/dist/components/primitives/command/command-empty.svelte +17 -0
  87. package/dist/components/primitives/command/command-empty.svelte.d.ts +4 -0
  88. package/dist/components/primitives/command/command-group.svelte +33 -0
  89. package/dist/components/primitives/command/command-group.svelte.d.ts +7 -0
  90. package/dist/components/primitives/command/command-input.svelte +36 -0
  91. package/dist/components/primitives/command/command-input.svelte.d.ts +4 -0
  92. package/dist/components/primitives/command/command-item.svelte +28 -0
  93. package/dist/components/primitives/command/command-item.svelte.d.ts +4 -0
  94. package/dist/components/primitives/command/command-link-item.svelte +21 -0
  95. package/dist/components/primitives/command/command-link-item.svelte.d.ts +4 -0
  96. package/dist/components/primitives/command/command-list.svelte +20 -0
  97. package/dist/components/primitives/command/command-list.svelte.d.ts +4 -0
  98. package/dist/components/primitives/command/command-loading.svelte +7 -0
  99. package/dist/components/primitives/command/command-loading.svelte.d.ts +4 -0
  100. package/dist/components/primitives/command/command-separator.svelte +17 -0
  101. package/dist/components/primitives/command/command-separator.svelte.d.ts +4 -0
  102. package/dist/components/primitives/command/command-shortcut.svelte +23 -0
  103. package/dist/components/primitives/command/command-shortcut.svelte.d.ts +5 -0
  104. package/dist/components/primitives/command/command.svelte +28 -0
  105. package/dist/components/primitives/command/command.svelte.d.ts +8 -0
  106. package/dist/components/primitives/command/index.d.ts +12 -0
  107. package/dist/components/primitives/command/index.js +14 -0
  108. package/dist/components/primitives/context-menu/context-menu-content.svelte +1 -1
  109. package/dist/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
  110. package/dist/components/primitives/dialog/dialog-content.svelte +11 -3
  111. package/dist/components/primitives/dialog/dialog-content.svelte.d.ts +2 -0
  112. package/dist/components/primitives/dialog/dialog-overlay.svelte +1 -1
  113. package/dist/components/primitives/dialog/dialog-title.svelte +6 -2
  114. package/dist/components/primitives/dialog/dialog-title.svelte.d.ts +5 -1
  115. package/dist/components/primitives/drawer/Drawer.svelte +2 -2
  116. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
  117. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-group.svelte.d.ts +4 -0
  118. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +46 -0
  119. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +9 -0
  120. package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte +31 -0
  121. package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte.d.ts +10 -0
  122. package/dist/components/primitives/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
  123. package/dist/components/primitives/dropdown-menu/dropdown-menu-group-heading.svelte.d.ts +8 -0
  124. package/dist/components/primitives/dropdown-menu/dropdown-menu-group.svelte +7 -0
  125. package/dist/components/primitives/dropdown-menu/dropdown-menu-group.svelte.d.ts +4 -0
  126. package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte +27 -0
  127. package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte.d.ts +8 -0
  128. package/dist/components/primitives/dropdown-menu/dropdown-menu-label.svelte +24 -0
  129. package/dist/components/primitives/dropdown-menu/dropdown-menu-label.svelte.d.ts +8 -0
  130. package/dist/components/primitives/dropdown-menu/dropdown-menu-portal.svelte +7 -0
  131. package/dist/components/primitives/dropdown-menu/dropdown-menu-portal.svelte.d.ts +3 -0
  132. package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
  133. package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +4 -0
  134. package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +36 -0
  135. package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte.d.ts +4 -0
  136. package/dist/components/primitives/dropdown-menu/dropdown-menu-separator.svelte +17 -0
  137. package/dist/components/primitives/dropdown-menu/dropdown-menu-separator.svelte.d.ts +4 -0
  138. package/dist/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +23 -0
  139. package/dist/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte.d.ts +5 -0
  140. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +31 -0
  141. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +10 -0
  142. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
  143. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +7 -0
  144. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub.svelte +7 -0
  145. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub.svelte.d.ts +3 -0
  146. package/dist/components/primitives/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
  147. package/dist/components/primitives/dropdown-menu/dropdown-menu-trigger.svelte.d.ts +4 -0
  148. package/dist/components/primitives/dropdown-menu/dropdown-menu.svelte +7 -0
  149. package/dist/components/primitives/dropdown-menu/dropdown-menu.svelte.d.ts +3 -0
  150. package/dist/components/primitives/dropdown-menu/index.d.ts +18 -0
  151. package/dist/components/primitives/dropdown-menu/index.js +18 -0
  152. package/dist/components/primitives/{alert/alert-description.svelte → empty/empty-content.svelte} +3 -3
  153. package/dist/components/primitives/empty/empty-content.svelte.d.ts +5 -0
  154. package/dist/components/primitives/empty/empty-description.svelte +23 -0
  155. package/dist/components/primitives/{alert/alert-description.svelte.d.ts → empty/empty-description.svelte.d.ts} +4 -4
  156. package/dist/components/primitives/{alert/alert-title.svelte → empty/empty-header.svelte} +3 -3
  157. package/dist/components/primitives/empty/empty-header.svelte.d.ts +5 -0
  158. package/dist/components/primitives/empty/empty-media.svelte +41 -0
  159. package/dist/components/primitives/empty/empty-media.svelte.d.ts +26 -0
  160. package/dist/components/primitives/{card/card-action.svelte → empty/empty-title.svelte} +2 -2
  161. package/dist/components/primitives/{card/card-action.svelte.d.ts → empty/empty-title.svelte.d.ts} +3 -3
  162. package/dist/components/primitives/empty/empty.svelte +23 -0
  163. package/dist/components/primitives/empty/empty.svelte.d.ts +5 -0
  164. package/dist/components/primitives/empty/index.d.ts +7 -0
  165. package/dist/components/primitives/empty/index.js +9 -0
  166. package/dist/components/primitives/index.d.ts +10 -1
  167. package/dist/components/primitives/index.js +10 -1
  168. package/dist/components/primitives/input/input.svelte +4 -4
  169. package/dist/components/primitives/input-group/index.d.ts +7 -0
  170. package/dist/components/primitives/input-group/index.js +9 -0
  171. package/dist/components/primitives/input-group/input-group-addon.svelte +53 -0
  172. package/dist/components/primitives/input-group/input-group-addon.svelte.d.ts +32 -0
  173. package/dist/components/primitives/input-group/input-group-button.svelte +49 -0
  174. package/dist/components/primitives/input-group/input-group-button.svelte.d.ts +32 -0
  175. package/dist/components/primitives/input-group/input-group-input.svelte +25 -0
  176. package/dist/components/primitives/input-group/input-group-input.svelte.d.ts +11 -0
  177. package/dist/components/primitives/input-group/input-group-text.svelte +22 -0
  178. package/dist/components/primitives/input-group/input-group-text.svelte.d.ts +5 -0
  179. package/dist/components/primitives/input-group/input-group-textarea.svelte +23 -0
  180. package/dist/components/primitives/input-group/input-group-textarea.svelte.d.ts +3 -0
  181. package/dist/components/primitives/input-group/input-group.svelte +24 -0
  182. package/dist/components/primitives/{alert/alert-title.svelte.d.ts → input-group/input-group.svelte.d.ts} +4 -4
  183. package/dist/components/primitives/mode-toggle/mode-toggle.svelte +6 -7
  184. package/dist/components/primitives/popover/index.d.ts +9 -0
  185. package/dist/components/primitives/popover/index.js +11 -0
  186. package/dist/components/primitives/popover/popover-close.svelte +7 -0
  187. package/dist/components/primitives/popover/popover-close.svelte.d.ts +4 -0
  188. package/dist/components/primitives/popover/popover-content.svelte +31 -0
  189. package/dist/components/primitives/popover/popover-content.svelte.d.ts +10 -0
  190. package/dist/components/primitives/popover/popover-description.svelte +20 -0
  191. package/dist/components/primitives/popover/popover-description.svelte.d.ts +5 -0
  192. package/dist/components/primitives/popover/popover-header.svelte +20 -0
  193. package/dist/components/primitives/popover/popover-header.svelte.d.ts +5 -0
  194. package/dist/components/primitives/popover/popover-portal.svelte +7 -0
  195. package/dist/components/primitives/popover/popover-portal.svelte.d.ts +3 -0
  196. package/dist/components/primitives/popover/popover-title.svelte +15 -0
  197. package/dist/components/primitives/popover/popover-title.svelte.d.ts +5 -0
  198. package/dist/components/primitives/popover/popover-trigger.svelte +17 -0
  199. package/dist/components/primitives/popover/popover-trigger.svelte.d.ts +4 -0
  200. package/dist/components/primitives/popover/popover.svelte +7 -0
  201. package/dist/components/primitives/popover/popover.svelte.d.ts +3 -0
  202. package/dist/components/primitives/resizable/resizable-handle.svelte +6 -2
  203. package/dist/components/primitives/resizable/resizable-handle.svelte.d.ts +2 -0
  204. package/dist/components/primitives/resizable/resizable-pane-group.svelte +1 -4
  205. package/dist/components/primitives/scroll-area/scroll-area.svelte +1 -1
  206. package/dist/components/primitives/search/search.svelte +3 -3
  207. package/dist/components/primitives/select/select-content.svelte +1 -1
  208. package/dist/components/primitives/select/select-trigger.svelte +1 -1
  209. package/dist/components/primitives/severity.d.ts +7 -0
  210. package/dist/components/primitives/severity.js +19 -0
  211. package/dist/components/primitives/slider/slider.svelte +8 -3
  212. package/dist/components/primitives/slider/slider.svelte.d.ts +5 -1
  213. package/dist/components/primitives/sonner/sonner.svelte +1 -1
  214. package/dist/components/primitives/spinner/index.d.ts +1 -0
  215. package/dist/components/primitives/spinner/index.js +1 -0
  216. package/dist/components/primitives/spinner/spinner.svelte +29 -0
  217. package/dist/components/primitives/spinner/spinner.svelte.d.ts +4 -0
  218. package/dist/components/primitives/switch/switch.svelte +2 -2
  219. package/dist/components/primitives/tabs/tabs-list.svelte +27 -5
  220. package/dist/components/primitives/tabs/tabs-list.svelte.d.ts +22 -1
  221. package/dist/components/primitives/tabs/tabs-trigger.svelte +23 -5
  222. package/dist/components/primitives/tabs/tabs-trigger.svelte.d.ts +22 -1
  223. package/dist/components/primitives/tabs/tabs.svelte +6 -2
  224. package/dist/components/primitives/tabs/tabs.svelte.d.ts +5 -1
  225. package/dist/components/primitives/textarea/textarea.svelte +1 -1
  226. package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte +1 -1
  227. package/dist/components/primitives/toggle/index.d.ts +3 -0
  228. package/dist/components/primitives/toggle/index.js +5 -0
  229. package/dist/components/primitives/toggle/toggle.svelte +54 -0
  230. package/dist/components/primitives/toggle/toggle.svelte.d.ts +46 -0
  231. package/dist/components/primitives/toggle-group/index.d.ts +3 -0
  232. package/dist/components/primitives/toggle-group/index.js +5 -0
  233. package/dist/components/primitives/toggle-group/toggle-group-item.svelte +35 -0
  234. package/dist/components/primitives/toggle-group/toggle-group-item.svelte.d.ts +6 -0
  235. package/dist/components/primitives/toggle-group/toggle-group.svelte +75 -0
  236. package/dist/components/primitives/toggle-group/toggle-group.svelte.d.ts +17 -0
  237. package/dist/components/viewer/MeshMetadataPanel.svelte +119 -0
  238. package/dist/components/viewer/MeshMetadataPanel.svelte.d.ts +9 -0
  239. package/dist/components/viewer/SceneManager.svelte +14 -5
  240. package/dist/components/viewer/Viewer.svelte +243 -221
  241. package/dist/components/viewer/Viewer.svelte.d.ts +3 -0
  242. package/dist/compute/run-panel-action.d.ts +8 -0
  243. package/dist/compute/run-panel-action.js +12 -0
  244. package/dist/compute/solving.svelte.d.ts +11 -7
  245. package/dist/compute/solving.svelte.js +64 -45
  246. package/dist/compute/useSolveSession.svelte.js +3 -0
  247. package/dist/constants.d.ts +6 -8
  248. package/dist/constants.js +7 -9
  249. package/dist/contexts/hostContext.svelte.d.ts +39 -0
  250. package/dist/contexts/hostContext.svelte.js +9 -0
  251. package/dist/i18n/localeContext.svelte.d.ts +10 -3
  252. package/dist/i18n/localeContext.svelte.js +27 -5
  253. package/dist/i18n/messages.d.ts +150 -2
  254. package/dist/i18n/messages.js +261 -11
  255. package/dist/index.d.ts +4 -1
  256. package/dist/index.js +3 -0
  257. package/dist/public.d.ts +1 -1
  258. package/dist/schema/host-support.d.ts +29 -0
  259. package/dist/schema/host-support.js +97 -0
  260. package/dist/schema/option-display.d.ts +12 -0
  261. package/dist/schema/option-display.js +29 -0
  262. package/dist/schema/param-exporter.d.ts +4 -1
  263. package/dist/schema/param-exporter.js +10 -6
  264. package/dist/schema/visibility-rules.js +21 -0
  265. package/dist/styles/base.css +80 -10
  266. package/dist/types/actionButton.d.ts +17 -3
  267. package/dist/types/presetLabels.d.ts +3 -2
  268. package/dist/types/presetLabels.js +9 -8
  269. package/dist/utils/file-download.js +10 -22
  270. package/dist/utils/host-files.d.ts +12 -0
  271. package/dist/utils/host-files.js +46 -0
  272. package/dist/utils/loadScript.d.ts +2 -0
  273. package/dist/utils/loadScript.js +2 -0
  274. package/dist/utils/webp-to-png.d.ts +10 -0
  275. package/dist/utils/webp-to-png.js +41 -0
  276. package/package.json +14 -14
  277. package/src/lib/components/ConfirmDialog.svelte +2 -10
  278. package/src/lib/components/ErrorScreen.svelte +21 -27
  279. package/src/lib/components/compute/AppLayout.svelte +286 -116
  280. package/src/lib/components/compute/ComputeApp.svelte +45 -24
  281. package/src/lib/components/compute/ComputeMessagesDialog.svelte +47 -83
  282. package/src/lib/components/compute/ParameterPresetManager.svelte +37 -130
  283. package/src/lib/components/compute/SolveMessages.svelte +131 -77
  284. package/src/lib/components/layout/AppShell.svelte +10 -6
  285. package/src/lib/components/layout/PageFooter.svelte +23 -11
  286. package/src/lib/components/layout/PageHeader.svelte +11 -7
  287. package/src/lib/components/layout/Pagination.svelte +2 -4
  288. package/src/lib/components/layout/SectionHeader.svelte +4 -2
  289. package/src/lib/components/layout/SideNav.svelte +56 -7
  290. package/src/lib/components/preview/ChartOutput.svelte +35 -25
  291. package/src/lib/components/preview/Group.svelte +92 -103
  292. package/src/lib/components/preview/HelpButton.svelte +36 -0
  293. package/src/lib/components/preview/ImageOutput.svelte +430 -71
  294. package/src/lib/components/preview/InputControl.svelte +163 -90
  295. package/src/lib/components/preview/OutputDisplay.svelte +28 -33
  296. package/src/lib/components/preview/TabBar.svelte +106 -22
  297. package/src/lib/components/preview/TabContent.svelte +63 -57
  298. package/src/lib/components/preview/TabLayout.svelte +27 -5
  299. package/src/lib/components/preview/inputs/CheckboxInput.svelte +7 -7
  300. package/src/lib/components/preview/inputs/ChecklistInput.svelte +7 -2
  301. package/src/lib/components/preview/inputs/ColorInput.svelte +4 -2
  302. package/src/lib/components/preview/inputs/DropdownInput.svelte +19 -4
  303. package/src/lib/components/preview/inputs/FileInput.svelte +112 -108
  304. package/src/lib/components/preview/inputs/GeometryInput.svelte +128 -0
  305. package/src/lib/components/preview/inputs/NumberInput.svelte +123 -61
  306. package/src/lib/components/preview/inputs/OptionGlyph.svelte +29 -0
  307. package/src/lib/components/preview/inputs/SegmentedInput.svelte +44 -0
  308. package/src/lib/components/preview/inputs/TextInput.svelte +8 -4
  309. package/src/lib/components/preview/inputs/TileInput.svelte +80 -0
  310. package/src/lib/components/preview/inputs/index.ts +3 -0
  311. package/src/lib/components/primitives/CalculateButton.svelte +56 -24
  312. package/src/lib/components/primitives/Callout.svelte +11 -18
  313. package/src/lib/components/primitives/DataTable.svelte +38 -5
  314. package/src/lib/components/primitives/FilterableDropdown.svelte +42 -129
  315. package/src/lib/components/primitives/IssueList.svelte +56 -0
  316. package/src/lib/components/primitives/SeverityIcon.svelte +15 -0
  317. package/src/lib/components/primitives/SolvingIndicator.svelte +43 -42
  318. package/src/lib/components/primitives/StateDisplay.svelte +19 -79
  319. package/src/lib/components/primitives/ViewToggle.svelte +18 -33
  320. package/src/lib/components/primitives/alert-dialog/alert-dialog-action.svelte +9 -3
  321. package/src/lib/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
  322. package/src/lib/components/primitives/alert-dialog/alert-dialog-overlay.svelte +1 -1
  323. package/src/lib/components/primitives/badge/badge.svelte +2 -2
  324. package/src/lib/components/primitives/button/button.svelte +6 -2
  325. package/src/lib/components/primitives/card/card-header.svelte +1 -1
  326. package/src/lib/components/primitives/card/card.svelte +21 -5
  327. package/src/lib/components/primitives/card/index.ts +1 -4
  328. package/src/lib/components/primitives/checkbox/checkbox.svelte +1 -1
  329. package/src/lib/components/primitives/command/command-dialog.svelte +42 -0
  330. package/src/lib/components/primitives/command/command-empty.svelte +17 -0
  331. package/src/lib/components/primitives/command/command-group.svelte +33 -0
  332. package/src/lib/components/primitives/command/command-input.svelte +36 -0
  333. package/src/lib/components/primitives/command/command-item.svelte +28 -0
  334. package/src/lib/components/primitives/command/command-link-item.svelte +21 -0
  335. package/src/lib/components/primitives/command/command-list.svelte +20 -0
  336. package/src/lib/components/primitives/command/command-loading.svelte +7 -0
  337. package/src/lib/components/primitives/command/command-separator.svelte +17 -0
  338. package/src/lib/components/primitives/command/command-shortcut.svelte +23 -0
  339. package/src/lib/components/primitives/command/command.svelte +28 -0
  340. package/src/lib/components/primitives/command/index.ts +37 -0
  341. package/src/lib/components/primitives/context-menu/context-menu-content.svelte +1 -1
  342. package/src/lib/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
  343. package/src/lib/components/primitives/dialog/dialog-content.svelte +11 -3
  344. package/src/lib/components/primitives/dialog/dialog-overlay.svelte +1 -1
  345. package/src/lib/components/primitives/dialog/dialog-title.svelte +6 -2
  346. package/src/lib/components/primitives/drawer/Drawer.svelte +2 -2
  347. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
  348. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +46 -0
  349. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-content.svelte +31 -0
  350. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
  351. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-group.svelte +7 -0
  352. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-item.svelte +27 -0
  353. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-label.svelte +24 -0
  354. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-portal.svelte +7 -0
  355. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
  356. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +36 -0
  357. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-separator.svelte +17 -0
  358. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +23 -0
  359. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +31 -0
  360. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
  361. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub.svelte +7 -0
  362. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
  363. package/src/lib/components/primitives/dropdown-menu/dropdown-menu.svelte +7 -0
  364. package/src/lib/components/primitives/dropdown-menu/index.ts +54 -0
  365. package/src/lib/components/primitives/{alert/alert-description.svelte → empty/empty-content.svelte} +3 -3
  366. package/src/lib/components/primitives/empty/empty-description.svelte +23 -0
  367. package/src/lib/components/primitives/{alert/alert-title.svelte → empty/empty-header.svelte} +3 -3
  368. package/src/lib/components/primitives/empty/empty-media.svelte +41 -0
  369. package/src/lib/components/primitives/{card/card-action.svelte → empty/empty-title.svelte} +2 -2
  370. package/src/lib/components/primitives/empty/empty.svelte +23 -0
  371. package/src/lib/components/primitives/empty/index.ts +22 -0
  372. package/src/lib/components/primitives/index.ts +10 -1
  373. package/src/lib/components/primitives/input/input.svelte +4 -4
  374. package/src/lib/components/primitives/input-group/index.ts +22 -0
  375. package/src/lib/components/primitives/input-group/input-group-addon.svelte +53 -0
  376. package/src/lib/components/primitives/input-group/input-group-button.svelte +49 -0
  377. package/src/lib/components/primitives/input-group/input-group-input.svelte +25 -0
  378. package/src/lib/components/primitives/input-group/input-group-text.svelte +22 -0
  379. package/src/lib/components/primitives/input-group/input-group-textarea.svelte +23 -0
  380. package/src/lib/components/primitives/input-group/input-group.svelte +24 -0
  381. package/src/lib/components/primitives/mode-toggle/mode-toggle.svelte +6 -7
  382. package/src/lib/components/primitives/popover/index.ts +28 -0
  383. package/src/lib/components/primitives/popover/popover-close.svelte +7 -0
  384. package/src/lib/components/primitives/popover/popover-content.svelte +31 -0
  385. package/src/lib/components/primitives/popover/popover-description.svelte +20 -0
  386. package/src/lib/components/primitives/popover/popover-header.svelte +20 -0
  387. package/src/lib/components/primitives/popover/popover-portal.svelte +7 -0
  388. package/src/lib/components/primitives/popover/popover-title.svelte +15 -0
  389. package/src/lib/components/primitives/popover/popover-trigger.svelte +17 -0
  390. package/src/lib/components/primitives/popover/popover.svelte +7 -0
  391. package/src/lib/components/primitives/resizable/resizable-handle.svelte +6 -2
  392. package/src/lib/components/primitives/resizable/resizable-pane-group.svelte +1 -4
  393. package/src/lib/components/primitives/scroll-area/scroll-area.svelte +1 -1
  394. package/src/lib/components/primitives/search/search.svelte +3 -3
  395. package/src/lib/components/primitives/select/select-content.svelte +1 -1
  396. package/src/lib/components/primitives/select/select-trigger.svelte +1 -1
  397. package/src/lib/components/primitives/severity.ts +26 -0
  398. package/src/lib/components/primitives/slider/slider.svelte +8 -3
  399. package/src/lib/components/primitives/sonner/sonner.svelte +1 -1
  400. package/src/lib/components/primitives/spinner/index.ts +1 -0
  401. package/src/lib/components/primitives/spinner/spinner.svelte +29 -0
  402. package/src/lib/components/primitives/switch/switch.svelte +2 -2
  403. package/src/lib/components/primitives/tabs/tabs-list.svelte +27 -5
  404. package/src/lib/components/primitives/tabs/tabs-trigger.svelte +23 -5
  405. package/src/lib/components/primitives/tabs/tabs.svelte +6 -2
  406. package/src/lib/components/primitives/textarea/textarea.svelte +1 -1
  407. package/src/lib/components/primitives/theme-switcher/ThemeSwitcher.svelte +1 -1
  408. package/src/lib/components/primitives/toggle/index.ts +13 -0
  409. package/src/lib/components/primitives/toggle/toggle.svelte +54 -0
  410. package/src/lib/components/primitives/toggle-group/index.ts +10 -0
  411. package/src/lib/components/primitives/toggle-group/toggle-group-item.svelte +35 -0
  412. package/src/lib/components/primitives/toggle-group/toggle-group.svelte +75 -0
  413. package/src/lib/components/viewer/MeshMetadataPanel.svelte +119 -0
  414. package/src/lib/components/viewer/SceneManager.svelte +14 -5
  415. package/src/lib/components/viewer/Viewer.svelte +243 -221
  416. package/src/lib/compute/run-panel-action.ts +16 -0
  417. package/src/lib/compute/solving.svelte.ts +66 -50
  418. package/src/lib/compute/useSolveSession.svelte.ts +3 -0
  419. package/src/lib/constants.ts +7 -9
  420. package/src/lib/contexts/hostContext.svelte.ts +51 -0
  421. package/src/lib/i18n/localeContext.svelte.ts +40 -5
  422. package/src/lib/i18n/messages.ts +453 -13
  423. package/src/lib/index.ts +21 -0
  424. package/src/lib/public.ts +1 -0
  425. package/src/lib/schema/host-support.ts +129 -0
  426. package/src/lib/schema/option-display.ts +44 -0
  427. package/src/lib/schema/param-exporter.ts +10 -7
  428. package/src/lib/schema/visibility-rules.ts +23 -0
  429. package/src/lib/styles/base.css +80 -10
  430. package/src/lib/types/actionButton.ts +16 -3
  431. package/src/lib/types/presetLabels.ts +13 -11
  432. package/src/lib/utils/file-download.ts +11 -21
  433. package/src/lib/utils/host-files.ts +61 -0
  434. package/src/lib/utils/loadScript.ts +3 -0
  435. package/src/lib/utils/webp-to-png.ts +48 -0
  436. package/dist/components/primitives/alert/alert.svelte +0 -44
  437. package/dist/components/primitives/alert/alert.svelte.d.ts +0 -26
  438. package/dist/components/primitives/alert/index.d.ts +0 -5
  439. package/dist/components/primitives/alert/index.js +0 -7
  440. package/dist/components/viewer/MeshMetadataDialog.svelte +0 -126
  441. package/dist/components/viewer/MeshMetadataDialog.svelte.d.ts +0 -10
  442. package/src/lib/components/primitives/alert/alert.svelte +0 -44
  443. package/src/lib/components/primitives/alert/index.ts +0 -14
  444. package/src/lib/components/viewer/MeshMetadataDialog.svelte +0 -126
@@ -7,7 +7,12 @@
7
7
  import type { PresetLabels } from '../../types/presetLabels';
8
8
  import { createSolvingIndicator } from '../../compute/solving.svelte';
9
9
  import { createRequestResponseDriver } from '@selvajs/solve/client';
10
- import type { RetainedSolveResult, SolveEventSource, SolveSession } from '@selvajs/solve/client';
10
+ import type {
11
+ RetainedSolveResult,
12
+ SolveEventSource,
13
+ SolveSession,
14
+ SolveSettlement
15
+ } from '@selvajs/solve/client';
11
16
  import SolveMessages from './SolveMessages.svelte';
12
17
  import { meshPolicy } from '@selvajs/visualization/parse';
13
18
  import type { ThreeViewer } from '@selvajs/visualization/render';
@@ -19,8 +24,8 @@
19
24
  import { type ViewerConfig } from '../viewer/Viewer.svelte';
20
25
  import StateDisplay from '../primitives/StateDisplay.svelte';
21
26
  import { setClientSlot, type ClientSlot } from '../../contexts/clientSlotContext.svelte';
22
- import type { Locale } from '../../i18n/messages';
23
- import { setLocaleContext, getLocaleContext } from '../../i18n/localeContext.svelte';
27
+ import type { Locale, ViewerMessages } from '../../i18n/messages';
28
+ import { layerLocaleContext } from '../../i18n/localeContext.svelte';
24
29
 
25
30
  import type { Snippet } from 'svelte';
26
31
 
@@ -34,8 +39,11 @@
34
39
  isEmbedded?: boolean;
35
40
  primaryColor?: string;
36
41
  showModeToggle?: boolean;
42
+ /** Host actions, listed in the panel footer's ⋯ menu after saving and loading inputs. */
37
43
  panelActions?: ActionButton[];
44
+ /** Lists "Save inputs…" in the footer menu. */
38
45
  showSaveButton?: boolean;
46
+ /** Lists "Load inputs…" in the footer menu. */
39
47
  showLoadButton?: boolean;
40
48
  /** When set, persist saved states via this callback instead of downloading a .slvp file. */
41
49
  onSaveState?: (state: ParameterPreset) => void | Promise<void>;
@@ -74,6 +82,12 @@
74
82
  */
75
83
  getSession: () => SolveSession;
76
84
  }) => void;
85
+ /**
86
+ * Once per settled solve: applied, discarded, blocked, aborted or failed. A result held
87
+ * for review counts when the user accepts or rejects it, and one a queued solve replaces
88
+ * never does. Auto-solves from input changes count too.
89
+ */
90
+ onSolved?: (settlement: SolveSettlement) => void;
77
91
  /** Hands the live three.js viewer to the host once it mounts. See `Viewer.svelte` for the contract. */
78
92
  onViewerReady?: (viewer: ThreeViewer) => void | (() => void);
79
93
  /** Viewer chrome and defaults. `backgroundColor` and `showSceneManager` are set by the layout. */
@@ -92,6 +106,14 @@
92
106
  // Language for the app's own chrome, English when unset. Does not translate
93
107
  // schema-authored labels or Grasshopper-sourced names/metadata.
94
108
  lang?: Locale;
109
+ /**
110
+ * Replaces individual strings of the app's own chrome, layered over the `lang` catalog
111
+ * (`VIEWER_MESSAGES`): reword a label, or supply every string for a language with no
112
+ * built-in catalog. Reaches every component inside, the viewer included. A `{name}`
113
+ * placeholder in the default is filled the same way in an override. The preset manager's
114
+ * strings come from `presetLabels` instead.
115
+ */
116
+ messages?: Partial<ViewerMessages>;
95
117
  }
96
118
 
97
119
  let {
@@ -123,22 +145,26 @@
123
145
  brandName,
124
146
  header,
125
147
  onReady,
148
+ onSolved,
126
149
  onViewerReady,
127
150
  viewerConfig = {},
128
151
  externalScopeKey,
129
152
  clientSlot,
130
- lang
153
+ lang,
154
+ messages
131
155
  }: Props = $props();
132
156
 
133
157
  // Reaches InputControl deep in the tree.
134
158
  // svelte-ignore state_referenced_locally
135
159
  setClientSlot(clientSlot);
136
160
 
137
- // Resolution: explicit `lang` → host-provided locale → English. Passed as a getter so
138
- // switching `lang` updates the chrome live.
139
- const hostLocale = getLocaleContext();
140
- setLocaleContext(() => lang ?? hostLocale.locale);
141
- const t = $derived(getLocaleContext().messages);
161
+ // Resolution: explicit `lang` → host-provided locale → English, with `messages` on top.
162
+ // Getters, so switching either updates the chrome live.
163
+ const locale = layerLocaleContext(
164
+ () => lang,
165
+ () => messages
166
+ );
167
+ const t = $derived(locale.messages);
142
168
 
143
169
  const resolvedScopeKey = $derived(externalScopeKey || definitionKey || schema?.id || '');
144
170
 
@@ -168,6 +194,9 @@
168
194
 
169
195
  const solvingIndicator = createSolvingIndicator(() => session.isSolving);
170
196
 
197
+ // Read at call time, so a host swapping the callback needs no resubscribe.
198
+ $effect(() => session.onSettled((settlement) => onSolved?.(settlement)));
199
+
171
200
  $effect(() => {
172
201
  onReady?.({
173
202
  loadValues: (incoming) => session.loadValues(incoming),
@@ -217,14 +246,14 @@
217
246
 
218
247
  let resolvedIsEmbedded = $derived(isEmbedded ?? page.url.searchParams.get('embed') === 'true');
219
248
  let resolvedPrimaryColor = $derived(primaryColor ?? page.url.searchParams.get('primary'));
220
- let customStyle = $derived(
221
- resolvedPrimaryColor ? `--primary: ${hexToOklch(resolvedPrimaryColor)}` : ''
249
+ let primaryOverride = $derived(
250
+ resolvedPrimaryColor ? hexToOklch(resolvedPrimaryColor) : undefined
222
251
  );
223
252
 
224
253
  let pageTitle = $derived(title ?? (schema?.description || schema.name));
225
254
  </script>
226
255
 
227
- <div style={customStyle} style:display="contents">
256
+ <div class="contents" style:--primary={primaryOverride}>
228
257
  <AppShell
229
258
  mode="fixed"
230
259
  showHeader={!resolvedIsEmbedded}
@@ -254,9 +283,11 @@
254
283
  {#key definitionKey}
255
284
  <AppLayout
256
285
  {schema}
286
+ showViewer={!!schema.viewerOptions?.enableRemote}
257
287
  meshes={session.meshes}
258
288
  isSolving={session.isSolving}
259
- showSolvingIndicator={schema.instanceSolve !== false && solvingIndicator.show}
289
+ showSolvingIndicator={solvingIndicator.show}
290
+ solveIsSlow={solvingIndicator.slow}
260
291
  hasPendingChanges={session.hasPendingChanges}
261
292
  hasNeverSolved={session.hasNeverSolved}
262
293
  bind:isViewerFullscreen
@@ -272,6 +303,7 @@
272
303
  {presetLabels}
273
304
  onValueChange={handleValueChange}
274
305
  oncalculate={handleCalculate}
306
+ ensureSolved={() => session.ensureSolved()}
275
307
  onLoadValues={() => session.loadValues({})}
276
308
  />
277
309
  {/key}
@@ -286,15 +318,4 @@
286
318
  onabort={() => session.abort()}
287
319
  onconfirm={() => session.acknowledge()}
288
320
  ondiscard={() => session.discard()}
289
- labels={{
290
- solving: t.solveSolving,
291
- blockedTitle: t.solveBlockedTitle,
292
- messagesTitle: t.solveMessagesTitle,
293
- blockedDescription: t.solveBlocked,
294
- messagesDescription: t.solveMessagesDescription,
295
- confirm: t.solveMessagesConfirm,
296
- discard: t.solveMessagesDiscard,
297
- abort: t.solveMessagesAbort,
298
- dismiss: t.solveMessagesDismiss
299
- }}
300
321
  />
@@ -2,11 +2,11 @@ import type { UISchema, ParameterPreset } from '@selvajs/schemas';
2
2
  import type { ActionButton } from '../../types/actionButton';
3
3
  import type { SolveFn } from '@selvajs/solve/shared';
4
4
  import type { PresetLabels } from '../../types/presetLabels';
5
- import type { RetainedSolveResult, SolveEventSource, SolveSession } from '@selvajs/solve/client';
5
+ import type { RetainedSolveResult, SolveEventSource, SolveSession, SolveSettlement } from '@selvajs/solve/client';
6
6
  import type { ThreeViewer } from '@selvajs/visualization/render';
7
7
  import { type ViewerConfig } from '../viewer/Viewer.svelte';
8
8
  import { type ClientSlot } from '../../contexts/clientSlotContext.svelte';
9
- import type { Locale } from '../../i18n/messages';
9
+ import type { Locale, ViewerMessages } from '../../i18n/messages';
10
10
  import type { Snippet } from 'svelte';
11
11
  interface Props {
12
12
  schema: UISchema;
@@ -18,8 +18,11 @@ interface Props {
18
18
  isEmbedded?: boolean;
19
19
  primaryColor?: string;
20
20
  showModeToggle?: boolean;
21
+ /** Host actions, listed in the panel footer's ⋯ menu after saving and loading inputs. */
21
22
  panelActions?: ActionButton[];
23
+ /** Lists "Save inputs…" in the footer menu. */
22
24
  showSaveButton?: boolean;
25
+ /** Lists "Load inputs…" in the footer menu. */
23
26
  showLoadButton?: boolean;
24
27
  /** When set, persist saved states via this callback instead of downloading a .slvp file. */
25
28
  onSaveState?: (state: ParameterPreset) => void | Promise<void>;
@@ -57,6 +60,12 @@ interface Props {
57
60
  */
58
61
  getSession: () => SolveSession;
59
62
  }) => void;
63
+ /**
64
+ * Once per settled solve: applied, discarded, blocked, aborted or failed. A result held
65
+ * for review counts when the user accepts or rejects it, and one a queued solve replaces
66
+ * never does. Auto-solves from input changes count too.
67
+ */
68
+ onSolved?: (settlement: SolveSettlement) => void;
60
69
  /** Hands the live three.js viewer to the host once it mounts. See `Viewer.svelte` for the contract. */
61
70
  onViewerReady?: (viewer: ThreeViewer) => void | (() => void);
62
71
  /** Viewer chrome and defaults. `backgroundColor` and `showSceneManager` are set by the layout. */
@@ -69,6 +78,14 @@ interface Props {
69
78
  externalScopeKey?: string;
70
79
  clientSlot?: ClientSlot;
71
80
  lang?: Locale;
81
+ /**
82
+ * Replaces individual strings of the app's own chrome, layered over the `lang` catalog
83
+ * (`VIEWER_MESSAGES`): reword a label, or supply every string for a language with no
84
+ * built-in catalog. Reaches every component inside, the viewer included. A `{name}`
85
+ * placeholder in the default is filled the same way in an override. The preset manager's
86
+ * strings come from `presetLabels` instead.
87
+ */
88
+ messages?: Partial<ViewerMessages>;
72
89
  }
73
90
  declare const ComputeApp: import("svelte").Component<Props, {}, "">;
74
91
  type ComputeApp = ReturnType<typeof ComputeApp>;
@@ -3,14 +3,15 @@
3
3
  //
4
4
  // The counterpart to `SolveMessages`, which interrupts only for what the definition's author
5
5
  // wrote. Everything else — Grasshopper complaining about its own components — lands here,
6
- // where it is available without being in the way. One section per level, most severe first, with the
7
- // component that raised each message shown as a label rather than spliced into its text.
6
+ // where it is available without being in the way. Most severe first, with the component that
7
+ // raised each message on its own line rather than spliced into its text.
8
8
 
9
9
  import type { Snippet } from 'svelte';
10
- import { CircleAlert, TriangleAlert, Info } from '@lucide/svelte';
11
10
  import type { SolveDiagnostic } from '@selvajs/solve/shared';
12
11
  import * as Dialog from '../primitives/dialog';
13
- import { Badge } from '../primitives/badge';
12
+ import IssueList, { type Issue } from '../primitives/IssueList.svelte';
13
+ import { getLocaleContext } from '../../i18n/localeContext.svelte';
14
+ import { formatCount } from '../../i18n/messages';
14
15
 
15
16
  interface Props {
16
17
  /** The last solve's messages. Preferred over `errors`/`warnings` when both are given. */
@@ -24,6 +25,9 @@
24
25
 
25
26
  let { diagnostics, errors = [], warnings = [], trigger }: Props = $props();
26
27
 
28
+ const locale = getLocaleContext();
29
+ const t = $derived(locale.messages);
30
+
27
31
  let open = $state(false);
28
32
 
29
33
  const rows = $derived<SolveDiagnostic[]>(
@@ -42,34 +46,11 @@
42
46
  count: number;
43
47
  }
44
48
 
45
- // Tone classes are written out, never interpolated: Tailwind scans source text, so a
46
- // constructed class name is not emitted and the icon would render colourless.
47
- const LEVELS = [
48
- {
49
- level: 'error',
50
- heading: 'Errors',
51
- one: 'error',
52
- many: 'errors',
53
- icon: CircleAlert,
54
- tone: 'text-destructive'
55
- },
56
- {
57
- level: 'warning',
58
- heading: 'Warnings',
59
- one: 'warning',
60
- many: 'warnings',
61
- icon: TriangleAlert,
62
- tone: 'text-amber-500'
63
- },
64
- {
65
- level: 'remark',
66
- heading: 'Notes',
67
- one: 'note',
68
- many: 'notes',
69
- icon: Info,
70
- tone: 'text-muted-foreground'
71
- }
72
- ] as const;
49
+ const levels = $derived([
50
+ { level: 'error', severity: 'error', one: t.errorCountOne, other: t.errorCountOther },
51
+ { level: 'warning', severity: 'warning', one: t.warningCountOne, other: t.warningCountOther },
52
+ { level: 'remark', severity: 'note', one: t.noteCountOne, other: t.noteCountOther }
53
+ ] as const);
73
54
 
74
55
  /**
75
56
  * One section per level that has messages, most severe first; within a level, the order the
@@ -77,72 +58,55 @@
77
58
  * branches raises the same warning 200 times, and an unstacked list buries every other message.
78
59
  */
79
60
  const sections = $derived(
80
- LEVELS.map((meta) => {
81
- // A null-prototype object rather than a Map: a local built fresh on each derive, never
82
- // reactive state, and the lint rule that steers Map → SvelteMap cannot tell them apart.
83
- const byKey: Record<string, Item> = Object.create(null);
84
- const items: Item[] = [];
85
- for (const d of rows) {
86
- if (d.level !== meta.level) continue;
87
- const key = `${d.message} ${d.source ?? ''}`;
88
- if (byKey[key]) {
89
- byKey[key].count++;
90
- } else {
91
- byKey[key] = { level: d.level, message: d.message, source: d.source, count: 1 };
92
- items.push(byKey[key]);
61
+ levels
62
+ .map((meta) => {
63
+ // A null-prototype object rather than a Map: a local built fresh on each derive, never
64
+ // reactive state, and the lint rule that steers Map → SvelteMap cannot tell them apart.
65
+ const byKey: Record<string, Item> = Object.create(null);
66
+ const items: Item[] = [];
67
+ for (const d of rows) {
68
+ if (d.level !== meta.level) continue;
69
+ const key = `${d.message} ${d.source ?? ''}`;
70
+ if (byKey[key]) {
71
+ byKey[key].count++;
72
+ } else {
73
+ byKey[key] = { level: d.level, message: d.message, source: d.source, count: 1 };
74
+ items.push(byKey[key]);
75
+ }
93
76
  }
94
- }
95
- return { ...meta, items };
96
- }).filter((section) => section.items.length > 0)
77
+ return { ...meta, items };
78
+ })
79
+ .filter((section) => section.items.length > 0)
80
+ );
81
+
82
+ const issues = $derived<Issue[]>(
83
+ sections.flatMap((section) =>
84
+ section.items.map((item) => ({
85
+ severity: section.severity,
86
+ message: item.message,
87
+ source: item.source,
88
+ count: item.count
89
+ }))
90
+ )
97
91
  );
98
92
  </script>
99
93
 
100
94
  <Dialog.Root bind:open>
101
- <Dialog.Trigger class="focus:outline-none">
95
+ <Dialog.Trigger>
102
96
  {@render trigger()}
103
97
  </Dialog.Trigger>
104
98
 
105
- <Dialog.Content class="max-w-lg gap-4">
99
+ <Dialog.Content class="max-w-lg">
106
100
  <Dialog.Header>
107
- <Dialog.Title>Messages</Dialog.Title>
101
+ <Dialog.Title>{t.messagesTitle}</Dialog.Title>
108
102
  <Dialog.Description>
109
103
  {#each sections as section, i (section.level)}
110
104
  {#if i > 0}<span class="mx-1.5">·</span>{/if}
111
- <span
112
- >{section.items.length} {section.items.length === 1 ? section.one : section.many}</span
113
- >
105
+ <span>{formatCount(section.items.length, section.one, section.other)}</span>
114
106
  {/each}
115
107
  </Dialog.Description>
116
108
  </Dialog.Header>
117
109
 
118
- <div class="space-y-4 max-h-[60vh] overflow-y-auto">
119
- {#each sections as section (section.level)}
120
- <section>
121
- <h3 class="mb-1.5 gap-1.5 text-xs font-medium flex items-center text-muted-foreground">
122
- <section.icon class="h-3.5 w-3.5 {section.tone}" />
123
- {section.heading}
124
- </h3>
125
- <ul class="divide-y rounded-lg border">
126
- {#each section.items as item (item.message + (item.source ?? ''))}
127
- <li class="gap-3 px-3 py-2 text-sm flex items-start justify-between">
128
- <p class="min-w-0 wrap-anywhere">
129
- {item.message}
130
- {#if item.count > 1}
131
- <span class="ml-1 text-xs text-muted-foreground tabular-nums"
132
- >×{item.count}</span
133
- >
134
- {/if}
135
- </p>
136
- {#if item.source}
137
- <Badge variant="secondary" class="font-normal max-w-[40%] shrink-0 truncate">
138
- {item.source}
139
- </Badge>
140
- {/if}
141
- </li>
142
- {/each}
143
- </ul>
144
- </section>
145
- {/each}
146
- </div>
110
+ <IssueList {issues} />
147
111
  </Dialog.Content>
148
112
  </Dialog.Root>
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { Download, Upload, AlertTriangle, CheckCircle } from '@lucide/svelte';
2
+ import { Upload } from '@lucide/svelte';
3
3
  import type { UISchema, ParameterPreset } from '@selvajs/schemas';
4
4
  import {
5
5
  createSavedState,
@@ -8,18 +8,14 @@
8
8
  exportStateAsJson,
9
9
  importStateFromJson
10
10
  } from '../../schema/param-exporter';
11
- import { Button, Input, Label, Textarea, Dialog, Card, toast } from '../primitives';
12
-
13
- import type { ActionButton } from '../../types/actionButton';
11
+ import { Button, Input, Label, Textarea, Dialog, Callout, IssueList, toast } from '../primitives';
14
12
  import { DEFAULT_PRESET_LABELS, type PresetLabels } from '../../types/presetLabels';
13
+ import { pickFile } from '../../utils/host-files';
15
14
 
16
15
  interface Props {
17
16
  schema: UISchema;
18
17
  currentValues: Record<string, unknown>;
19
18
  onLoadValues: (values: Record<string, unknown>) => void;
20
- showSaveButton?: boolean;
21
- showLoadButton?: boolean;
22
- actions?: ActionButton[];
23
19
  /** When set, persist saved states via this callback instead of downloading a .slvp file. */
24
20
  onSaveState?: (state: ParameterPreset) => void | Promise<void>;
25
21
  /** When set, the Load dialog lists these states instead of showing a file input. */
@@ -28,17 +24,7 @@
28
24
  labels?: Partial<PresetLabels>;
29
25
  }
30
26
 
31
- let {
32
- schema,
33
- currentValues,
34
- onLoadValues,
35
- showSaveButton = true,
36
- showLoadButton = true,
37
- actions = [],
38
- onSaveState,
39
- onListStates,
40
- labels
41
- }: Props = $props();
27
+ let { schema, currentValues, onLoadValues, onSaveState, onListStates, labels }: Props = $props();
42
28
 
43
29
  const t = $derived({ ...DEFAULT_PRESET_LABELS, ...labels });
44
30
 
@@ -52,13 +38,13 @@
52
38
  let showLoadDialog = $state(false);
53
39
  let loadResult = $state<PresetLoadResult | null>(null);
54
40
  let loadingPresetName = $state('');
55
- let fileInputRef = $state<HTMLInputElement | null>(null);
56
41
 
57
42
  let listedStates = $state<ParameterPreset[]>([]);
58
43
  let isLoadingList = $state(false);
59
44
  let listError = $state('');
60
45
 
61
- function openExportDialog() {
46
+ /** Opens the save dialog. The panel footer's menu calls it. */
47
+ export function openSave() {
62
48
  exportName = `State ${new Date().toLocaleDateString()}`;
63
49
  exportDescription = '';
64
50
  exportAuthor = schema.author || '';
@@ -83,7 +69,7 @@
83
69
  });
84
70
 
85
71
  if (onSaveState) await onSaveState(state);
86
- else exportStateAsJson(state);
72
+ else await exportStateAsJson(state);
87
73
  showExportDialog = false;
88
74
  }
89
75
 
@@ -100,19 +86,16 @@
100
86
  }
101
87
  }
102
88
 
103
- async function handleImport(event: Event) {
104
- const input = event.target as HTMLInputElement;
105
- if (!input.files || input.files.length === 0) return;
89
+ async function importFromFile() {
90
+ // .sps is the pre-rename extension; files with it exist on users' drives, so keep accepting it.
91
+ const file = await pickFile({ accept: '.slvp,.sps' });
92
+ if (!file) return;
106
93
 
107
94
  try {
108
- const imported = await importStateFromJson(input.files[0]);
109
- tryLoad(imported);
95
+ tryLoad(await importStateFromJson(file));
110
96
  } catch (error) {
111
97
  toast.error(t.loadImportError + (error as Error).message);
112
98
  }
113
-
114
- // Reset so re-picking the same file fires `change` again.
115
- input.value = '';
116
99
  }
117
100
 
118
101
  function confirmLoad() {
@@ -128,7 +111,8 @@
128
111
  loadResult = null;
129
112
  }
130
113
 
131
- async function openLoadDialog() {
114
+ /** Opens the load dialog. The panel footer's menu calls it. */
115
+ export async function openLoad() {
132
116
  showLoadDialog = true;
133
117
  if (!onListStates) return;
134
118
 
@@ -145,8 +129,8 @@
145
129
  }
146
130
 
147
131
  function handleLoadClick() {
148
- fileInputRef?.click();
149
132
  showLoadDialog = false;
133
+ void importFromFile();
150
134
  }
151
135
 
152
136
  function selectListedState(preset: ParameterPreset) {
@@ -155,39 +139,6 @@
155
139
  }
156
140
  </script>
157
141
 
158
- {#if showSaveButton}
159
- <Button variant="default" size="sm" onclick={openExportDialog}>
160
- <Download class="mr-2 h-4 w-4" />
161
- {t.saveButton}
162
- </Button>
163
- {/if}
164
-
165
- {#if showLoadButton}
166
- <Button variant="outline" size="sm" onclick={openLoadDialog}>
167
- <Upload class="mr-2 h-4 w-4" />
168
- {t.loadButton}
169
- </Button>
170
- {/if}
171
-
172
- {#each actions as action (action.id)}
173
- <Button variant={action.variant ?? 'outline'} size={action.size ?? 'sm'} onclick={action.onclick}>
174
- {#if action.icon}
175
- {@const IconComponent = action.icon}
176
- <IconComponent class="mr-2 h-4 w-4" />
177
- {/if}
178
- {action.label}
179
- </Button>
180
- {/each}
181
-
182
- <!-- .sps is the pre-rename extension; files with it exist on users' drives, so keep accepting it. -->
183
- <input
184
- bind:this={fileInputRef}
185
- type="file"
186
- accept=".slvp,.sps"
187
- onchange={handleImport}
188
- class="hidden"
189
- />
190
-
191
142
  <!-- Save Dialog -->
192
143
  <Dialog.Root bind:open={showExportDialog}>
193
144
  <Dialog.Content>
@@ -225,7 +176,7 @@
225
176
 
226
177
  <Dialog.Footer>
227
178
  <Button variant="outline" onclick={() => (showExportDialog = false)}>{t.cancelButton}</Button>
228
- <Button onclick={handleExport}>{t.saveButton}</Button>
179
+ <Button onclick={handleExport}>{t.saveConfirmButton}</Button>
229
180
  </Dialog.Footer>
230
181
  </Dialog.Content>
231
182
  </Dialog.Root>
@@ -239,7 +190,7 @@
239
190
  </Dialog.Header>
240
191
 
241
192
  {#if onListStates}
242
- <div class="py-4 max-h-[60vh] overflow-y-auto">
193
+ <div class="py-4">
243
194
  {#if isLoadingList}
244
195
  <p class="text-sm py-8 text-center text-muted-foreground">…</p>
245
196
  {:else if listError}
@@ -283,7 +234,7 @@
283
234
 
284
235
  <!-- Validation Dialog -->
285
236
  <Dialog.Root bind:open={showValidationDialog}>
286
- <Dialog.Content class="max-w-2xl max-h-[80vh] overflow-y-auto">
237
+ <Dialog.Content class="max-w-2xl">
287
238
  <Dialog.Header>
288
239
  <Dialog.Title>{t.validationTitle}</Dialog.Title>
289
240
  <Dialog.Description>
@@ -296,75 +247,31 @@
296
247
  {#if loadResult}
297
248
  <div class="gap-4 py-4 grid">
298
249
  {#if loadResult.isValid}
299
- <Card.Root class="p-4 border-success/30 bg-success/5">
300
- <div class="gap-3 flex items-start">
301
- <CheckCircle class="h-5 w-5 text-success" />
302
- <div>
303
- <h4 class="text-sm font-semibold text-success-foreground">
304
- {t.validationNoIssuesTitle}
305
- </h4>
306
- <p class="text-sm mt-1 text-success-foreground/80">
307
- {t.validationNoIssuesBody}
308
- </p>
309
- </div>
310
- </div>
311
- </Card.Root>
250
+ <Callout tone="success" title={t.validationNoIssuesTitle}>
251
+ {t.validationNoIssuesBody}
252
+ </Callout>
312
253
  {:else if loadResult.canLoad}
313
- <Card.Root class="p-4 border-warning/30 bg-warning/5">
314
- <div class="gap-3 flex items-start">
315
- <AlertTriangle class="h-5 w-5 text-warning" />
316
- <div>
317
- <h4 class="text-sm font-semibold text-warning-foreground">
318
- {t.validationWarningsTitle}
319
- </h4>
320
- <p class="text-sm mt-1 text-warning-foreground/80">
321
- {t.validationWarningsBody.replace('{count}', String(loadResult.issues.length))}
322
- </p>
323
- </div>
324
- </div>
325
- </Card.Root>
254
+ <Callout tone="warning" title={t.validationWarningsTitle}>
255
+ {t.validationWarningsBody.replace('{count}', String(loadResult.issues.length))}
256
+ </Callout>
326
257
  {:else}
327
- <Card.Root class="p-4 border-destructive/30 bg-destructive/5">
328
- <div class="gap-3 flex items-start">
329
- <AlertTriangle class="h-5 w-5 text-destructive" />
330
- <div>
331
- <h4 class="text-sm font-semibold text-destructive">{t.validationErrorsTitle}</h4>
332
- <p class="text-sm mt-1 text-destructive/80">
333
- {t.validationErrorsBody}
334
- </p>
335
- </div>
336
- </div>
337
- </Card.Root>
258
+ <Callout tone="danger" title={t.validationErrorsTitle}>
259
+ {t.validationErrorsBody}
260
+ </Callout>
338
261
  {/if}
339
262
 
340
263
  {#if !loadResult.isValid}
341
- <div class="space-y-2">
264
+ <div class="gap-2 flex flex-col">
342
265
  <h4 class="text-sm font-medium">{t.validationIssuesHeading}</h4>
343
- {#each loadResult.issues as issue (issue.message)}
344
- <div
345
- class="p-3 rounded-lg border {issue.severity === 'error'
346
- ? 'border-destructive/30 bg-destructive/5'
347
- : 'border-warning/30 bg-warning/5'}"
348
- >
349
- <div class="gap-2 flex items-start">
350
- <AlertTriangle
351
- class="h-4 w-4 mt-0.5 {issue.severity === 'error'
352
- ? 'text-destructive'
353
- : 'text-warning'}"
354
- />
355
- <div class="flex-1">
356
- <p class="text-sm font-medium">{issue.message}</p>
357
- {#if issue.details}
358
- <p class="text-xs mt-1 text-muted-foreground">
359
- {t.validationExpected}
360
- {issue.details.expected} → {t.validationActual}
361
- {issue.details.actual}
362
- </p>
363
- {/if}
364
- </div>
365
- </div>
366
- </div>
367
- {/each}
266
+ <IssueList
267
+ issues={loadResult.issues.map((issue) => ({
268
+ severity: issue.severity === 'error' ? 'error' : 'warning',
269
+ message: issue.message,
270
+ detail: issue.details
271
+ ? `${t.validationExpected} ${issue.details.expected} → ${t.validationActual} ${issue.details.actual}`
272
+ : undefined
273
+ }))}
274
+ />
368
275
  </div>
369
276
  {/if}
370
277
  </div>