@selvajs/ui 6.6.0-beta.8 → 7.0.0

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 (373) hide show
  1. package/README.md +0 -3
  2. package/dist/components/ErrorScreen.svelte +1 -1
  3. package/dist/components/compute/AppLayout.svelte +95 -37
  4. package/dist/components/compute/AppLayout.svelte.d.ts +18 -1
  5. package/dist/components/compute/CollapsedPanelStrip.svelte +4 -2
  6. package/dist/components/compute/ComputeApp.svelte +6 -2
  7. package/dist/components/compute/ComputeApp.svelte.d.ts +1 -1
  8. package/dist/components/compute/ComputeMessagesDialog.svelte +3 -3
  9. package/dist/components/compute/ParameterPresetManager.svelte +9 -21
  10. package/dist/components/compute/SolveMessages.svelte +101 -87
  11. package/dist/components/compute/SolveMessages.svelte.d.ts +12 -0
  12. package/dist/components/layout/AppShell.svelte +2 -2
  13. package/dist/components/layout/FooterItemRenderer.svelte +2 -2
  14. package/dist/components/layout/FooterItemRenderer.svelte.d.ts +1 -1
  15. package/dist/components/layout/PageContent.svelte +3 -2
  16. package/dist/components/layout/PageFooter.svelte +8 -6
  17. package/dist/components/layout/PageHeader.svelte +3 -3
  18. package/dist/components/layout/SideNav.svelte +56 -15
  19. package/dist/components/layout/SubNav.svelte +2 -2
  20. package/dist/components/preview/ChartOutput.svelte +158 -62
  21. package/dist/components/preview/Group.svelte +14 -9
  22. package/dist/components/preview/HelpButton.svelte +1 -1
  23. package/dist/components/preview/ImageOutput.svelte +16 -11
  24. package/dist/components/preview/InputControl.svelte +115 -50
  25. package/dist/components/preview/InputControl.svelte.d.ts +5 -1
  26. package/dist/components/preview/OutputDisplay.svelte +26 -17
  27. package/dist/components/preview/TabBar.svelte +8 -6
  28. package/dist/components/preview/TabBar.svelte.d.ts +2 -0
  29. package/dist/components/preview/TabContent.svelte +65 -33
  30. package/dist/components/preview/TabContent.svelte.d.ts +5 -1
  31. package/dist/components/preview/TabLayout.svelte +29 -8
  32. package/dist/components/preview/TabLayout.svelte.d.ts +5 -0
  33. package/dist/components/preview/inputs/CheckboxInput.svelte +1 -1
  34. package/dist/components/preview/inputs/ChecklistInput.svelte +11 -6
  35. package/dist/components/preview/inputs/ChecklistInput.svelte.d.ts +2 -1
  36. package/dist/components/preview/inputs/ColorInput.svelte +356 -14
  37. package/dist/components/preview/inputs/ColorInput.svelte.d.ts +1 -0
  38. package/dist/components/preview/inputs/DropdownInput.svelte +18 -6
  39. package/dist/components/preview/inputs/DropdownInput.svelte.d.ts +2 -1
  40. package/dist/components/preview/inputs/FileInput.svelte +71 -75
  41. package/dist/components/preview/inputs/GeometryInput.svelte +128 -0
  42. package/dist/components/preview/inputs/GeometryInput.svelte.d.ts +21 -0
  43. package/dist/components/preview/inputs/NumberInput.svelte +8 -8
  44. package/dist/components/preview/inputs/OptionGlyph.svelte +29 -0
  45. package/dist/components/preview/inputs/OptionGlyph.svelte.d.ts +8 -0
  46. package/dist/components/preview/inputs/SegmentedInput.svelte +45 -0
  47. package/dist/components/preview/inputs/SegmentedInput.svelte.d.ts +12 -0
  48. package/dist/components/preview/inputs/TextInput.svelte +5 -5
  49. package/dist/components/preview/inputs/TileInput.svelte +83 -0
  50. package/dist/components/preview/inputs/TileInput.svelte.d.ts +12 -0
  51. package/dist/components/preview/inputs/index.d.ts +3 -0
  52. package/dist/components/preview/inputs/index.js +3 -0
  53. package/dist/components/primitives/CalculateButton.svelte +10 -4
  54. package/dist/components/primitives/Callout.svelte +8 -6
  55. package/dist/components/primitives/Callout.svelte.d.ts +4 -4
  56. package/dist/components/primitives/DataTable.svelte +1 -1
  57. package/dist/components/primitives/FilterableDropdown.svelte +13 -1
  58. package/dist/components/primitives/FilterableDropdown.svelte.d.ts +5 -0
  59. package/dist/components/primitives/ImageUploadField.svelte +1 -1
  60. package/dist/components/primitives/SolvingIndicator.svelte +245 -19
  61. package/dist/components/primitives/SolvingIndicator.svelte.d.ts +15 -0
  62. package/dist/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
  63. package/dist/components/primitives/badge/badge.svelte +2 -2
  64. package/dist/components/primitives/badge/badge.svelte.d.ts +6 -6
  65. package/dist/components/primitives/button/button.svelte +9 -7
  66. package/dist/components/primitives/button/button.svelte.d.ts +19 -16
  67. package/dist/components/primitives/card/card.svelte +1 -1
  68. package/dist/components/primitives/card/card.svelte.d.ts +1 -1
  69. package/dist/components/primitives/checkbox/checkbox.svelte +1 -1
  70. package/dist/components/primitives/command/command-input.svelte +1 -1
  71. package/dist/components/primitives/command/command-item.svelte +1 -1
  72. package/dist/components/primitives/command/command-link-item.svelte +1 -1
  73. package/dist/components/primitives/command/command.svelte +1 -1
  74. package/dist/components/primitives/context-menu/context-menu-checkbox-item.svelte +1 -1
  75. package/dist/components/primitives/context-menu/context-menu-content.svelte +1 -1
  76. package/dist/components/primitives/context-menu/context-menu-item.svelte +1 -1
  77. package/dist/components/primitives/context-menu/context-menu-radio-item.svelte +1 -1
  78. package/dist/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
  79. package/dist/components/primitives/context-menu/context-menu-sub-trigger.svelte +1 -1
  80. package/dist/components/primitives/dialog/dialog-content.svelte +3 -3
  81. package/dist/components/primitives/drawer/Drawer.svelte +1 -1
  82. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +31 -11
  83. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +2 -0
  84. package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte +5 -1
  85. package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte.d.ts +2 -0
  86. package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte +4 -2
  87. package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte.d.ts +2 -1
  88. package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +1 -1
  89. package/dist/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +1 -1
  90. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
  91. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +1 -1
  92. package/dist/components/primitives/index.d.ts +1 -1
  93. package/dist/components/primitives/index.js +1 -1
  94. package/dist/components/primitives/input/input.svelte +2 -2
  95. package/dist/components/primitives/input-group/input-group-input.svelte.d.ts +1 -1
  96. package/dist/components/primitives/input-group/input-group.svelte +1 -1
  97. package/dist/components/primitives/mode-toggle/mode-toggle.svelte +2 -2
  98. package/dist/components/primitives/popover/popover-content.svelte +1 -1
  99. package/dist/components/primitives/resizable/resizable-handle.svelte +2 -2
  100. package/dist/components/primitives/search/search.svelte +1 -1
  101. package/dist/components/primitives/select/select-content.svelte +1 -1
  102. package/dist/components/primitives/select/select-item.svelte +1 -1
  103. package/dist/components/primitives/select/select-trigger.svelte +1 -1
  104. package/dist/components/primitives/slider/slider.svelte +1 -1
  105. package/dist/components/primitives/switch/switch.svelte +1 -1
  106. package/dist/components/primitives/tabs/tabs-list.svelte +2 -2
  107. package/dist/components/primitives/tabs/tabs-list.svelte.d.ts +6 -6
  108. package/dist/components/primitives/tabs/tabs-trigger.svelte +2 -2
  109. package/dist/components/primitives/tabs/tabs-trigger.svelte.d.ts +6 -6
  110. package/dist/components/primitives/textarea/textarea.svelte +1 -1
  111. package/dist/components/primitives/toggle/toggle.svelte +11 -3
  112. package/dist/components/primitives/toggle/toggle.svelte.d.ts +13 -4
  113. package/dist/components/primitives/toggle-group/toggle-group-item.svelte +1 -1
  114. package/dist/components/primitives/toggle-group/toggle-group.svelte +1 -1
  115. package/dist/components/primitives/tooltip/index.d.ts +6 -0
  116. package/dist/components/primitives/tooltip/index.js +8 -0
  117. package/dist/components/primitives/tooltip/tooltip-content.svelte +34 -0
  118. package/dist/components/primitives/tooltip/tooltip-content.svelte.d.ts +10 -0
  119. package/dist/components/primitives/tooltip/tooltip-portal.svelte +7 -0
  120. package/dist/components/primitives/tooltip/tooltip-portal.svelte.d.ts +4 -0
  121. package/dist/components/primitives/tooltip/tooltip-provider.svelte +7 -0
  122. package/dist/components/primitives/tooltip/tooltip-provider.svelte.d.ts +4 -0
  123. package/dist/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
  124. package/dist/components/primitives/tooltip/tooltip-trigger.svelte.d.ts +4 -0
  125. package/dist/components/primitives/tooltip/tooltip.svelte +7 -0
  126. package/dist/components/primitives/tooltip/tooltip.svelte.d.ts +4 -0
  127. package/dist/components/viewer/MeshMetadataPanel.svelte +2 -2
  128. package/dist/components/viewer/SceneManager.svelte +32 -21
  129. package/dist/components/viewer/SceneManager.svelte.d.ts +3 -1
  130. package/dist/components/viewer/Viewer.svelte +135 -185
  131. package/dist/components/viewer/Viewer.svelte.d.ts +7 -2
  132. package/dist/components/viewer/ViewerDock.svelte +404 -0
  133. package/dist/components/viewer/ViewerDock.svelte.d.ts +42 -0
  134. package/dist/composables/useFooterItem.svelte.d.ts +1 -1
  135. package/dist/composables/useFooterItem.svelte.js +1 -1
  136. package/dist/compute/liveProgress.svelte.d.ts +16 -0
  137. package/dist/compute/liveProgress.svelte.js +90 -0
  138. package/dist/compute/solving.svelte.d.ts +11 -7
  139. package/dist/compute/solving.svelte.js +64 -45
  140. package/dist/constants.d.ts +6 -8
  141. package/dist/constants.js +8 -11
  142. package/dist/contexts/hostContext.svelte.d.ts +39 -0
  143. package/dist/contexts/hostContext.svelte.js +9 -0
  144. package/dist/features/chart/plotly-compat.d.ts +15 -0
  145. package/dist/features/chart/plotly-compat.js +124 -0
  146. package/dist/i18n/messages.d.ts +50 -0
  147. package/dist/i18n/messages.js +84 -0
  148. package/dist/index.d.ts +5 -0
  149. package/dist/index.js +5 -0
  150. package/dist/public.d.ts +1 -0
  151. package/dist/public.js +1 -0
  152. package/dist/schema/host-support.d.ts +29 -0
  153. package/dist/schema/host-support.js +97 -0
  154. package/dist/schema/option-display.d.ts +12 -0
  155. package/dist/schema/option-display.js +29 -0
  156. package/dist/schema/param-exporter.d.ts +4 -1
  157. package/dist/schema/param-exporter.js +10 -6
  158. package/dist/schema/visibility-rules.d.ts +7 -1
  159. package/dist/schema/visibility-rules.js +17 -0
  160. package/dist/styles/base.css +94 -84
  161. package/dist/utils/color-space.d.ts +21 -0
  162. package/dist/utils/color-space.js +90 -0
  163. package/dist/utils/file-download.js +6 -10
  164. package/dist/utils/host-files.d.ts +12 -0
  165. package/dist/utils/host-files.js +46 -0
  166. package/dist/utils/webp-to-png.d.ts +10 -0
  167. package/dist/utils/webp-to-png.js +41 -0
  168. package/package.json +31 -23
  169. package/src/lib/components/ErrorScreen.svelte +1 -1
  170. package/src/lib/components/compute/AppLayout.svelte +96 -38
  171. package/src/lib/components/compute/CollapsedPanelStrip.svelte +4 -2
  172. package/src/lib/components/compute/ComputeApp.svelte +6 -2
  173. package/src/lib/components/compute/ComputeMessagesDialog.svelte +4 -4
  174. package/src/lib/components/compute/ParameterPresetManager.svelte +9 -21
  175. package/src/lib/components/compute/SolveMessages.svelte +103 -89
  176. package/src/lib/components/layout/AppShell.svelte +2 -2
  177. package/src/lib/components/layout/FooterItemRenderer.svelte +2 -2
  178. package/src/lib/components/layout/PageContent.svelte +3 -2
  179. package/src/lib/components/layout/PageFooter.svelte +8 -6
  180. package/src/lib/components/layout/PageHeader.svelte +3 -3
  181. package/src/lib/components/layout/SideNav.svelte +56 -15
  182. package/src/lib/components/layout/SubNav.svelte +2 -2
  183. package/src/lib/components/preview/ChartOutput.svelte +158 -62
  184. package/src/lib/components/preview/Group.svelte +14 -9
  185. package/src/lib/components/preview/HelpButton.svelte +1 -1
  186. package/src/lib/components/preview/ImageOutput.svelte +16 -11
  187. package/src/lib/components/preview/InputControl.svelte +115 -50
  188. package/src/lib/components/preview/OutputDisplay.svelte +26 -17
  189. package/src/lib/components/preview/TabBar.svelte +8 -6
  190. package/src/lib/components/preview/TabContent.svelte +65 -33
  191. package/src/lib/components/preview/TabLayout.svelte +29 -8
  192. package/src/lib/components/preview/inputs/CheckboxInput.svelte +1 -1
  193. package/src/lib/components/preview/inputs/ChecklistInput.svelte +11 -6
  194. package/src/lib/components/preview/inputs/ColorInput.svelte +356 -14
  195. package/src/lib/components/preview/inputs/DropdownInput.svelte +18 -6
  196. package/src/lib/components/preview/inputs/FileInput.svelte +71 -75
  197. package/src/lib/components/preview/inputs/GeometryInput.svelte +128 -0
  198. package/src/lib/components/preview/inputs/NumberInput.svelte +8 -8
  199. package/src/lib/components/preview/inputs/OptionGlyph.svelte +29 -0
  200. package/src/lib/components/preview/inputs/SegmentedInput.svelte +45 -0
  201. package/src/lib/components/preview/inputs/TextInput.svelte +5 -5
  202. package/src/lib/components/preview/inputs/TileInput.svelte +83 -0
  203. package/src/lib/components/preview/inputs/index.ts +3 -0
  204. package/src/lib/components/primitives/CalculateButton.svelte +10 -4
  205. package/src/lib/components/primitives/Callout.svelte +9 -7
  206. package/src/lib/components/primitives/DataTable.svelte +1 -1
  207. package/src/lib/components/primitives/FilterableDropdown.svelte +14 -2
  208. package/src/lib/components/primitives/ImageUploadField.svelte +1 -1
  209. package/src/lib/components/primitives/IssueList.svelte +1 -1
  210. package/src/lib/components/primitives/SeverityIcon.svelte +1 -1
  211. package/src/lib/components/primitives/SolvingIndicator.svelte +245 -19
  212. package/src/lib/components/primitives/StateDisplay.svelte +1 -1
  213. package/src/lib/components/primitives/alert-dialog/alert-dialog-action.svelte +2 -2
  214. package/src/lib/components/primitives/alert-dialog/alert-dialog-cancel.svelte +2 -2
  215. package/src/lib/components/primitives/alert-dialog/alert-dialog-content.svelte +2 -2
  216. package/src/lib/components/primitives/alert-dialog/alert-dialog-description.svelte +1 -1
  217. package/src/lib/components/primitives/alert-dialog/alert-dialog-footer.svelte +1 -1
  218. package/src/lib/components/primitives/alert-dialog/alert-dialog-header.svelte +1 -1
  219. package/src/lib/components/primitives/alert-dialog/alert-dialog-overlay.svelte +1 -1
  220. package/src/lib/components/primitives/alert-dialog/alert-dialog-title.svelte +1 -1
  221. package/src/lib/components/primitives/badge/badge.svelte +3 -3
  222. package/src/lib/components/primitives/button/button.svelte +9 -7
  223. package/src/lib/components/primitives/button-group/button-group-separator.svelte +2 -2
  224. package/src/lib/components/primitives/button-group/button-group-text.svelte +1 -1
  225. package/src/lib/components/primitives/button-group/button-group.svelte +1 -1
  226. package/src/lib/components/primitives/card/card-content.svelte +1 -1
  227. package/src/lib/components/primitives/card/card-description.svelte +1 -1
  228. package/src/lib/components/primitives/card/card-footer.svelte +1 -1
  229. package/src/lib/components/primitives/card/card-header.svelte +1 -1
  230. package/src/lib/components/primitives/card/card-title.svelte +1 -1
  231. package/src/lib/components/primitives/card/card.svelte +2 -2
  232. package/src/lib/components/primitives/checkbox/checkbox.svelte +2 -2
  233. package/src/lib/components/primitives/command/command-dialog.svelte +2 -2
  234. package/src/lib/components/primitives/command/command-empty.svelte +1 -1
  235. package/src/lib/components/primitives/command/command-group.svelte +1 -1
  236. package/src/lib/components/primitives/command/command-input.svelte +3 -3
  237. package/src/lib/components/primitives/command/command-item.svelte +2 -2
  238. package/src/lib/components/primitives/command/command-link-item.svelte +2 -2
  239. package/src/lib/components/primitives/command/command-list.svelte +1 -1
  240. package/src/lib/components/primitives/command/command-separator.svelte +1 -1
  241. package/src/lib/components/primitives/command/command-shortcut.svelte +1 -1
  242. package/src/lib/components/primitives/command/command.svelte +2 -2
  243. package/src/lib/components/primitives/context-menu/context-menu-checkbox-item.svelte +2 -2
  244. package/src/lib/components/primitives/context-menu/context-menu-content.svelte +2 -2
  245. package/src/lib/components/primitives/context-menu/context-menu-group-heading.svelte +1 -1
  246. package/src/lib/components/primitives/context-menu/context-menu-item.svelte +2 -2
  247. package/src/lib/components/primitives/context-menu/context-menu-label.svelte +1 -1
  248. package/src/lib/components/primitives/context-menu/context-menu-radio-item.svelte +2 -2
  249. package/src/lib/components/primitives/context-menu/context-menu-separator.svelte +1 -1
  250. package/src/lib/components/primitives/context-menu/context-menu-shortcut.svelte +1 -1
  251. package/src/lib/components/primitives/context-menu/context-menu-sub-content.svelte +2 -2
  252. package/src/lib/components/primitives/context-menu/context-menu-sub-trigger.svelte +2 -2
  253. package/src/lib/components/primitives/dialog/dialog-content.svelte +4 -4
  254. package/src/lib/components/primitives/dialog/dialog-description.svelte +1 -1
  255. package/src/lib/components/primitives/dialog/dialog-footer.svelte +1 -1
  256. package/src/lib/components/primitives/dialog/dialog-header.svelte +1 -1
  257. package/src/lib/components/primitives/dialog/dialog-overlay.svelte +1 -1
  258. package/src/lib/components/primitives/dialog/dialog-title.svelte +1 -1
  259. package/src/lib/components/primitives/drawer/Drawer.svelte +1 -1
  260. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +32 -12
  261. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-content.svelte +6 -2
  262. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-group-heading.svelte +1 -1
  263. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-item.svelte +5 -3
  264. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-label.svelte +1 -1
  265. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +2 -2
  266. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-separator.svelte +1 -1
  267. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +2 -2
  268. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +2 -2
  269. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +2 -2
  270. package/src/lib/components/primitives/empty/empty-content.svelte +1 -1
  271. package/src/lib/components/primitives/empty/empty-description.svelte +1 -1
  272. package/src/lib/components/primitives/empty/empty-header.svelte +1 -1
  273. package/src/lib/components/primitives/empty/empty-media.svelte +1 -1
  274. package/src/lib/components/primitives/empty/empty-title.svelte +1 -1
  275. package/src/lib/components/primitives/empty/empty.svelte +1 -1
  276. package/src/lib/components/primitives/field/field-content.svelte +1 -1
  277. package/src/lib/components/primitives/field/field-description.svelte +1 -1
  278. package/src/lib/components/primitives/field/field-error.svelte +1 -1
  279. package/src/lib/components/primitives/field/field-group.svelte +1 -1
  280. package/src/lib/components/primitives/field/field-label.svelte +2 -2
  281. package/src/lib/components/primitives/field/field-legend.svelte +1 -1
  282. package/src/lib/components/primitives/field/field-separator.svelte +2 -2
  283. package/src/lib/components/primitives/field/field-set.svelte +1 -1
  284. package/src/lib/components/primitives/field/field-title.svelte +1 -1
  285. package/src/lib/components/primitives/field/field.svelte +1 -1
  286. package/src/lib/components/primitives/index.ts +1 -1
  287. package/src/lib/components/primitives/input/input.svelte +3 -3
  288. package/src/lib/components/primitives/input-group/input-group-addon.svelte +1 -1
  289. package/src/lib/components/primitives/input-group/input-group-button.svelte +2 -2
  290. package/src/lib/components/primitives/input-group/input-group-input.svelte +2 -2
  291. package/src/lib/components/primitives/input-group/input-group-text.svelte +1 -1
  292. package/src/lib/components/primitives/input-group/input-group-textarea.svelte +2 -2
  293. package/src/lib/components/primitives/input-group/input-group.svelte +2 -2
  294. package/src/lib/components/primitives/label/label.svelte +1 -1
  295. package/src/lib/components/primitives/mode-toggle/mode-toggle.svelte +2 -2
  296. package/src/lib/components/primitives/popover/popover-content.svelte +2 -2
  297. package/src/lib/components/primitives/popover/popover-description.svelte +1 -1
  298. package/src/lib/components/primitives/popover/popover-header.svelte +1 -1
  299. package/src/lib/components/primitives/popover/popover-title.svelte +1 -1
  300. package/src/lib/components/primitives/popover/popover-trigger.svelte +1 -1
  301. package/src/lib/components/primitives/resizable/resizable-handle.svelte +3 -3
  302. package/src/lib/components/primitives/resizable/resizable-pane-group.svelte +1 -1
  303. package/src/lib/components/primitives/scroll-area/scroll-area-scrollbar.svelte +1 -1
  304. package/src/lib/components/primitives/scroll-area/scroll-area.svelte +1 -1
  305. package/src/lib/components/primitives/search/search.svelte +2 -2
  306. package/src/lib/components/primitives/select/select-content.svelte +2 -2
  307. package/src/lib/components/primitives/select/select-group-heading.svelte +1 -1
  308. package/src/lib/components/primitives/select/select-item.svelte +2 -2
  309. package/src/lib/components/primitives/select/select-label.svelte +1 -1
  310. package/src/lib/components/primitives/select/select-scroll-down-button.svelte +1 -1
  311. package/src/lib/components/primitives/select/select-scroll-up-button.svelte +1 -1
  312. package/src/lib/components/primitives/select/select-separator.svelte +2 -2
  313. package/src/lib/components/primitives/select/select-trigger.svelte +2 -2
  314. package/src/lib/components/primitives/separator/separator.svelte +1 -1
  315. package/src/lib/components/primitives/slider/slider.svelte +2 -2
  316. package/src/lib/components/primitives/spinner/spinner.svelte +1 -1
  317. package/src/lib/components/primitives/switch/switch.svelte +2 -2
  318. package/src/lib/components/primitives/tabs/tabs-content.svelte +1 -1
  319. package/src/lib/components/primitives/tabs/tabs-list.svelte +3 -3
  320. package/src/lib/components/primitives/tabs/tabs-trigger.svelte +3 -3
  321. package/src/lib/components/primitives/tabs/tabs.svelte +1 -1
  322. package/src/lib/components/primitives/textarea/textarea.svelte +2 -2
  323. package/src/lib/components/primitives/toggle/toggle.svelte +12 -4
  324. package/src/lib/components/primitives/toggle-group/toggle-group-item.svelte +3 -3
  325. package/src/lib/components/primitives/toggle-group/toggle-group.svelte +3 -3
  326. package/src/lib/components/primitives/tooltip/index.ts +19 -0
  327. package/src/lib/components/primitives/tooltip/tooltip-content.svelte +34 -0
  328. package/src/lib/components/primitives/tooltip/tooltip-portal.svelte +7 -0
  329. package/src/lib/components/primitives/tooltip/tooltip-provider.svelte +7 -0
  330. package/src/lib/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
  331. package/src/lib/components/primitives/tooltip/tooltip.svelte +7 -0
  332. package/src/lib/components/viewer/MeshMetadataPanel.svelte +2 -2
  333. package/src/lib/components/viewer/SceneManager.svelte +32 -21
  334. package/src/lib/components/viewer/Viewer.svelte +136 -186
  335. package/src/lib/components/viewer/ViewerDock.svelte +404 -0
  336. package/src/lib/composables/useFooterItem.svelte.ts +1 -1
  337. package/src/lib/compute/liveProgress.svelte.ts +103 -0
  338. package/src/lib/compute/solving.svelte.ts +66 -50
  339. package/src/lib/constants.ts +8 -11
  340. package/src/lib/contexts/hostContext.svelte.ts +51 -0
  341. package/src/lib/features/chart/plotly-compat.ts +141 -0
  342. package/src/lib/i18n/messages.ts +139 -0
  343. package/src/lib/index.ts +22 -0
  344. package/src/lib/public.ts +1 -0
  345. package/src/lib/schema/host-support.ts +129 -0
  346. package/src/lib/schema/option-display.ts +44 -0
  347. package/src/lib/schema/param-exporter.ts +10 -7
  348. package/src/lib/schema/visibility-rules.ts +27 -1
  349. package/src/lib/styles/base.css +94 -84
  350. package/src/lib/utils/color-space.ts +107 -0
  351. package/src/lib/utils/file-download.ts +7 -11
  352. package/src/lib/utils/host-files.ts +61 -0
  353. package/src/lib/utils/webp-to-png.ts +48 -0
  354. package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
  355. package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte.d.ts +0 -3
  356. package/dist/components/primitives/theme-switcher/index.d.ts +0 -1
  357. package/dist/components/primitives/theme-switcher/index.js +0 -1
  358. package/dist/styles/themes/cyberpunk.css +0 -98
  359. package/dist/styles/themes/neutral.css +0 -72
  360. package/dist/styles/themes/ocean.css +0 -75
  361. package/dist/styles/themes/selva.css +0 -105
  362. package/dist/theme/themeStore.svelte.d.ts +0 -12
  363. package/dist/theme/themeStore.svelte.js +0 -40
  364. package/dist/theme/themes.d.ts +0 -5
  365. package/dist/theme/themes.js +0 -13
  366. package/src/lib/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
  367. package/src/lib/components/primitives/theme-switcher/index.ts +0 -1
  368. package/src/lib/styles/themes/cyberpunk.css +0 -98
  369. package/src/lib/styles/themes/neutral.css +0 -72
  370. package/src/lib/styles/themes/ocean.css +0 -75
  371. package/src/lib/styles/themes/selva.css +0 -105
  372. package/src/lib/theme/themeStore.svelte.ts +0 -50
  373. package/src/lib/theme/themes.ts +0 -18
@@ -0,0 +1,51 @@
1
+ import { getContext, setContext } from 'svelte';
2
+ import type { GeometryKind } from '@selvajs/schemas';
3
+ import type { UIHost } from '#lib/schema/host-support.js';
4
+
5
+ // Tells InputControl which host it renders in and how to reach the host's own actions, without
6
+ // threading a prop through every layout layer. Without a provider the host is Selva.
7
+
8
+ export type GeometryPickResult =
9
+ | { outcome: 'picked'; summary: string }
10
+ | { outcome: 'cancelled' }
11
+ | { outcome: 'failed'; error: string };
12
+
13
+ /** What a pick button can ask for: a Get Geometry filter's kinds, or Get Point/Line/Plane's own. */
14
+ export type PickKind = GeometryKind | 'line' | 'plane';
15
+
16
+ /** What a geometry input lets the user pick, as the host discovered it on the canvas. */
17
+ export interface GeometryPickTarget {
18
+ /** The kinds its filter allows; absent when it takes anything. */
19
+ kinds?: readonly GeometryKind[];
20
+ /** 1 picks a single object. */
21
+ atMost?: number;
22
+ }
23
+
24
+ export interface HostActions {
25
+ host: UIHost;
26
+ /** Prompts in the Rhino viewport for a geometry input. The picked geometry stays in Grasshopper. */
27
+ pickGeometry?: (paramId: string) => Promise<GeometryPickResult>;
28
+ /** Empties a geometry input again, back to the definition's own value. */
29
+ clearGeometry?: (paramId: string) => void;
30
+ /**
31
+ * Reports what the param holds after every pick or clear, including those another page asked
32
+ * for; null when nothing is picked into it. Returns an unsubscribe.
33
+ */
34
+ onGeometrySummary?: (paramId: string, listener: (summary: string | null) => void) => () => void;
35
+ describeGeometry?: (paramId: string) => GeometryPickTarget | undefined;
36
+ /** Presses a button input: one solve with `true`, then it goes back to `false`. */
37
+ trigger?: (paramId: string) => void;
38
+ /** Grasshopper refuses a press while it solves, so the button waits it out disabled. */
39
+ isSolving?: () => boolean;
40
+ }
41
+
42
+ const SELVA_HOST: HostActions = { host: 'selva' };
43
+ const HOST_CONTEXT_KEY = Symbol('host-context');
44
+
45
+ export function setHostContext(actions: HostActions): void {
46
+ setContext(HOST_CONTEXT_KEY, actions);
47
+ }
48
+
49
+ export function getHostContext(): HostActions {
50
+ return getContext<HostActions | undefined>(HOST_CONTEXT_KEY) ?? SELVA_HOST;
51
+ }
@@ -0,0 +1,141 @@
1
+ import { hsvToRgb } from '#lib/utils/color-space.js';
2
+
3
+ // ============================================================================
4
+ // Plotly 3 → 4 figure compatibility
5
+ // ============================================================================
6
+ //
7
+ // Chart outputs come from whatever plugin version solved them, often one written against
8
+ // Plotly 3. This rewrites the parts Plotly 4 draws differently or rejects, so those figures
9
+ // keep their look. Figures that are already compatible pass through unchanged.
10
+
11
+ type Json = Record<string, unknown>;
12
+
13
+ export interface PlotlyFigure {
14
+ data: Json[];
15
+ layout?: Json;
16
+ config?: Json;
17
+ frames?: Json[];
18
+ }
19
+
20
+ const REMOVED_MAP_TRACES: Record<string, string> = {
21
+ scattermapbox: 'scattermap',
22
+ choroplethmapbox: 'choroplethmap',
23
+ densitymapbox: 'densitymap'
24
+ };
25
+
26
+ const MAPBOX_SUBPLOT = /^mapbox(\d*)$/;
27
+ const BARE_HEX = /^(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
28
+ const HSV_FUNCTION =
29
+ /^hsva?[\s(]+([-+\d.]+)%?[\s,]+([\d.]+)(%?)[\s,]+([\d.]+)(%?)(?:[\s,/]+([\d.]+)(%?))?[\s)]*$/i;
30
+
31
+ const isObject = (v: unknown): v is Json =>
32
+ typeof v === 'object' && v !== null && !Array.isArray(v);
33
+
34
+ /** Returns a rewritten copy; the input is not modified. */
35
+ export function upgradePlotlyFigure(figure: PlotlyFigure): PlotlyFigure {
36
+ const out = structuredClone(figure);
37
+ const layout = out.layout ?? {};
38
+ normalizeColors(layout);
39
+
40
+ let migratedMaps = false;
41
+ for (const trace of out.data ?? []) {
42
+ if (!isObject(trace)) continue;
43
+ normalizeColors(trace);
44
+
45
+ const replacement = REMOVED_MAP_TRACES[trace.type as string];
46
+ if (replacement) {
47
+ trace.type = replacement;
48
+ if (typeof trace.subplot === 'string')
49
+ trace.subplot = trace.subplot.replace(MAPBOX_SUBPLOT, 'map$1');
50
+ migratedMaps = true;
51
+ } else if (trace.type === 'splom') {
52
+ keepSplomAxesUnlinked(trace);
53
+ }
54
+ }
55
+
56
+ if (migratedMaps) migrateMapLayout(layout);
57
+ // Frame data replaces trace data during playback, so it needs the same colour fixes.
58
+ for (const frame of out.frames ?? []) if (isObject(frame)) normalizeColors(frame);
59
+ return { ...out, layout };
60
+ }
61
+
62
+ // Plotly 4 links each dimension's x and y axes by default.
63
+ function keepSplomAxesUnlinked(trace: Json) {
64
+ if (!Array.isArray(trace.dimensions)) return;
65
+ for (const dim of trace.dimensions) {
66
+ if (!isObject(dim)) continue;
67
+ const axis = isObject(dim.axis) ? dim.axis : (dim.axis = {});
68
+ if (!('matches' in axis)) axis.matches = false;
69
+ }
70
+ }
71
+
72
+ function migrateMapLayout(layout: Json) {
73
+ for (const key of Object.keys(layout)) {
74
+ const match = MAPBOX_SUBPLOT.exec(key);
75
+ if (!match) continue;
76
+
77
+ const map = layout[key];
78
+ delete layout[key];
79
+ const newKey = `map${match[1]}`;
80
+ if (newKey in layout || !isObject(map)) continue;
81
+
82
+ delete map.accesstoken;
83
+ // Stamen and mapbox:// styles have no map equivalent.
84
+ if (typeof map.style === 'string' && /^(stamen|mapbox:\/\/)/.test(map.style))
85
+ map.style = 'open-street-map';
86
+ layout[newKey] = map;
87
+ }
88
+ }
89
+
90
+ // Plotly attributes that hold colours: *color, colorway, colorscale and pie's marker.colors.
91
+ const isColorKey = (key: string) =>
92
+ key.toLowerCase().endsWith('color') ||
93
+ key === 'colors' ||
94
+ key === 'colorway' ||
95
+ key === 'colorscale';
96
+
97
+ function normalizeColors(props: Json) {
98
+ for (const [key, value] of Object.entries(props)) {
99
+ if (isColorKey(key)) props[key] = normalizeColorValue(value, false);
100
+ else if (isObject(value)) normalizeColors(value);
101
+ else if (Array.isArray(value))
102
+ for (const item of value) if (isObject(item)) normalizeColors(item);
103
+ }
104
+ }
105
+
106
+ // Covers a single colour, a per-point list and colorscale stops ([[0, "ff0000"], ...]).
107
+ function normalizeColorValue(value: unknown, inList: boolean): unknown {
108
+ if (Array.isArray(value)) return value.map((v) => normalizeColorValue(v, true));
109
+ if (typeof value !== 'string') return value;
110
+ // Plotly reads numeric strings in a per-point list as numbers for the colorscale.
111
+ if (inList && /^\s*\d+\s*$/.test(value)) return value;
112
+ return normalizePlotlyColor(value);
113
+ }
114
+
115
+ /**
116
+ * Rewrites colour spellings Plotly 3 accepted but Plotly 4 rejects (hex without `#`, `hsv()`)
117
+ * into valid CSS. Anything else is returned unchanged.
118
+ */
119
+ export function normalizePlotlyColor(color: string): string {
120
+ const value = color.trim();
121
+ if (BARE_HEX.test(value)) return `#${value}`;
122
+
123
+ const hsv = HSV_FUNCTION.exec(value);
124
+ if (!hsv) return color;
125
+
126
+ const { r, g, b } = hsvToRgb({
127
+ h: Number(hsv[1]),
128
+ s: unit(hsv[2], hsv[3] === '%'),
129
+ v: unit(hsv[4], hsv[5] === '%')
130
+ });
131
+ const rgb = `${Math.round(r)},${Math.round(g)},${Math.round(b)}`;
132
+ if (hsv[6] === undefined) return `rgb(${rgb})`;
133
+ return `rgba(${rgb},${+unit(hsv[6], hsv[7] === '%').toFixed(3)})`;
134
+ }
135
+
136
+ // Plotly 3 (TinyColor) read 0..1 as a fraction and anything above 1 as a percentage.
137
+ function unit(s: string, percent: boolean): number {
138
+ let x = Number(s);
139
+ if (percent || x > 1) x /= 100;
140
+ return Math.min(1, Math.max(0, x));
141
+ }
@@ -40,6 +40,8 @@ export interface ViewerMessages {
40
40
  lookTechnical: string;
41
41
  lookStudio: string;
42
42
  lookShowcase: string;
43
+ lookNight: string;
44
+ nightMode: string;
43
45
  lookArctic: string;
44
46
  lookXray: string;
45
47
  lookLineart: string;
@@ -73,8 +75,14 @@ export interface ViewerMessages {
73
75
  solveMessagesConfirm: string;
74
76
  solveMessagesDiscard: string;
75
77
  solveMessagesAbort: string;
78
+ /** Stands in for Abort where the page can't take a click mid-solve. */
79
+ solveMessagesEscHint: string;
76
80
  solveMessagesDismiss: string;
77
81
  solveSolving: string;
82
+ /** A visible solve has landed; followed by how long it took. */
83
+ solveDone: string;
84
+ /** A visible solve was aborted; the previous result stays. */
85
+ solveStopped: string;
78
86
  parametersTab: string;
79
87
  moreTab: string;
80
88
  scrollTabsBack: string;
@@ -129,8 +137,52 @@ export interface ViewerMessages {
129
137
  /** `{max}` is replaced with the field's character limit. */
130
138
  maxLength: string;
131
139
  invalidFormat: string;
140
+ /** Trigger label; `{color}` is the current hex value. */
141
+ colorPick: string;
142
+ colorArea: string;
143
+ /** `{s}` and `{v}` are percentages. */
144
+ colorAreaValue: string;
145
+ colorHue: string;
146
+ colorHex: string;
147
+ colorHexInvalid: string;
148
+ colorPresets: string;
149
+ colorEyedropper: string;
132
150
  invalidPattern: string;
133
151
 
152
+ // Geometry input (Rhino only)
153
+ /** The pick button when the input takes several kinds of object. */
154
+ geometryPickAnyOne: string;
155
+ geometryPickAnyOther: string;
156
+ /** Shown while Rhino's viewport prompt for a pick is open. */
157
+ geometryPicking: string;
158
+ /** Where this page may not pick, such as a browser tab beside the Rhino panel. */
159
+ geometryPickInPanel: string;
160
+ geometryPickAgain: string;
161
+ geometryClear: string;
162
+ // The pick button when the input takes one kind: `One` picks a single object, `Other` several.
163
+ geometryPickPointOne: string;
164
+ geometryPickPointOther: string;
165
+ geometryPickPointCloudOne: string;
166
+ geometryPickPointCloudOther: string;
167
+ geometryPickCurveOne: string;
168
+ geometryPickCurveOther: string;
169
+ geometryPickLineOne: string;
170
+ geometryPickLineOther: string;
171
+ geometryPickPlaneOne: string;
172
+ geometryPickPlaneOther: string;
173
+ geometryPickSurfaceOne: string;
174
+ geometryPickSurfaceOther: string;
175
+ geometryPickPolysurfaceOne: string;
176
+ geometryPickPolysurfaceOther: string;
177
+ geometryPickExtrusionOne: string;
178
+ geometryPickExtrusionOther: string;
179
+ geometryPickMeshOne: string;
180
+ geometryPickMeshOther: string;
181
+ geometryPickSubdOne: string;
182
+ geometryPickSubdOther: string;
183
+ geometryPickBlockOne: string;
184
+ geometryPickBlockOther: string;
185
+
134
186
  // File input
135
187
  fileModeUpload: string;
136
188
  fileModeUrl: string;
@@ -183,6 +235,7 @@ export interface ViewerMessages {
183
235
  copied: string;
184
236
  chartReceiving: string;
185
237
  chartRenderFailed: string;
238
+ downloadChartImage: string;
186
239
  /** `{error}` is replaced with the browser's reason. */
187
240
  fullscreenUnavailable: string;
188
241
  /** `{error}` is replaced with the browser's reason. */
@@ -232,6 +285,8 @@ const en: ViewerMessages = {
232
285
  lookTechnical: 'Technical',
233
286
  lookStudio: 'Studio',
234
287
  lookShowcase: 'Showcase',
288
+ lookNight: 'Night',
289
+ nightMode: 'Night mode',
235
290
  lookArctic: 'Arctic',
236
291
  lookXray: 'X-Ray',
237
292
  lookLineart: 'Line Art',
@@ -261,8 +316,11 @@ const en: ViewerMessages = {
261
316
  solveMessagesConfirm: 'Continue',
262
317
  solveMessagesDiscard: 'Discard',
263
318
  solveMessagesAbort: 'Abort',
319
+ solveMessagesEscHint: 'Esc aborts the solve',
264
320
  solveMessagesDismiss: 'Dismiss',
265
321
  solveSolving: 'Solving…',
322
+ solveDone: 'Done',
323
+ solveStopped: 'Stopped',
266
324
  parametersTab: 'Parameters',
267
325
  moreTab: 'More',
268
326
  scrollTabsBack: 'Previous tabs',
@@ -303,8 +361,45 @@ const en: ViewerMessages = {
303
361
  fineDragHint: 'Hold Shift to drag finely',
304
362
  maxLength: 'Maximum {max} characters allowed',
305
363
  invalidFormat: 'Invalid format',
364
+ colorPick: 'Choose color, currently {color}',
365
+ colorArea: 'Saturation and brightness',
366
+ colorAreaValue: 'Saturation {s}%, brightness {v}%',
367
+ colorHue: 'Hue',
368
+ colorHex: 'Hex color',
369
+ colorHexInvalid: 'Enter a hex color such as #2f6fd6',
370
+ colorPresets: 'Presets',
371
+ colorEyedropper: 'Pick a color from the screen',
306
372
  invalidPattern: 'Invalid validation pattern configured',
307
373
 
374
+ geometryPickAnyOne: 'Pick an object',
375
+ geometryPickAnyOther: 'Pick objects',
376
+ geometryPicking: 'Pick in the viewport, Esc to cancel',
377
+ geometryPickInPanel: 'Pick in the Rhino panel',
378
+ geometryPickAgain: 'Pick again',
379
+ geometryClear: 'Clear',
380
+ geometryPickPointOne: 'Pick a point',
381
+ geometryPickPointOther: 'Pick points',
382
+ geometryPickPointCloudOne: 'Pick a point cloud',
383
+ geometryPickPointCloudOther: 'Pick point clouds',
384
+ geometryPickCurveOne: 'Pick a curve',
385
+ geometryPickCurveOther: 'Pick curves',
386
+ geometryPickLineOne: 'Pick a line',
387
+ geometryPickLineOther: 'Pick lines',
388
+ geometryPickPlaneOne: 'Pick a plane',
389
+ geometryPickPlaneOther: 'Pick planes',
390
+ geometryPickSurfaceOne: 'Pick a surface',
391
+ geometryPickSurfaceOther: 'Pick surfaces',
392
+ geometryPickPolysurfaceOne: 'Pick a polysurface',
393
+ geometryPickPolysurfaceOther: 'Pick polysurfaces',
394
+ geometryPickExtrusionOne: 'Pick an extrusion',
395
+ geometryPickExtrusionOther: 'Pick extrusions',
396
+ geometryPickMeshOne: 'Pick a mesh',
397
+ geometryPickMeshOther: 'Pick meshes',
398
+ geometryPickSubdOne: 'Pick a SubD',
399
+ geometryPickSubdOther: 'Pick SubDs',
400
+ geometryPickBlockOne: 'Pick a block',
401
+ geometryPickBlockOther: 'Pick blocks',
402
+
308
403
  fileModeUpload: 'Upload',
309
404
  fileModeUrl: 'URL',
310
405
  fileUrlLabel: 'File URL',
@@ -351,6 +446,7 @@ const en: ViewerMessages = {
351
446
  copied: 'Copied!',
352
447
  chartReceiving: 'Receiving chart data...',
353
448
  chartRenderFailed: 'Failed to render chart',
449
+ downloadChartImage: 'Download plot as image',
354
450
  fullscreenUnavailable: 'Fullscreen unavailable: {error}',
355
451
  exitFullscreenFailed: 'Exit fullscreen failed: {error}',
356
452
 
@@ -395,6 +491,8 @@ const de: ViewerMessages = {
395
491
  lookTechnical: 'Technisch',
396
492
  lookStudio: 'Studio',
397
493
  lookShowcase: 'Präsentation',
494
+ lookNight: 'Nacht',
495
+ nightMode: 'Nachtmodus',
398
496
  lookArctic: 'Arktis',
399
497
  lookXray: 'Röntgen',
400
498
  lookLineart: 'Strichzeichnung',
@@ -425,8 +523,11 @@ const de: ViewerMessages = {
425
523
  solveMessagesConfirm: 'Weiter',
426
524
  solveMessagesDiscard: 'Verwerfen',
427
525
  solveMessagesAbort: 'Abbrechen',
526
+ solveMessagesEscHint: 'Esc bricht die Berechnung ab',
428
527
  solveMessagesDismiss: 'Schliessen',
429
528
  solveSolving: 'Berechnung läuft…',
529
+ solveDone: 'Fertig',
530
+ solveStopped: 'Abgebrochen',
430
531
  parametersTab: 'Parameter',
431
532
  moreTab: 'Mehr',
432
533
  scrollTabsBack: 'Vorherige Tabs',
@@ -467,8 +568,45 @@ const de: ViewerMessages = {
467
568
  fineDragHint: 'Umschalttaste halten für feine Schritte',
468
569
  maxLength: 'Höchstens {max} Zeichen erlaubt',
469
570
  invalidFormat: 'Ungültiges Format',
571
+ colorPick: 'Farbe wählen, aktuell {color}',
572
+ colorArea: 'Sättigung und Helligkeit',
573
+ colorAreaValue: 'Sättigung {s} %, Helligkeit {v} %',
574
+ colorHue: 'Farbton',
575
+ colorHex: 'Hex-Farbe',
576
+ colorHexInvalid: 'Hex-Farbe eingeben, z. B. #2f6fd6',
577
+ colorPresets: 'Vorgaben',
578
+ colorEyedropper: 'Farbe vom Bildschirm aufnehmen',
470
579
  invalidPattern: 'Ungültiges Prüfmuster hinterlegt',
471
580
 
581
+ geometryPickAnyOne: 'Objekt wählen',
582
+ geometryPickAnyOther: 'Objekte wählen',
583
+ geometryPicking: 'Im Ansichtsfenster wählen, Esc bricht ab',
584
+ geometryPickInPanel: 'Im Rhino-Panel wählen',
585
+ geometryPickAgain: 'Neu wählen',
586
+ geometryClear: 'Leeren',
587
+ geometryPickPointOne: 'Punkt wählen',
588
+ geometryPickPointOther: 'Punkte wählen',
589
+ geometryPickPointCloudOne: 'Punktwolke wählen',
590
+ geometryPickPointCloudOther: 'Punktwolken wählen',
591
+ geometryPickCurveOne: 'Kurve wählen',
592
+ geometryPickCurveOther: 'Kurven wählen',
593
+ geometryPickLineOne: 'Linie wählen',
594
+ geometryPickLineOther: 'Linien wählen',
595
+ geometryPickPlaneOne: 'Ebene wählen',
596
+ geometryPickPlaneOther: 'Ebenen wählen',
597
+ geometryPickSurfaceOne: 'Fläche wählen',
598
+ geometryPickSurfaceOther: 'Flächen wählen',
599
+ geometryPickPolysurfaceOne: 'Flächenverband wählen',
600
+ geometryPickPolysurfaceOther: 'Flächenverbände wählen',
601
+ geometryPickExtrusionOne: 'Extrusion wählen',
602
+ geometryPickExtrusionOther: 'Extrusionen wählen',
603
+ geometryPickMeshOne: 'Netz wählen',
604
+ geometryPickMeshOther: 'Netze wählen',
605
+ geometryPickSubdOne: 'SubD wählen',
606
+ geometryPickSubdOther: 'SubDs wählen',
607
+ geometryPickBlockOne: 'Block wählen',
608
+ geometryPickBlockOther: 'Blöcke wählen',
609
+
472
610
  fileModeUpload: 'Hochladen',
473
611
  fileModeUrl: 'URL',
474
612
  fileUrlLabel: 'Datei-URL',
@@ -516,6 +654,7 @@ const de: ViewerMessages = {
516
654
  copied: 'Kopiert!',
517
655
  chartReceiving: 'Diagrammdaten werden empfangen…',
518
656
  chartRenderFailed: 'Diagramm konnte nicht dargestellt werden',
657
+ downloadChartImage: 'Diagramm als Bild herunterladen',
519
658
  fullscreenUnavailable: 'Vollbild nicht verfügbar: {error}',
520
659
  exitFullscreenFailed: 'Vollbild konnte nicht beendet werden: {error}',
521
660
 
package/src/lib/index.ts CHANGED
@@ -13,12 +13,25 @@ export { default as ErrorScreen } from './components/ErrorScreen.svelte';
13
13
  // Design-system primitives (shadcn-svelte + custom)
14
14
  export * from './components/primitives';
15
15
  export { default as StateDisplay } from './components/primitives/StateDisplay.svelte';
16
+ export { default as ColorInput } from './components/preview/inputs/ColorInput.svelte';
16
17
 
17
18
  export { default as Viewer } from './components/viewer/Viewer.svelte';
18
19
 
19
20
  export * from './schema/defaults';
20
21
  export * from './schema/dynamic-value-list';
21
22
  export * from './schema/traversal';
23
+ export { visibleInputItems } from './schema/visibility-rules';
24
+ export {
25
+ type UIHost,
26
+ type ElementKind,
27
+ HOST_LABELS,
28
+ isGeometryParamType,
29
+ layoutItemKind,
30
+ hostsFor,
31
+ isSupportedOn,
32
+ valuelessInputIds,
33
+ unsupportedItems
34
+ } from './schema/host-support';
22
35
  export * from './compute/solving.svelte';
23
36
 
24
37
  // Solve Session seam. Re-exported so transports outside this package — e.g.
@@ -54,10 +67,19 @@ export {
54
67
 
55
68
  export * from './contexts/footerContext.svelte';
56
69
  export * from './contexts/clientSlotContext.svelte';
70
+ export * from './contexts/hostContext.svelte';
57
71
  export * from './composables/useFooterItem.svelte';
58
72
 
59
73
  export * from './utils';
60
74
  export { randomId } from './utils/randomId';
75
+ export {
76
+ saveBlob,
77
+ pickFile,
78
+ setBlobSaver,
79
+ setFilePicker,
80
+ type BlobSaver,
81
+ type FilePicker
82
+ } from './utils/host-files';
61
83
 
62
84
  // UI-specific runtime types (not from schema)
63
85
  export type { ActionButton } from './types/actionButton';
package/src/lib/public.ts CHANGED
@@ -80,6 +80,7 @@ export {
80
80
  export * from './schema/defaults';
81
81
  export * from './schema/traversal';
82
82
  export * from './schema/dynamic-value-list';
83
+ export { visibleInputItems } from './schema/visibility-rules';
83
84
 
84
85
  // UI-facing runtime types (not from schema)
85
86
  export type { ActionButton } from './types/actionButton';
@@ -0,0 +1,129 @@
1
+ // Which elements of a schema each host renders. Worked out from the schema on every read and
2
+ // never stored in it: a stored copy goes stale the way a saved paramType does. Making an element
3
+ // work on Selva later is a change to SUPPORT, with no schema change and no migration.
4
+
5
+ import type {
6
+ InputLayoutItem,
7
+ LayoutItem,
8
+ SchemaInput,
9
+ UISchema,
10
+ CheckboxWidgetConfig
11
+ } from '@selvajs/schemas';
12
+ import { getGroups } from '@selvajs/schemas';
13
+
14
+ /**
15
+ * Where a UI runs: `rhino` is the plugin's page inside Rhino, solving in the user's own
16
+ * Grasshopper; `selva` is the Selva app, solving headless on Rhino.Compute.
17
+ */
18
+ export type UIHost = 'rhino' | 'selva';
19
+
20
+ /**
21
+ * - `value`: an input or output every host renders.
22
+ * - `geometry`: a Rhino Get Geometry/Point/Line/Plane input, filled by picking in the viewport.
23
+ * - `trigger`: a boolean input shown as a button; a press solves once with `true`.
24
+ * - `unknown`: a layout item from a newer schema than this build knows.
25
+ */
26
+ export type ElementKind = 'value' | 'geometry' | 'trigger' | 'unknown';
27
+
28
+ const SUPPORT: Record<ElementKind, readonly UIHost[]> = {
29
+ value: ['rhino', 'selva'],
30
+ geometry: ['rhino'],
31
+ trigger: ['rhino'],
32
+ unknown: []
33
+ };
34
+
35
+ export const HOST_LABELS: Record<UIHost, string> = { rhino: 'Rhino', selva: 'Selva' };
36
+
37
+ const GEOMETRY_PARAM_TYPES: ReadonlySet<string> = new Set(['geometry', 'point', 'line', 'plane']);
38
+
39
+ type WidgetTypeOf<T extends 'input' | 'output'> = Extract<LayoutItem, { type: T }>['widgetType'];
40
+
41
+ // Keyed by the schema's own widget unions, so a widget added to the schema fails to compile here
42
+ // until someone decides which hosts render it.
43
+ const INPUT_WIDGETS = {
44
+ number: true,
45
+ text: true,
46
+ dropdown: true,
47
+ dynamicValueList: true,
48
+ checkbox: true,
49
+ file: true,
50
+ color: true
51
+ } as const satisfies Record<WidgetTypeOf<'input'>, true>;
52
+ const OUTPUT_WIDGETS = {
53
+ text: true,
54
+ number: true,
55
+ file: true,
56
+ chart: true,
57
+ image: true,
58
+ dynamicValueList: true
59
+ } as const satisfies Record<WidgetTypeOf<'output'>, true>;
60
+
61
+ const KNOWN_WIDGETS: Record<'input' | 'output', ReadonlySet<string>> = {
62
+ input: new Set(Object.keys(INPUT_WIDGETS)),
63
+ output: new Set(Object.keys(OUTPUT_WIDGETS))
64
+ };
65
+
66
+ /** The control comes from this, whatever the saved widgetType says: saved ones hold `text`. */
67
+ export function isGeometryParamType(paramType: string | undefined): boolean {
68
+ return paramType !== undefined && GEOMETRY_PARAM_TYPES.has(paramType);
69
+ }
70
+
71
+ export function isTriggerItem(item: LayoutItem): boolean {
72
+ return (
73
+ item.type === 'input' &&
74
+ item.widgetType === 'checkbox' &&
75
+ (item.config as CheckboxWidgetConfig | undefined)?.displayAs === 'button'
76
+ );
77
+ }
78
+
79
+ export function layoutItemKind(item: LayoutItem, inputs: readonly SchemaInput[]): ElementKind {
80
+ if (item.type === 'linebreak') return 'value';
81
+ if (item.type !== 'input' && item.type !== 'output') return 'unknown';
82
+ if (item.type === 'input') {
83
+ const paramType = inputs.find((i) => i.id === item.paramId)?.paramType;
84
+ if (isGeometryParamType(paramType)) return 'geometry';
85
+ }
86
+ if (!KNOWN_WIDGETS[item.type].has(item.widgetType)) return 'unknown';
87
+ return isTriggerItem(item) ? 'trigger' : 'value';
88
+ }
89
+
90
+ export function hostsFor(kind: ElementKind): readonly UIHost[] {
91
+ return SUPPORT[kind];
92
+ }
93
+
94
+ export function isSupportedOn(host: UIHost, kind: ElementKind): boolean {
95
+ return SUPPORT[kind].includes(host);
96
+ }
97
+
98
+ /**
99
+ * Inputs the form keeps no value for: geometry lives on the Grasshopper param after a pick, and a
100
+ * button only sends a press. Value updates and presets skip them; holding a button's `true` would
101
+ * fire its action again on every solve.
102
+ */
103
+ export function isValuelessInput(item: InputLayoutItem, input: SchemaInput | undefined): boolean {
104
+ return isGeometryParamType(input?.paramType) || isTriggerItem(item);
105
+ }
106
+
107
+ export function valuelessInputIds(schema: UISchema): Set<string> {
108
+ const ids = new Set<string>();
109
+ for (const input of schema.inputs) {
110
+ if (isGeometryParamType(input.paramType)) ids.add(input.id);
111
+ }
112
+ for (const group of getGroups(schema)) {
113
+ for (const item of group.items ?? []) {
114
+ if (isTriggerItem(item)) ids.add((item as InputLayoutItem).paramId);
115
+ }
116
+ }
117
+ return ids;
118
+ }
119
+
120
+ /** The placed items a host won't render, for the builder's summary of where the UI runs. */
121
+ export function unsupportedItems(schema: UISchema, host: UIHost): LayoutItem[] {
122
+ const items: LayoutItem[] = [];
123
+ for (const group of getGroups(schema)) {
124
+ for (const item of group.items ?? []) {
125
+ if (!isSupportedOn(host, layoutItemKind(item, schema.inputs))) items.push(item);
126
+ }
127
+ }
128
+ return items;
129
+ }
@@ -0,0 +1,44 @@
1
+ import type { DropdownWidgetConfig, OptionMedia, UISchema } from '@selvajs/schemas';
2
+
3
+ export type OptionDisplay = NonNullable<DropdownWidgetConfig['displayAs']>;
4
+
5
+ // Past this a button row no longer fits a panel column. A computed list can grow past it at
6
+ // runtime, so the row turns back into a dropdown instead of wrapping.
7
+ const MAX_SEGMENTED_OPTIONS = 6;
8
+
9
+ export function resolveOptionDisplay(
10
+ displayAs: string | undefined,
11
+ optionCount: number
12
+ ): OptionDisplay {
13
+ switch (displayAs) {
14
+ case 'checklist':
15
+ case 'tiles':
16
+ return displayAs;
17
+ case 'segmented':
18
+ return optionCount <= MAX_SEGMENTED_OPTIONS ? 'segmented' : 'dropdown';
19
+ default:
20
+ return 'dropdown';
21
+ }
22
+ }
23
+
24
+ export type GlyphSource = { kind: 'icon'; d: string } | { kind: 'image'; src: string };
25
+
26
+ // The schema can come from any .gh, so an image reaches <img> only as an inline raster data URI.
27
+ // Anything else could be a URL that makes every viewer's browser call wherever the file points.
28
+ const RASTER_DATA_URI = /^data:image\/(webp|jpeg|png);base64,[A-Za-z0-9+/=]+$/;
29
+
30
+ /** What to draw beside an option: its thumbnail, else its icon. */
31
+ export function optionGlyph(
32
+ media: OptionMedia | undefined,
33
+ assets: UISchema['assets'] | undefined
34
+ ): GlyphSource | undefined {
35
+ if (!media || !assets) return undefined;
36
+
37
+ if (media.image) {
38
+ const src = assets[media.image]?.img;
39
+ if (src && RASTER_DATA_URI.test(src)) return { kind: 'image', src };
40
+ }
41
+
42
+ const d = media.icon ? assets[media.icon]?.d : undefined;
43
+ return d ? { kind: 'icon', d } : undefined;
44
+ }