@selvajs/ui 6.5.1-beta.0 → 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 +15 -15
  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
@@ -4,6 +4,7 @@
4
4
  FileInputWidgetConfig,
5
5
  DynamicValueListWidgetConfig,
6
6
  DropdownWidgetConfig,
7
+ UISchema,
7
8
  SupportedTypes
8
9
  } from '@selvajs/schemas';
9
10
  import {
@@ -16,18 +17,30 @@
16
17
  isColorWidget
17
18
  } from '@selvajs/schemas';
18
19
  import * as Field from '../primitives/field';
19
- import * as Dialog from '../primitives/dialog';
20
- import { HelpCircle } from '@lucide/svelte';
20
+ import { Button } from '../primitives/button';
21
+ import { toast } from '../primitives/sonner';
22
+ import HelpButton from './HelpButton.svelte';
21
23
  import {
22
24
  CheckboxInput,
23
25
  ChecklistInput,
24
26
  ColorInput,
25
27
  DropdownInput,
26
28
  FileInput,
29
+ GeometryInput,
27
30
  NumberInput,
28
- TextInput
31
+ SegmentedInput,
32
+ TextInput,
33
+ TileInput
29
34
  } from './inputs';
30
35
  import { getClientSlot } from '../../contexts/clientSlotContext.svelte';
36
+ import {
37
+ getHostContext,
38
+ type GeometryPickTarget,
39
+ type PickKind
40
+ } from '../../contexts/hostContext.svelte';
41
+ import { getLocaleContext } from '../../i18n/localeContext.svelte';
42
+ import { isGeometryParamType, isTriggerItem } from '../../schema/host-support';
43
+ import { resolveOptionDisplay } from '../../schema/option-display';
31
44
 
32
45
  interface Props {
33
46
  item: InputLayoutItem;
@@ -42,6 +55,10 @@
42
55
  disabled?: boolean;
43
56
  /** Runtime-computed options for a dynamic value list input (name -> value). */
44
57
  dynamicOptions?: Record<string, string>;
58
+ /** The input's paramType: a geometry input gets its control from this, not from the widget type. */
59
+ paramType?: string;
60
+ /** The schema's icons and thumbnails, which value-list options point into. */
61
+ assets?: UISchema['assets'];
45
62
  }
46
63
 
47
64
  let {
@@ -50,9 +67,26 @@
50
67
  displayName,
51
68
  onChange,
52
69
  disabled = false,
53
- dynamicOptions
70
+ dynamicOptions,
71
+ paramType,
72
+ assets
54
73
  }: Props = $props();
55
74
 
75
+ const locale = getLocaleContext();
76
+ const hostActions = getHostContext();
77
+ const { pickGeometry, clearGeometry, onGeometrySummary } = hostActions;
78
+ const isGeometry = $derived(isGeometryParamType(paramType));
79
+ const isTrigger = $derived(isTriggerItem(item));
80
+ const pickTarget = $derived(
81
+ isGeometry ? hostActions.describeGeometry?.(item.paramId) : undefined
82
+ );
83
+
84
+ // Get Point/Line/Plane take their own kind; Get Geometry takes what its filter allows.
85
+ function pickKinds(target: GeometryPickTarget | undefined): readonly PickKind[] | undefined {
86
+ if (paramType === 'point' || paramType === 'line' || paramType === 'plane') return [paramType];
87
+ return target?.kinds;
88
+ }
89
+
56
90
  const inputId = $derived(`input-${item.paramId}`);
57
91
  const label = $derived(displayName || item.displayName || item.paramId);
58
92
 
@@ -65,15 +99,15 @@
65
99
  });
66
100
  const clientSlot = getClientSlot();
67
101
 
68
- // Min/max hint rendered next to the label. `hideRange` lets the author suppress it.
102
+ // Sliders never show the hint: the track already conveys the bounds.
69
103
  const numberRangeHint = $derived.by(() => {
70
104
  if (!isNumberWidget(item)) return null;
71
105
  const cfg = item.config;
72
- if (cfg?.hideRange) return null;
106
+ if (cfg?.hideRange || cfg?.renderAsSlider) return null;
73
107
  const hasMin = typeof cfg?.minimum === 'number';
74
108
  const hasMax = typeof cfg?.maximum === 'number';
75
109
  if (!hasMin && !hasMax) return null;
76
- if (hasMin && hasMax) return `${cfg!.minimum} to ${cfg!.maximum}`;
110
+ if (hasMin && hasMax) return `${cfg!.minimum} – ${cfg!.maximum}`;
77
111
  if (hasMin) return `≥ ${cfg!.minimum}`;
78
112
  return `≤ ${cfg!.maximum}`;
79
113
  });
@@ -100,7 +134,8 @@
100
134
  // As a dropdown config so DropdownInput/ChecklistInput can consume it unchanged.
101
135
  const dynamicListAsDropdownConfig = $derived<DropdownWidgetConfig>({
102
136
  options: dynamicListOptions,
103
- displayAs: dynamicListConfig?.displayAs ?? 'dropdown'
137
+ displayAs: dynamicListConfig?.displayAs ?? 'dropdown',
138
+ optionMedia: dynamicListConfig?.optionMedia
104
139
  });
105
140
  const hideDynamicListWhenEmpty = $derived(
106
141
  isDynamicValueListWidget(item) &&
@@ -171,59 +206,132 @@
171
206
  }
172
207
  </script>
173
208
 
209
+ {#snippet valueList(config: DropdownWidgetConfig)}
210
+ {@const display = resolveOptionDisplay(
211
+ config.displayAs,
212
+ Object.keys(config.options ?? {}).length
213
+ )}
214
+ {@const single = typeof value === 'string' ? value : ''}
215
+ {#if display === 'checklist'}
216
+ <ChecklistInput
217
+ {inputId}
218
+ value={Array.isArray(value)
219
+ ? (value as string[])
220
+ : typeof value === 'string' && value
221
+ ? [value]
222
+ : []}
223
+ {config}
224
+ {assets}
225
+ onChange={commit}
226
+ {disabled}
227
+ />
228
+ {:else if display === 'segmented'}
229
+ <SegmentedInput
230
+ labelId="{inputId}-label"
231
+ value={single}
232
+ {config}
233
+ {assets}
234
+ onChange={commit}
235
+ {disabled}
236
+ />
237
+ {:else if display === 'tiles'}
238
+ <TileInput
239
+ labelId="{inputId}-label"
240
+ value={single}
241
+ {config}
242
+ {assets}
243
+ onChange={commit}
244
+ {disabled}
245
+ />
246
+ {:else}
247
+ <DropdownInput value={single} {config} {assets} onChange={commit} {disabled} />
248
+ {/if}
249
+ {/snippet}
250
+
251
+ {#snippet labelText(forId?: string, tone: 'quiet' | 'strong' = 'quiet')}
252
+ <Field.Label
253
+ for={forId}
254
+ id={forId ? `${forId}-label` : undefined}
255
+ class="min-w-0 block break-words"
256
+ >
257
+ <span
258
+ class={tone === 'quiet' ? 'font-normal text-muted-foreground' : 'font-normal text-foreground'}
259
+ >{label}</span
260
+ >
261
+ </Field.Label>
262
+ {/snippet}
263
+
264
+ {#snippet helpButton()}
265
+ {#if item.description}
266
+ <HelpButton {label} description={item.description} />
267
+ {/if}
268
+ {/snippet}
269
+
270
+ {#snippet fieldHeader(forId?: string)}
271
+ <div class="gap-1.5 min-h-5 min-w-0 flex items-center">
272
+ {@render labelText(forId)}
273
+ {@render helpButton()}
274
+ {#if showRangeInLabel}
275
+ <span
276
+ class="text-xs pl-2 ml-auto hidden shrink-0 whitespace-nowrap text-muted-foreground tabular-nums group-focus-within/field:inline"
277
+ >
278
+ {numberRangeHint}
279
+ </span>
280
+ {/if}
281
+ </div>
282
+ {/snippet}
283
+
174
284
  {#if isClientSlot}
175
285
  {#if clientSlot}
176
- <Field.Field>
177
- <Field.Label class="gap-2 flex items-center">
178
- {label}
179
- {#if item.description}
180
- <Dialog.Root>
181
- <Dialog.Trigger class="p-1 cursor-help opacity-60 transition-opacity hover:opacity-100">
182
- <HelpCircle size={16} />
183
- </Dialog.Trigger>
184
- <Dialog.Content class="sm:max-w-md">
185
- <Dialog.Header>
186
- <Dialog.Title>{label}</Dialog.Title>
187
- <Dialog.Description>{item.description}</Dialog.Description>
188
- </Dialog.Header>
189
- </Dialog.Content>
190
- </Dialog.Root>
191
- {/if}
192
- </Field.Label>
286
+ <div role="group" class="group/field gap-1.5 min-w-0 flex flex-col">
287
+ {@render fieldHeader()}
193
288
  {@render clientSlot({
194
289
  inputId: item.paramId,
195
290
  displayName: label,
196
291
  value,
197
292
  onValueChange: commit
198
293
  })}
199
- </Field.Field>
294
+ </div>
200
295
  {/if}
296
+ {:else if isGeometry}
297
+ <div role="group" class="group/field gap-1.5 min-w-0 flex flex-col">
298
+ {@render fieldHeader(inputId)}
299
+ <GeometryInput
300
+ {inputId}
301
+ kinds={pickKinds(pickTarget)}
302
+ atMost={pickTarget?.atMost}
303
+ summary={typeof value === 'string' ? value : undefined}
304
+ onPick={pickGeometry && (() => pickGeometry(item.paramId))}
305
+ onClear={clearGeometry && (() => clearGeometry(item.paramId))}
306
+ watchSummary={onGeometrySummary && ((listener) => onGeometrySummary(item.paramId, listener))}
307
+ onError={(message) => toast.error(message)}
308
+ {disabled}
309
+ />
310
+ </div>
311
+ {:else if isTrigger}
312
+ <div role="group" class="group/field gap-1.5 min-w-0 flex items-center" data-control-line>
313
+ <Button
314
+ id={inputId}
315
+ variant="outline"
316
+ class="min-w-0 flex-1"
317
+ onclick={() => hostActions.trigger?.(item.paramId)}
318
+ disabled={disabled || !hostActions.trigger || hostActions.isSolving?.()}
319
+ >
320
+ <span class="truncate">{label}</span>
321
+ </Button>
322
+ {@render helpButton()}
323
+ </div>
201
324
  {:else if !hideDynamicListWhenEmpty}
202
- <Field.Field>
203
- <Field.Label for={inputId} class="gap-2 flex items-center">
204
- {label}
205
- {#if item.description}
206
- <Dialog.Root>
207
- <Dialog.Trigger class="p-1 cursor-help opacity-60 transition-opacity hover:opacity-100">
208
- <HelpCircle size={16} />
209
- </Dialog.Trigger>
210
- <Dialog.Content class="sm:max-w-md">
211
- <Dialog.Header>
212
- <Dialog.Title>{label}</Dialog.Title>
213
- <Dialog.Description>{item.description}</Dialog.Description>
214
- </Dialog.Header>
215
- </Dialog.Content>
216
- </Dialog.Root>
217
- {/if}
218
- {#if showRangeInLabel}
219
- <span class="text-xs font-normal text-muted-foreground">{numberRangeHint}</span>
220
- {/if}
221
- </Field.Label>
325
+ <div role="group" class="group/field gap-1.5 min-w-0 flex flex-col">
326
+ {#if !isCheckboxWidget(item)}
327
+ {@render fieldHeader(inputId)}
328
+ {/if}
222
329
 
223
330
  {#if isNumberWidget(item)}
224
331
  {@const config = item.config}
225
332
  <NumberInput
226
333
  {inputId}
334
+ labelId="{inputId}-label"
227
335
  value={typeof value === 'number' ? value : undefined}
228
336
  {config}
229
337
  onChange={commit}
@@ -235,7 +343,10 @@
235
343
  value={typeof value === 'boolean' ? value : undefined}
236
344
  onChange={commit}
237
345
  {disabled}
238
- />
346
+ >
347
+ {@render labelText(inputId, 'strong')}
348
+ {@render helpButton()}
349
+ </CheckboxInput>
239
350
  {:else if isTextWidget(item)}
240
351
  {@const config = item.config}
241
352
  <TextInput
@@ -246,51 +357,12 @@
246
357
  {disabled}
247
358
  />
248
359
  {:else if isDropdownWidget(item)}
249
- {@const config = item.config}
250
- {#if config.displayAs === 'checklist'}
251
- <ChecklistInput
252
- {inputId}
253
- value={Array.isArray(value)
254
- ? (value as string[])
255
- : typeof value === 'string' && value
256
- ? [value]
257
- : []}
258
- {config}
259
- onChange={commit}
260
- {disabled}
261
- />
262
- {:else}
263
- <DropdownInput
264
- value={typeof value === 'string' ? value : ''}
265
- {config}
266
- onChange={commit}
267
- {disabled}
268
- />
269
- {/if}
360
+ {@render valueList(item.config)}
270
361
  {:else if isDynamicValueListWidget(item)}
271
362
  {#if dynamicListHasOptions}
272
- {#if dynamicListAsDropdownConfig.displayAs === 'checklist'}
273
- <ChecklistInput
274
- {inputId}
275
- value={Array.isArray(value)
276
- ? (value as string[])
277
- : typeof value === 'string' && value
278
- ? [value]
279
- : []}
280
- config={dynamicListAsDropdownConfig}
281
- onChange={commit}
282
- {disabled}
283
- />
284
- {:else}
285
- <DropdownInput
286
- value={typeof value === 'string' ? value : ''}
287
- config={dynamicListAsDropdownConfig}
288
- onChange={commit}
289
- {disabled}
290
- />
291
- {/if}
363
+ {@render valueList(dynamicListAsDropdownConfig)}
292
364
  {:else}
293
- <p class="text-sm text-muted-foreground">No options available yet.</p>
365
+ <p class="text-sm text-muted-foreground">{locale.messages.noOptionsYet}</p>
294
366
  {/if}
295
367
  {:else if isFileWidget(item)}
296
368
  {@const config = item.config as FileInputWidgetConfig}
@@ -303,9 +375,10 @@
303
375
  />
304
376
  {:else if isColorWidget(item)}
305
377
  <ColorInput
378
+ {inputId}
306
379
  value={typeof value === 'string' ? value : '#000000'}
307
380
  onChange={(newValue) => commit(newValue)}
308
381
  />
309
382
  {/if}
310
- </Field.Field>
383
+ </div>
311
384
  {/if}
@@ -1,4 +1,4 @@
1
- import type { InputLayoutItem, SupportedTypes } from '@selvajs/schemas';
1
+ import type { InputLayoutItem, UISchema, SupportedTypes } from '@selvajs/schemas';
2
2
  interface Props {
3
3
  item: InputLayoutItem;
4
4
  value?: SupportedTypes;
@@ -12,6 +12,10 @@ interface Props {
12
12
  disabled?: boolean;
13
13
  /** Runtime-computed options for a dynamic value list input (name -> value). */
14
14
  dynamicOptions?: Record<string, string>;
15
+ /** The input's paramType: a geometry input gets its control from this, not from the widget type. */
16
+ paramType?: string;
17
+ /** The schema's icons and thumbnails, which value-list options point into. */
18
+ assets?: UISchema['assets'];
15
19
  }
16
20
  declare const InputControl: import("svelte").Component<Props, {}, "value">;
17
21
  type InputControl = ReturnType<typeof InputControl>;
@@ -10,10 +10,12 @@
10
10
  isFileData
11
11
  } from '../../utils/file-download';
12
12
  import { Button } from '../primitives';
13
- import * as Dialog from '../primitives/dialog';
14
- import { Info, Folder, FolderOpen, FileIcon, ChevronRight } from '@lucide/svelte';
13
+ import { Folder, FolderOpen, FileIcon, ChevronRight } from '@lucide/svelte';
14
+ import HelpButton from './HelpButton.svelte';
15
15
  import { SvelteMap, SvelteSet } from 'svelte/reactivity';
16
16
  import { Label } from '../primitives/label';
17
+ import { getLocaleContext } from '../../i18n/localeContext.svelte';
18
+ import { formatCount, formatMessage } from '../../i18n/messages';
17
19
 
18
20
  interface Props {
19
21
  item: OutputLayoutItem;
@@ -23,6 +25,9 @@
23
25
 
24
26
  let { item, value, displayName }: Props = $props();
25
27
 
28
+ const locale = getLocaleContext();
29
+ const t = $derived(locale.messages);
30
+
26
31
  let copied = $state(false);
27
32
  let copyTimeout: ReturnType<typeof setTimeout>;
28
33
 
@@ -142,7 +147,7 @@
142
147
  await downloadFiles(filesArray, fileName);
143
148
  }
144
149
  } catch (err) {
145
- downloadError = err instanceof Error ? err.message : 'Failed to download files';
150
+ downloadError = err instanceof Error ? err.message : t.downloadFailed;
146
151
  console.error('[OutputDisplayWidget] Download error:', err);
147
152
  } finally {
148
153
  downloading = false;
@@ -154,23 +159,13 @@
154
159
  <div class="gap-2 flex items-center">
155
160
  <Label>{label}</Label>
156
161
  {#if item.description}
157
- <Dialog.Root>
158
- <Dialog.Trigger class="p-1 cursor-help opacity-60 transition-opacity hover:opacity-100">
159
- <Info size={16} />
160
- </Dialog.Trigger>
161
- <Dialog.Content class="sm:max-w-md">
162
- <Dialog.Header>
163
- <Dialog.Title>{label}</Dialog.Title>
164
- <Dialog.Description>{item.description}</Dialog.Description>
165
- </Dialog.Header>
166
- </Dialog.Content>
167
- </Dialog.Root>
162
+ <HelpButton {label} description={item.description} />
168
163
  {/if}
169
164
  </div>
170
165
  {/snippet}
171
166
 
172
167
  {#snippet placeholder()}
173
- <span class="text-muted-foreground not-italic">Waiting for data...</span>
168
+ <span class="text-muted-foreground not-italic">{t.waitingForData}</span>
174
169
  {/snippet}
175
170
 
176
171
  {#snippet treeNodes(nodes: Map<string, TreeNode>, path: string)}
@@ -219,7 +214,7 @@
219
214
  {#snippet fileDisplay()}
220
215
  {#if fileCount === 0}
221
216
  <div class="rounded px-3 py-3 text-sm border border-border bg-muted text-muted-foreground">
222
- Waiting for file data...
217
+ {t.waitingForFiles}
223
218
  </div>
224
219
  {:else}
225
220
  <div class="gap-2 flex flex-col">
@@ -228,7 +223,7 @@
228
223
  <span class="min-w-0 text-sm font-medium truncate text-foreground">
229
224
  {fileCount === 1
230
225
  ? `${filesArray[0].fileName}${filesArray[0].fileType}`
231
- : `${fileCount} files`}
226
+ : formatMessage(t.fileCount, { count: fileCount })}
232
227
  </span>
233
228
  <span class="text-xs shrink-0 text-muted-foreground">{formatFileSize(totalSize)}</span>
234
229
  </div>
@@ -255,18 +250,16 @@
255
250
  <div
256
251
  class="rounded px-3 py-2 text-sm border border-destructive bg-destructive/10 text-destructive"
257
252
  >
258
- <div class="font-medium">Duplicate file names detected</div>
253
+ <div class="font-medium">{t.duplicateFilesTitle}</div>
259
254
  <div class="mt-1 text-xs">
260
- The following {duplicatePaths.length === 1 ? 'path appears' : 'paths appear'} more than once:
255
+ {formatCount(duplicatePaths.length, t.duplicatePathsOne, t.duplicatePathsOther)}
261
256
  </div>
262
257
  <ul class="mt-1 ml-4 text-xs list-disc">
263
258
  {#each duplicatePaths as path (path)}
264
259
  <li class="truncate"><span class="font-mono">{path}</span></li>
265
260
  {/each}
266
261
  </ul>
267
- <div class="mt-1 text-xs">
268
- Rename outputs in your Grasshopper definition so each file has a unique name.
269
- </div>
262
+ <div class="mt-1 text-xs">{t.duplicateFilesHint}</div>
270
263
  </div>
271
264
  {/if}
272
265
  {#if downloadError}
@@ -278,8 +271,10 @@
278
271
  {/if}
279
272
  <Button onclick={handleDownload} disabled={downloading || hasDuplicates} class="w-full">
280
273
  {downloading
281
- ? 'Downloading...'
282
- : `Download ${fileCount === 1 ? 'File' : `${fileCount} Files`}`}
274
+ ? t.downloading
275
+ : fileCount === 1
276
+ ? t.downloadFile
277
+ : formatMessage(t.downloadFiles, { count: fileCount })}
283
278
  </Button>
284
279
  </div>
285
280
  {/if}
@@ -287,7 +282,7 @@
287
282
 
288
283
  <!-- Dynamic value list outputs are routing sinks (their options feed an input), not displayed. -->
289
284
  {#if item.widgetType !== 'dynamicValueList'}
290
- <div class="gap-2 flex flex-col">
285
+ <div role="group" class="group/field gap-2 flex flex-col">
291
286
  {@render fieldHeader()}
292
287
 
293
288
  {#if item.widgetType === 'chart'}
@@ -311,24 +306,24 @@
311
306
  <div class="group relative">
312
307
  {#if isObjectValue}
313
308
  <pre
314
- class="{boxClass} overflow-wrap-anywhere max-h-96 overflow-auto bg-muted/10 text-foreground">{formattedValue}</pre>
309
+ class="{boxClass} max-h-96 overflow-auto bg-muted/10 wrap-anywhere text-foreground">{formattedValue}</pre>
315
310
  {:else}
316
311
  <div
317
- class="{boxClass} overflow-wrap-anywhere bg-muted/10 wrap-break-word whitespace-pre-wrap text-foreground"
312
+ class="{boxClass} bg-muted/10 wrap-anywhere wrap-break-word whitespace-pre-wrap text-foreground"
318
313
  >
319
314
  {#if hasValue}{value}{:else}{@render placeholder()}{/if}
320
315
  </div>
321
316
  {/if}
322
317
  {#if hasValue}
323
- <Button
324
- onclick={copyToClipboard}
318
+ <div
325
319
  class="right-2 top-2 absolute transition-opacity {copied
326
320
  ? 'opacity-100'
327
- : 'opacity-0 group-hover:opacity-100'}"
328
- size="sm"
321
+ : 'opacity-0 group-hover:opacity-100 focus-within:opacity-100 pointer-coarse:opacity-100'}"
329
322
  >
330
- {copied ? 'Copied!' : 'Copy'}
331
- </Button>
323
+ <Button onclick={copyToClipboard} size="sm">
324
+ {copied ? t.copied : t.copy}
325
+ </Button>
326
+ </div>
332
327
  {/if}
333
328
  </div>
334
329
  {/if}
@@ -1,44 +1,73 @@
1
1
  <script lang="ts">
2
2
  import type { TabConfig } from '@selvajs/schemas';
3
3
  import * as Tabs from '../primitives/tabs';
4
- import { ScrollArea } from '../primitives/scroll-area';
4
+ import { ChevronLeft, ChevronRight } from '@lucide/svelte';
5
5
  import Icon from '@iconify/svelte';
6
+ import { getLocaleContext } from '../../i18n/localeContext.svelte';
7
+
8
+ const locale = getLocaleContext();
9
+ const t = $derived(locale.messages);
6
10
 
7
11
  interface Props {
8
12
  tabs: TabConfig[];
13
+ activeTabId: string;
9
14
  onTabChange: (tabId: string) => void;
10
15
  }
11
16
 
12
- let { tabs, onTabChange }: Props = $props();
17
+ let { tabs, activeTabId, onTabChange }: Props = $props();
18
+
19
+ const SCROLL_BUTTON_WIDTH = 32;
20
+
21
+ let listRef = $state<HTMLElement | null>(null);
22
+ let canScrollBack = $state(false);
23
+ let canScrollForward = $state(false);
24
+
25
+ function updateOverflow() {
26
+ if (!listRef) return;
27
+ const { scrollLeft, scrollWidth, clientWidth } = listRef;
28
+ canScrollBack = scrollLeft > 1;
29
+ canScrollForward = scrollLeft + clientWidth < scrollWidth - 1;
30
+ }
13
31
 
14
- let viewportRef = $state<HTMLElement | null>(null);
32
+ $effect(() => {
33
+ if (!listRef) return;
34
+ const observer = new ResizeObserver(updateOverflow);
35
+ observer.observe(listRef);
36
+ updateOverflow();
37
+ return () => observer.disconnect();
38
+ });
39
+
40
+ // A tab picked from the collapsed strip may sit outside the visible strip. Not
41
+ // scrollIntoView: that also scrolls every scrollable ancestor, e.g. the mobile drawer.
42
+ $effect(() => {
43
+ if (!listRef) return;
44
+ const active = listRef.querySelector<HTMLElement>(`[data-value="${CSS.escape(activeTabId)}"]`);
45
+ if (!active) return;
46
+ // Keep the tab clear of the scroll buttons, which overlay the strip's edges.
47
+ const start = active.offsetLeft - SCROLL_BUTTON_WIDTH;
48
+ const end = active.offsetLeft + active.offsetWidth + SCROLL_BUTTON_WIDTH;
49
+ if (start < listRef.scrollLeft) listRef.scrollLeft = start;
50
+ else if (end > listRef.scrollLeft + listRef.clientWidth)
51
+ listRef.scrollLeft = end - listRef.clientWidth;
52
+ });
53
+
54
+ function scrollByPage(direction: -1 | 1) {
55
+ listRef?.scrollBy({ left: direction * listRef.clientWidth * 0.7, behavior: 'smooth' });
56
+ }
15
57
 
16
58
  function handleWheel(e: WheelEvent) {
17
- if (!viewportRef) return;
59
+ if (!listRef || (!canScrollBack && !canScrollForward)) return;
18
60
  // Trackpad horizontal swipes already produce deltaX — let those pass through.
19
61
  if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) return;
20
- const canScroll = viewportRef.scrollWidth > viewportRef.clientWidth;
21
- if (!canScroll) return;
22
62
  e.preventDefault();
23
- viewportRef.scrollLeft += e.deltaY;
63
+ listRef.scrollLeft += e.deltaY;
24
64
  }
25
65
  </script>
26
66
 
27
- <ScrollArea
28
- bind:viewportRef
29
- class="w-full shrink-0 border-b border-border"
30
- orientation="horizontal"
31
- onwheel={handleWheel}
32
- >
33
- <Tabs.List
34
- class="px-2 py-2 gap-0 inline-flex h-auto w-max justify-start rounded-none bg-transparent"
35
- >
67
+ <div class="tab-bar relative shrink-0 border-b border-border">
68
+ <Tabs.List bind:ref={listRef} variant="line" onscroll={updateOverflow} onwheel={handleWheel}>
36
69
  {#each tabs as tab (tab.id)}
37
- <Tabs.Trigger
38
- value={tab.id}
39
- onclick={() => onTabChange(tab.id)}
40
- class="group/tab gap-1.5 px-3 py-1 text-sm font-medium relative h-auto flex-none shrink-0 rounded-none border-0 transition-colors not-last:border-r not-last:border-border hover:bg-accent data-[state=active]:bg-transparent data-[state=active]:text-foreground data-[state=active]:shadow-none data-[state=inactive]:text-muted-foreground dark:data-[state=active]:border-transparent dark:data-[state=active]:bg-transparent"
41
- >
70
+ <Tabs.Trigger value={tab.id} onclick={() => onTabChange(tab.id)} variant="line">
42
71
  {#if tab.icon}
43
72
  {#if tab.icon.includes(':')}
44
73
  <Icon icon={tab.icon} class="h-4 w-4" />
@@ -50,4 +79,59 @@
50
79
  </Tabs.Trigger>
51
80
  {/each}
52
81
  </Tabs.List>
53
- </ScrollArea>
82
+
83
+ {#if canScrollBack}
84
+ <button
85
+ type="button"
86
+ class="scroll-button back"
87
+ aria-label={t.scrollTabsBack}
88
+ onclick={() => scrollByPage(-1)}
89
+ >
90
+ <ChevronLeft class="h-4 w-4" />
91
+ </button>
92
+ {/if}
93
+ {#if canScrollForward}
94
+ <button
95
+ type="button"
96
+ class="scroll-button forward"
97
+ aria-label={t.scrollTabsForward}
98
+ onclick={() => scrollByPage(1)}
99
+ >
100
+ <ChevronRight class="h-4 w-4" />
101
+ </button>
102
+ {/if}
103
+ </div>
104
+
105
+ <style>
106
+ .tab-bar :global([data-slot='tabs-list']) {
107
+ position: relative;
108
+ overflow-x: auto;
109
+ scrollbar-width: none;
110
+ }
111
+ .tab-bar :global([data-slot='tabs-list']::-webkit-scrollbar) {
112
+ display: none;
113
+ }
114
+
115
+ .scroll-button {
116
+ position: absolute;
117
+ top: 0;
118
+ bottom: 1px;
119
+ display: flex;
120
+ align-items: center;
121
+ color: var(--muted-foreground);
122
+ cursor: pointer;
123
+ }
124
+ .scroll-button:hover {
125
+ color: var(--foreground);
126
+ }
127
+ .scroll-button.back {
128
+ left: 0;
129
+ padding: 0 1.25rem 0 0.375rem;
130
+ background: linear-gradient(to right, var(--card) 55%, transparent);
131
+ }
132
+ .scroll-button.forward {
133
+ right: 0;
134
+ padding: 0 0.375rem 0 1.25rem;
135
+ background: linear-gradient(to left, var(--card) 55%, transparent);
136
+ }
137
+ </style>
@@ -1,6 +1,7 @@
1
1
  import type { TabConfig } from '@selvajs/schemas';
2
2
  interface Props {
3
3
  tabs: TabConfig[];
4
+ activeTabId: string;
4
5
  onTabChange: (tabId: string) => void;
5
6
  }
6
7
  declare const TabBar: import("svelte").Component<Props, {}, "">;