@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
@@ -1,13 +1,9 @@
1
1
  import type { UISchema, ParameterPreset } from '@selvajs/schemas';
2
- import type { ActionButton } from '../../types/actionButton';
3
2
  import { type PresetLabels } from '../../types/presetLabels';
4
3
  interface Props {
5
4
  schema: UISchema;
6
5
  currentValues: Record<string, unknown>;
7
6
  onLoadValues: (values: Record<string, unknown>) => void;
8
- showSaveButton?: boolean;
9
- showLoadButton?: boolean;
10
- actions?: ActionButton[];
11
7
  /** When set, persist saved states via this callback instead of downloading a .slvp file. */
12
8
  onSaveState?: (state: ParameterPreset) => void | Promise<void>;
13
9
  /** When set, the Load dialog lists these states instead of showing a file input. */
@@ -15,6 +11,9 @@ interface Props {
15
11
  /** Overrides merged over `DEFAULT_PRESET_LABELS`. */
16
12
  labels?: Partial<PresetLabels>;
17
13
  }
18
- declare const ParameterPresetManager: import("svelte").Component<Props, {}, "">;
14
+ declare const ParameterPresetManager: import("svelte").Component<Props, {
15
+ openSave: () => void;
16
+ openLoad: () => Promise<void>;
17
+ }, "">;
19
18
  type ParameterPresetManager = ReturnType<typeof ParameterPresetManager>;
20
19
  export default ParameterPresetManager;
@@ -13,10 +13,13 @@
13
13
  // anything, so it appears on its own after the solve and fades.
14
14
 
15
15
  import { untrack } from 'svelte';
16
- import { CircleAlert, TriangleAlert, Info, LoaderCircle } from '@lucide/svelte';
16
+ import { LoaderCircle } from '@lucide/svelte';
17
17
  import type { SolveDiagnostic } from '@selvajs/solve/shared';
18
18
  import type { LiveSolveState, SolvePhase } from '@selvajs/solve/client';
19
19
  import { Button } from '../primitives/button';
20
+ import IssueList, { type Issue } from '../primitives/IssueList.svelte';
21
+ import SeverityIcon from '../primitives/SeverityIcon.svelte';
22
+ import { getLocaleContext } from '../../i18n/localeContext.svelte';
20
23
 
21
24
  interface Props {
22
25
  /** What the running (or most recent) solve has said over the live channel. */
@@ -28,33 +31,15 @@
28
31
  onabort: () => void;
29
32
  onconfirm: () => void;
30
33
  ondiscard: () => void;
31
- labels?: Labels;
34
+ /**
35
+ * See `createSolvingIndicator`. The live panel would only paint once the solve is over, so
36
+ * an Esc hint stands in for it; the result's messages still show.
37
+ */
38
+ freezesDuringSolve?: boolean;
39
+ /** `floating` overlays the bottom centre; `inline` sits in the flow below the host's content. */
40
+ placement?: 'floating' | 'inline';
32
41
  }
33
42
 
34
- interface Labels {
35
- solving: string;
36
- blockedTitle: string;
37
- messagesTitle: string;
38
- blockedDescription: string;
39
- messagesDescription: string;
40
- confirm: string;
41
- discard: string;
42
- abort: string;
43
- dismiss: string;
44
- }
45
-
46
- const DEFAULT_LABELS: Labels = {
47
- solving: 'Solving…',
48
- blockedTitle: 'Solve stopped',
49
- messagesTitle: 'Solve messages',
50
- blockedDescription: 'The definition stopped this solve. No results were produced.',
51
- messagesDescription: 'This solve reported the following. Continue to see the result.',
52
- confirm: 'Continue',
53
- discard: 'Discard',
54
- abort: 'Abort',
55
- dismiss: 'Dismiss'
56
- };
57
-
58
43
  let {
59
44
  live,
60
45
  phase: sessionPhase,
@@ -62,9 +47,13 @@
62
47
  onabort,
63
48
  onconfirm,
64
49
  ondiscard,
65
- labels = DEFAULT_LABELS
50
+ freezesDuringSolve = false,
51
+ placement = 'floating'
66
52
  }: Props = $props();
67
53
 
54
+ const locale = getLocaleContext();
55
+ const t = $derived(locale.messages);
56
+
68
57
  const REMARK_LINGER_MS = 6000;
69
58
 
70
59
  const progress = $derived([...live.progress.values()]);
@@ -137,16 +126,30 @@
137
126
  // Keyed on the diagnostics array's identity, which every report renews, rather than on a
138
127
  // solve id: only the live channel has one, and on the Compute path remarks arrive with the
139
128
  // result. Once per array, so remarks that sat behind a review do not reappear after Continue.
129
+ //
130
+ // A remark is shown once while it stays raised, not after every solve. Every report repeats
131
+ // it: Grasshopper keeps runtime messages on a Message component an input change did not
132
+ // reach, and Compute re-solves the whole definition. It shows again once a solve stops
133
+ // raising it and a later one raises it anew.
140
134
  let lingering = $state(false);
141
135
  let lingeredFor: SolveDiagnostic[] | null = null;
136
+ let shownRemarks: ReadonlySet<string> = new Set();
137
+ let freshRemarks = $state.raw<SolveDiagnostic[]>([]);
138
+ const remarkKey = (d: SolveDiagnostic) => `${d.source ?? ''}\u0000${d.message}`;
142
139
  $effect(() => {
143
140
  if (phase === 'live') {
144
141
  lingering = false;
145
142
  return;
146
143
  }
147
- if (authoredRemarks.length === 0 || lingeredFor === diagnostics) return;
144
+ if (lingeredFor === diagnostics) return;
148
145
  lingeredFor = diagnostics;
149
- if (phase !== 'idle') return;
146
+ const raised = authoredRemarks.map(remarkKey);
147
+ const stillShown = raised.filter((k) => shownRemarks.has(k));
148
+ const fresh = authoredRemarks.filter((d) => !shownRemarks.has(remarkKey(d)));
149
+ const showNow = phase === 'idle' && fresh.length > 0;
150
+ shownRemarks = new Set(showNow ? [...stillShown, ...fresh.map(remarkKey)] : stillShown);
151
+ if (!showNow) return;
152
+ freshRemarks = fresh;
150
153
  lingering = true;
151
154
  const timer = setTimeout(() => (lingering = false), REMARK_LINGER_MS);
152
155
  return () => clearTimeout(timer);
@@ -165,6 +168,7 @@
165
168
  $effect(() => {
166
169
  if (phase === 'live') {
167
170
  finishing = false;
171
+ if (freezesDuringSolve) return;
168
172
  const timer = setTimeout(() => {
169
173
  revealed = true;
170
174
  revealedAt = performance.now();
@@ -191,7 +195,16 @@
191
195
  // While solving, the live channel is all there is. Once the result lands it is authoritative
192
196
  // — it carries remarks too — so the live list is dropped entirely and nothing is shown twice.
193
197
  const rows = $derived<SolveDiagnostic[]>(
194
- view === 'live' ? [...live.diagnostics] : view === 'idle' ? authoredRemarks : authoredGating
198
+ view === 'live' ? [...live.diagnostics] : view === 'idle' ? freshRemarks : authoredGating
199
+ );
200
+
201
+ // A remark states something without asking anything, so it reads as a quiet note.
202
+ const issues = $derived<Issue[]>(
203
+ rows.map((d) => ({
204
+ severity: d.level === 'remark' ? 'note' : d.level,
205
+ message: d.message,
206
+ source: d.source
207
+ }))
195
208
  );
196
209
 
197
210
  // Steps a few milliseconds long would swap the headline faster than it can be read. Each one
@@ -228,28 +241,59 @@
228
241
  : rows.length > 0 && lingering
229
242
  );
230
243
 
244
+ // What a screen reader hears of the passive views, through a region that outlives the panel: one
245
+ // created together with its text is not announced. The step name, not its counter, so a long
246
+ // solve announces each step rather than every tick. Review and blocked are alerts of their own.
247
+ const announcement = $derived(
248
+ !visible
249
+ ? ''
250
+ : view === 'live'
251
+ ? ((headline ?? progress[0])?.label ?? t.solveSolving)
252
+ : view === 'idle'
253
+ ? rows.map((d) => d.message).join(' ')
254
+ : ''
255
+ );
256
+
231
257
  function dismiss() {
232
258
  dismissedFor = diagnostics;
233
259
  }
234
260
 
235
261
  // Escape resolves to the safe side — discard, keeping what is on screen — never to silently
236
- // applying a result the user has not accepted.
262
+ // applying a result the user has not accepted. A frozen host gets no keydown until the solve
263
+ // ends; there the plugin aborts on the key state, which only counts while Rhino is in front, so
264
+ // a browser tab (local or Compute) has to abort from the page.
237
265
  function handleKeydown(e: KeyboardEvent) {
238
266
  if (e.key !== 'Escape') return;
239
- if (phase === 'review') ondiscard();
267
+ if (phase === 'live') {
268
+ if (!freezesDuringSolve) onabort();
269
+ } else if (phase === 'review') ondiscard();
240
270
  else if (phase === 'blocked') dismiss();
241
271
  }
242
272
  </script>
243
273
 
244
274
  <svelte:window onkeydown={handleKeydown} />
245
275
 
246
- {#if visible}
276
+ <div class="sr-only" role="status" aria-live="polite">{announcement}</div>
277
+
278
+ {#if freezesDuringSolve && view === 'live'}
279
+ <!-- Painted before the solve takes the thread; Abort could not be clicked until it ends. Inline,
280
+ the solving chip carries the hint instead: a line here would resize the footer mid-solve. -->
281
+ {#if placement === 'floating'}
282
+ <p
283
+ class="bottom-4 text-xs fixed left-1/2 z-50 -translate-x-1/2 text-muted-foreground"
284
+ data-testid="solve-esc-hint"
285
+ >
286
+ {t.solveMessagesEscHint}
287
+ </p>
288
+ {/if}
289
+ {:else if visible}
290
+ <!-- Inline, it is a row of the host's footer like the Calculate row under it, not a card: a
291
+ framed box inside an edge-to-edge column reads as a dialog glued into the page. -->
247
292
  <div
248
- class="bottom-4 p-3 shadow-lg fixed left-1/2 z-50 w-[min(32rem,calc(100vw-2rem))] -translate-x-1/2 rounded-lg border bg-background {view ===
249
- 'blocked'
250
- ? 'border-destructive/50'
251
- : ''}"
252
- role={view === 'live' || view === 'idle' ? 'status' : 'alert'}
293
+ class={placement === 'inline'
294
+ ? `px-2 py-2 border-t ${view === 'blocked' ? 'border-destructive/40' : 'border-border/50'}`
295
+ : `p-3 bottom-4 shadow-lg w-lg fixed left-1/2 z-50 max-w-screen-inset -translate-x-1/2 rounded-lg border bg-background ${view === 'blocked' ? 'border-destructive/50' : ''}`}
296
+ role={view === 'review' || view === 'blocked' ? 'alert' : undefined}
253
297
  data-testid="solve-messages"
254
298
  data-view={view}
255
299
  >
@@ -259,7 +303,7 @@
259
303
  <div>
260
304
  <div class="gap-2 flex items-center">
261
305
  <LoaderCircle class="h-4 w-4 animate-spin shrink-0 text-muted-foreground" />
262
- <span class="min-w-0 text-sm flex-1 truncate">{head?.label ?? labels.solving}</span>
306
+ <span class="min-w-0 text-sm flex-1 truncate">{head?.label ?? t.solveSolving}</span>
263
307
  {#if head?.done !== undefined && head?.total !== undefined}
264
308
  <span class="text-xs shrink-0 text-muted-foreground tabular-nums">
265
309
  {head.done} / {head.total}
@@ -267,12 +311,17 @@
267
311
  {/if}
268
312
  <Button
269
313
  variant="secondary"
270
- size="sm"
271
- class="-my-1 h-7 px-3 text-xs shrink-0"
314
+ size="xs"
315
+ class="-my-1 shrink-0"
272
316
  disabled={finishing}
273
317
  onclick={onabort}
318
+ aria-keyshortcuts="Escape"
319
+ title={t.solveMessagesEscHint}
274
320
  >
275
- {labels.abort}
321
+ {t.solveMessagesAbort}
322
+ <kbd class="px-1 font-sans rounded border border-border/60 text-2xs opacity-70">
323
+ Esc
324
+ </kbd>
276
325
  </Button>
277
326
  </div>
278
327
  {#each progress as p, i (p.source ?? '')}
@@ -289,7 +338,7 @@
289
338
  <div
290
339
  class="h-1 overflow-hidden rounded-full bg-muted"
291
340
  role="progressbar"
292
- aria-label={p.label ?? p.source ?? labels.solving}
341
+ aria-label={p.label ?? p.source ?? t.solveSolving}
293
342
  aria-valuemin={0}
294
343
  aria-valuemax={100}
295
344
  aria-valuenow={p.fraction !== undefined ? Math.round(p.fraction * 100) : undefined}
@@ -299,8 +348,9 @@
299
348
  ? { width: 1, ms: FINISH_MS }
300
349
  : (bars[p.source ?? ''] ?? { width: p.fraction, ms: 150 })}
301
350
  <div
302
- class="h-full rounded-full bg-primary transition-[width] ease-linear"
303
- style="width: {bar.width * 100}%; transition-duration: {bar.ms}ms"
351
+ class="h-full w-(--bar-width) rounded-full bg-primary transition-all duration-(--bar-ms) ease-linear"
352
+ style:--bar-width="{bar.width * 100}%"
353
+ style:--bar-ms="{bar.ms}ms"
304
354
  ></div>
305
355
  {:else}
306
356
  <div class="animate-pulse h-full w-1/3 rounded-full bg-primary/60"></div>
@@ -310,56 +360,60 @@
310
360
  {/each}
311
361
  </div>
312
362
  </div>
363
+ {:else if (view === 'review' || view === 'blocked') && placement === 'inline'}
364
+ <!-- Each message carries its own icon, so the label goes without one; the buttons share
365
+ its row rather than adding one under a single line of text. -->
366
+ <div class="mb-1.5 gap-2 flex items-center">
367
+ <span
368
+ class="min-w-0 text-xs font-medium flex-1 truncate {view === 'blocked'
369
+ ? 'text-destructive'
370
+ : 'text-muted-foreground'}"
371
+ >
372
+ {view === 'blocked' ? t.solveBlockedTitle : t.solveMessagesTitle}
373
+ </span>
374
+ {#if view === 'blocked'}
375
+ <Button variant="ghost" size="xs" class="-my-1 shrink-0" onclick={dismiss}>
376
+ {t.solveMessagesDismiss}
377
+ </Button>
378
+ {:else}
379
+ <Button variant="ghost" size="xs" class="-my-1 shrink-0" onclick={ondiscard}>
380
+ {t.solveMessagesDiscard}
381
+ </Button>
382
+ <Button size="xs" class="-my-1 shrink-0" onclick={onconfirm}>
383
+ {t.solveMessagesConfirm}
384
+ </Button>
385
+ {/if}
386
+ </div>
313
387
  {:else if view === 'review' || view === 'blocked'}
314
388
  <div class="mb-2">
315
389
  <div class="gap-2 text-sm font-medium flex items-center">
316
390
  {#if view === 'blocked'}
317
- <CircleAlert class="h-4 w-4 shrink-0 text-destructive" />
318
- {labels.blockedTitle}
391
+ <SeverityIcon severity="error" />
392
+ {t.solveBlockedTitle}
319
393
  {:else}
320
- <TriangleAlert class="h-4 w-4 text-amber-500 shrink-0" />
321
- {labels.messagesTitle}
394
+ <SeverityIcon severity="warning" />
395
+ {t.solveMessagesTitle}
322
396
  {/if}
323
397
  </div>
324
398
  <p class="text-xs text-muted-foreground">
325
- {view === 'blocked' ? labels.blockedDescription : labels.messagesDescription}
399
+ {view === 'blocked' ? t.solveBlocked : t.solveMessagesDescription}
326
400
  </p>
327
401
  </div>
328
402
  {/if}
329
403
 
330
404
  {#if rows.length > 0}
331
- <ul
332
- class="max-h-40 space-y-2 text-sm overflow-y-auto {view === 'live'
333
- ? 'mt-3 pt-3 border-t'
334
- : ''}"
335
- >
336
- {#each rows as row, i (i)}
337
- <li class="gap-2 flex">
338
- {#if row.level === 'error'}
339
- <CircleAlert class="mt-0.5 h-4 w-4 shrink-0 text-destructive" />
340
- {:else if row.level === 'warning'}
341
- <TriangleAlert class="mt-0.5 h-4 w-4 text-amber-500 shrink-0" />
342
- {:else}
343
- <Info class="mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" />
344
- {/if}
345
- <div class="min-w-0 flex-1">
346
- <p class="wrap-anywhere">{row.message}</p>
347
- {#if row.source}
348
- <p class="text-xs text-muted-foreground">{row.source}</p>
349
- {/if}
350
- </div>
351
- </li>
352
- {/each}
353
- </ul>
405
+ <div class="max-h-40 overflow-y-auto {view === 'live' ? 'mt-3 pt-3 border-t' : ''}">
406
+ <IssueList {issues} variant="plain" />
407
+ </div>
354
408
  {/if}
355
409
 
356
- {#if view === 'review' || view === 'blocked'}
410
+ {#if (view === 'review' || view === 'blocked') && placement === 'floating'}
357
411
  <div class="mt-3 gap-2 flex justify-end">
358
412
  {#if view === 'blocked'}
359
- <Button variant="outline" size="sm" onclick={dismiss}>{labels.dismiss}</Button>
413
+ <Button variant="outline" size="sm" onclick={dismiss}>{t.solveMessagesDismiss}</Button>
360
414
  {:else}
361
- <Button variant="outline" size="sm" onclick={ondiscard}>{labels.discard}</Button>
362
- <Button size="sm" onclick={onconfirm}>{labels.confirm}</Button>
415
+ <Button variant="outline" size="sm" onclick={ondiscard}>{t.solveMessagesDiscard}</Button>
416
+ <Button size="sm" onclick={onconfirm}>{t.solveMessagesConfirm}</Button>
363
417
  {/if}
364
418
  </div>
365
419
  {/if}
@@ -1,16 +1,5 @@
1
1
  import type { SolveDiagnostic } from '@selvajs/solve/shared';
2
2
  import type { LiveSolveState, SolvePhase } from '@selvajs/solve/client';
3
- interface Labels {
4
- solving: string;
5
- blockedTitle: string;
6
- messagesTitle: string;
7
- blockedDescription: string;
8
- messagesDescription: string;
9
- confirm: string;
10
- discard: string;
11
- abort: string;
12
- dismiss: string;
13
- }
14
3
  interface Props {
15
4
  /** What the running (or most recent) solve has said over the live channel. */
16
5
  live: LiveSolveState;
@@ -21,7 +10,13 @@ interface Props {
21
10
  onabort: () => void;
22
11
  onconfirm: () => void;
23
12
  ondiscard: () => void;
24
- labels?: Labels;
13
+ /**
14
+ * See `createSolvingIndicator`. The live panel would only paint once the solve is over, so
15
+ * an Esc hint stands in for it; the result's messages still show.
16
+ */
17
+ freezesDuringSolve?: boolean;
18
+ /** `floating` overlays the bottom centre; `inline` sits in the flow below the host's content. */
19
+ placement?: 'floating' | 'inline';
25
20
  }
26
21
  declare const SolveMessages: import("svelte").Component<Props, {}, "">;
27
22
  type SolveMessages = ReturnType<typeof SolveMessages>;
@@ -74,14 +74,16 @@
74
74
 
75
75
  const rootClass = $derived(
76
76
  _mode === 'fixed'
77
- ? `flex flex-col h-screen overflow-hidden bg-background ${className}`
78
- : `flex flex-col min-h-screen bg-background ${className}`
77
+ ? // dvh, not vh: iOS sizes 100vh to the viewport without its toolbar, which hides the
78
+ // footer and the phone drawer's handle behind the toolbar.
79
+ `flex flex-col h-dvh overflow-hidden bg-background ${className}`
80
+ : `flex flex-col min-h-dvh bg-background ${className}`
79
81
  );
80
82
 
81
83
  const bodyShellClass = $derived(
82
84
  _mode === 'fixed'
83
- ? `flex flex-1 min-h-0 ${sidenav ? 'flex-row' : 'flex-col'} ${bodyClass}`.trim()
84
- : `flex-1 ${sidenav ? 'flex flex-row' : ''} ${bodyClass}`.trim()
85
+ ? `flex flex-1 min-h-0 ${sidenav ? 'flex-col sm:flex-row' : 'flex-col'} ${bodyClass}`.trim()
86
+ : `flex-1 ${sidenav ? 'flex flex-col sm:flex-row' : ''} ${bodyClass}`.trim()
85
87
  );
86
88
 
87
89
  const bodyShellStyle = '';
@@ -92,13 +94,15 @@
92
94
  const sidenavWrapClass = $derived(
93
95
  _mode === 'fixed'
94
96
  ? 'flex shrink-0'
95
- : 'flex shrink-0 self-start sticky top-(--header-h) max-h-[calc(100svh-var(--header-h))]'
97
+ : 'flex shrink-0 sm:self-start sm:sticky sm:top-(--header-h) sm:max-h-(--below-header-h)'
96
98
  );
97
99
 
98
100
  // The sticky wrapper is only as tall as its content, so in scroll mode the divider comes
99
101
  // from the main column's left edge — that one spans the full body height.
100
102
  const mainClass = $derived(
101
- _mode === 'fixed' ? 'flex-1 overflow-y-auto' : 'flex-1 overflow-y-auto border-l border-border'
103
+ _mode === 'fixed'
104
+ ? 'min-h-0 flex-1 overflow-y-auto'
105
+ : 'min-w-0 flex-1 overflow-y-auto border-border sm:border-l'
102
106
  );
103
107
  </script>
104
108
 
@@ -5,6 +5,8 @@
5
5
  import { useFooter } from '../../contexts/footerContext.svelte';
6
6
  import ComputeMessagesDialog from '../compute/ComputeMessagesDialog.svelte';
7
7
  import FooterItemRenderer from './FooterItemRenderer.svelte';
8
+ import { getLocaleContext } from '../../i18n/localeContext.svelte';
9
+ import { formatCount, formatMessage } from '../../i18n/messages';
8
10
 
9
11
  interface Props {
10
12
  errors?: string[];
@@ -26,6 +28,9 @@
26
28
  children
27
29
  }: Props = $props();
28
30
 
31
+ const locale = getLocaleContext();
32
+ const t = $derived(locale.messages);
33
+
29
34
  let footerStore = (() => {
30
35
  try {
31
36
  return useFooter();
@@ -66,16 +71,15 @@
66
71
  const hasMessages = $derived(totalCount > 0);
67
72
 
68
73
  const copyrightLine = $derived(
69
- footerText
70
- ? footerText.replace('{name}', copyrightName).replace('{year}', String(_currentYear))
71
- : `by ${copyrightName} © ${_currentYear}`
74
+ formatMessage(footerText ?? t.copyright, { name: copyrightName, year: _currentYear })
72
75
  );
73
76
  </script>
74
77
 
78
+ <!-- One line at any width: the message counts keep their size and the copyright truncates. -->
75
79
  <footer
76
- class="px-4 gap-4 text-xs h-7 flex shrink-0 items-center justify-between border-t border-border bg-background text-muted-foreground select-none"
80
+ class="px-4 gap-4 text-xs h-7 flex shrink-0 items-center justify-between border-t border-border bg-background whitespace-nowrap text-muted-foreground select-none"
77
81
  >
78
- <div class="gap-4 flex items-center">
82
+ <div class="gap-4 flex shrink-0 items-center">
79
83
  {#each leftItems as item (item.id)}
80
84
  <FooterItemRenderer {item} />
81
85
  {/each}
@@ -90,11 +94,13 @@
90
94
  : warningCount > 0
91
95
  ? 'text-warning hover:bg-warning/10'
92
96
  : 'hover:bg-muted'}"
93
- title={`${totalCount} ${totalCount === 1 ? 'message' : 'messages'} from the last solve`}
97
+ title={formatCount(totalCount, t.lastSolveMessagesOne, t.lastSolveMessagesOther)}
94
98
  >
95
99
  {#if errorCount > 0}
96
100
  <CircleAlert class="h-3.5 w-3.5" />
97
- <span class="font-medium">{errorCount} Error{errorCount !== 1 ? 's' : ''}</span>
101
+ <span class="font-medium"
102
+ >{formatCount(errorCount, t.errorCountOne, t.errorCountOther)}</span
103
+ >
98
104
  {/if}
99
105
 
100
106
  {#if warningCount > 0}
@@ -102,12 +108,16 @@
102
108
  <span class="text-border">•</span>
103
109
  {/if}
104
110
  <TriangleAlert class="h-3.5 w-3.5" />
105
- <span class="font-medium">{warningCount} Warning{warningCount !== 1 ? 's' : ''}</span>
111
+ <span class="font-medium"
112
+ >{formatCount(warningCount, t.warningCountOne, t.warningCountOther)}</span
113
+ >
106
114
  {/if}
107
115
 
108
116
  {#if errorCount === 0 && warningCount === 0}
109
117
  <Info class="h-3.5 w-3.5" />
110
- <span class="font-medium">{remarkCount} Note{remarkCount !== 1 ? 's' : ''}</span>
118
+ <span class="font-medium"
119
+ >{formatCount(remarkCount, t.noteCountOne, t.noteCountOther)}</span
120
+ >
111
121
  {/if}
112
122
  </div>
113
123
  {/snippet}
@@ -121,11 +131,13 @@
121
131
  {/if}
122
132
  </div>
123
133
 
124
- <div class="gap-4 ml-auto flex items-center">
134
+ <div class="gap-4 min-w-0 ml-auto flex items-center">
125
135
  {#each rightItems as item (item.id)}
126
136
  <FooterItemRenderer {item} />
127
137
  {/each}
128
138
 
129
- <p>{copyrightLine}</p>
139
+ {#if copyrightLine}
140
+ <p class="truncate">{copyrightLine}</p>
141
+ {/if}
130
142
  </div>
131
143
  </footer>
@@ -31,27 +31,31 @@
31
31
  <header
32
32
  class={`top-0 backdrop-blur-sm sticky z-40 border-b border-border bg-background/90 ${className}`}
33
33
  >
34
- <div class="gap-5 flex h-(--header-h) items-center px-(--page-px)">
34
+ <div class="gap-2 sm:gap-5 flex h-(--header-h) items-center px-(--page-px)">
35
35
  <!-- Logo -->
36
- <a href={homeUrl} class="gap-2 flex shrink-0 items-center">
36
+ <a href={homeUrl} class="gap-2 flex shrink-0 items-center" aria-label={brandName}>
37
37
  <img src={logo} alt="" aria-hidden="true" class="h-5 w-5" />
38
- <span class="font-semibold text-sm tracking-tight">{brandName}</span>
38
+ <!-- On a phone the page title needs the room more than the brand does. -->
39
+ <span
40
+ class="font-semibold text-sm tracking-tight {title !== undefined ? 'sm:inline hidden' : ''}"
41
+ >{brandName}</span
42
+ >
39
43
  </a>
40
44
 
41
45
  {#if title !== undefined}
42
- <span class="text-sm text-border">/</span>
43
- <span class="text-sm font-medium text-muted-foreground">{title ?? ''}</span>
46
+ <span class="text-sm shrink-0 text-border">/</span>
47
+ <span class="text-sm font-medium min-w-0 truncate text-muted-foreground">{title ?? ''}</span>
44
48
  {/if}
45
49
 
46
50
  <!-- Primary nav next to logo -->
47
51
  {#if navItems}
48
- <nav class="ml-5 gap-1 flex">
52
+ <nav class="sm:ml-5 gap-1 flex shrink-0">
49
53
  {@render navItems()}
50
54
  </nav>
51
55
  {/if}
52
56
 
53
57
  <!-- Right cluster: identity + utilities, anchored flush-right -->
54
- <div class="gap-2 ml-auto flex items-center">
58
+ <div class="gap-2 ml-auto flex shrink-0 items-center">
55
59
  {#if rightContent}
56
60
  {@render rightContent()}
57
61
  {/if}
@@ -40,23 +40,21 @@
40
40
  </p>
41
41
  <div class="gap-1 flex items-center">
42
42
  <Button
43
- size="sm"
43
+ size="icon-sm"
44
44
  variant="outline"
45
45
  disabled={page <= 1}
46
46
  onclick={() => (page -= 1)}
47
47
  aria-label="Previous page"
48
- class="h-8 w-8 p-0"
49
48
  >
50
49
  <ChevronLeft class="h-4 w-4" />
51
50
  </Button>
52
51
  <span class="px-2 font-mono text-xs text-muted-foreground">{page} / {pageCount}</span>
53
52
  <Button
54
- size="sm"
53
+ size="icon-sm"
55
54
  variant="outline"
56
55
  disabled={page >= pageCount}
57
56
  onclick={() => (page += 1)}
58
57
  aria-label="Next page"
59
- class="h-8 w-8 p-0"
60
58
  >
61
59
  <ChevronRight class="h-4 w-4" />
62
60
  </Button>
@@ -18,7 +18,9 @@
18
18
  }: SectionHeaderProps = $props();
19
19
  </script>
20
20
 
21
- <div class={`mb-6 gap-5 flex items-start justify-between ${className}`}>
21
+ <div
22
+ class={`mb-6 gap-3 sm:gap-5 sm:flex-row sm:items-start sm:justify-between flex flex-col ${className}`}
23
+ >
22
24
  <div class="min-w-0">
23
25
  {#if eyebrow}
24
26
  <div class="mb-1.5 text-xs font-medium tracking-wider text-muted-foreground uppercase">
@@ -31,7 +33,7 @@
31
33
  {/if}
32
34
  </div>
33
35
  {#if actions}
34
- <div class="gap-2 flex shrink-0 items-center">
36
+ <div class="gap-2 flex shrink-0 flex-wrap items-center">
35
37
  {@render actions()}
36
38
  </div>
37
39
  {/if}