@selvajs/ui 6.6.0-beta.9 → 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 (345) hide show
  1. package/README.md +0 -3
  2. package/dist/components/ErrorScreen.svelte +1 -1
  3. package/dist/components/compute/AppLayout.svelte +73 -45
  4. package/dist/components/compute/AppLayout.svelte.d.ts +14 -2
  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 +1 -1
  10. package/dist/components/compute/SolveMessages.svelte +79 -88
  11. package/dist/components/compute/SolveMessages.svelte.d.ts +5 -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 +5 -5
  17. package/dist/components/layout/PageHeader.svelte +3 -3
  18. package/dist/components/layout/SideNav.svelte +3 -3
  19. package/dist/components/layout/SubNav.svelte +2 -2
  20. package/dist/components/preview/ChartOutput.svelte +141 -50
  21. package/dist/components/preview/Group.svelte +9 -9
  22. package/dist/components/preview/HelpButton.svelte +1 -1
  23. package/dist/components/preview/ImageOutput.svelte +13 -10
  24. package/dist/components/preview/InputControl.svelte +13 -12
  25. package/dist/components/preview/OutputDisplay.svelte +26 -17
  26. package/dist/components/preview/TabBar.svelte +8 -6
  27. package/dist/components/preview/TabBar.svelte.d.ts +2 -0
  28. package/dist/components/preview/TabContent.svelte +8 -8
  29. package/dist/components/preview/TabLayout.svelte +6 -7
  30. package/dist/components/preview/inputs/CheckboxInput.svelte +1 -1
  31. package/dist/components/preview/inputs/ChecklistInput.svelte +5 -5
  32. package/dist/components/preview/inputs/ColorInput.svelte +356 -14
  33. package/dist/components/preview/inputs/ColorInput.svelte.d.ts +1 -0
  34. package/dist/components/preview/inputs/DropdownInput.svelte +3 -3
  35. package/dist/components/preview/inputs/FileInput.svelte +17 -12
  36. package/dist/components/preview/inputs/GeometryInput.svelte +4 -4
  37. package/dist/components/preview/inputs/GeometryInput.svelte.d.ts +1 -1
  38. package/dist/components/preview/inputs/NumberInput.svelte +8 -8
  39. package/dist/components/preview/inputs/OptionGlyph.svelte +1 -1
  40. package/dist/components/preview/inputs/OptionGlyph.svelte.d.ts +1 -1
  41. package/dist/components/preview/inputs/SegmentedInput.svelte +3 -2
  42. package/dist/components/preview/inputs/TextInput.svelte +5 -5
  43. package/dist/components/preview/inputs/TileInput.svelte +8 -5
  44. package/dist/components/primitives/CalculateButton.svelte +10 -4
  45. package/dist/components/primitives/Callout.svelte +8 -6
  46. package/dist/components/primitives/Callout.svelte.d.ts +4 -4
  47. package/dist/components/primitives/DataTable.svelte +1 -1
  48. package/dist/components/primitives/FilterableDropdown.svelte +13 -1
  49. package/dist/components/primitives/FilterableDropdown.svelte.d.ts +5 -0
  50. package/dist/components/primitives/ImageUploadField.svelte +1 -1
  51. package/dist/components/primitives/SolvingIndicator.svelte +242 -41
  52. package/dist/components/primitives/SolvingIndicator.svelte.d.ts +13 -5
  53. package/dist/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
  54. package/dist/components/primitives/badge/badge.svelte +2 -2
  55. package/dist/components/primitives/badge/badge.svelte.d.ts +6 -6
  56. package/dist/components/primitives/button/button.svelte +7 -8
  57. package/dist/components/primitives/button/button.svelte.d.ts +19 -19
  58. package/dist/components/primitives/card/card.svelte +1 -1
  59. package/dist/components/primitives/card/card.svelte.d.ts +1 -1
  60. package/dist/components/primitives/checkbox/checkbox.svelte +1 -1
  61. package/dist/components/primitives/command/command-input.svelte +1 -1
  62. package/dist/components/primitives/command/command-item.svelte +1 -1
  63. package/dist/components/primitives/command/command-link-item.svelte +1 -1
  64. package/dist/components/primitives/command/command.svelte +1 -1
  65. package/dist/components/primitives/context-menu/context-menu-checkbox-item.svelte +1 -1
  66. package/dist/components/primitives/context-menu/context-menu-content.svelte +1 -1
  67. package/dist/components/primitives/context-menu/context-menu-item.svelte +1 -1
  68. package/dist/components/primitives/context-menu/context-menu-radio-item.svelte +1 -1
  69. package/dist/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
  70. package/dist/components/primitives/context-menu/context-menu-sub-trigger.svelte +1 -1
  71. package/dist/components/primitives/dialog/dialog-content.svelte +3 -3
  72. package/dist/components/primitives/drawer/Drawer.svelte +1 -1
  73. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +31 -11
  74. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +2 -0
  75. package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte +5 -1
  76. package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte.d.ts +2 -0
  77. package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte +4 -2
  78. package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte.d.ts +2 -1
  79. package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +1 -1
  80. package/dist/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +1 -1
  81. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
  82. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +1 -1
  83. package/dist/components/primitives/index.d.ts +1 -1
  84. package/dist/components/primitives/index.js +1 -1
  85. package/dist/components/primitives/input/input.svelte +2 -2
  86. package/dist/components/primitives/input-group/input-group-input.svelte.d.ts +1 -1
  87. package/dist/components/primitives/input-group/input-group.svelte +1 -1
  88. package/dist/components/primitives/mode-toggle/mode-toggle.svelte +2 -2
  89. package/dist/components/primitives/popover/popover-content.svelte +1 -1
  90. package/dist/components/primitives/resizable/resizable-handle.svelte +2 -2
  91. package/dist/components/primitives/search/search.svelte +1 -1
  92. package/dist/components/primitives/select/select-content.svelte +1 -1
  93. package/dist/components/primitives/select/select-item.svelte +1 -1
  94. package/dist/components/primitives/select/select-trigger.svelte +1 -1
  95. package/dist/components/primitives/slider/slider.svelte +1 -1
  96. package/dist/components/primitives/switch/switch.svelte +1 -1
  97. package/dist/components/primitives/tabs/tabs-list.svelte +2 -2
  98. package/dist/components/primitives/tabs/tabs-list.svelte.d.ts +6 -6
  99. package/dist/components/primitives/tabs/tabs-trigger.svelte +2 -2
  100. package/dist/components/primitives/tabs/tabs-trigger.svelte.d.ts +6 -6
  101. package/dist/components/primitives/textarea/textarea.svelte +1 -1
  102. package/dist/components/primitives/toggle/toggle.svelte +8 -2
  103. package/dist/components/primitives/toggle/toggle.svelte.d.ts +10 -4
  104. package/dist/components/primitives/toggle-group/toggle-group-item.svelte +1 -1
  105. package/dist/components/primitives/toggle-group/toggle-group.svelte +1 -1
  106. package/dist/components/primitives/tooltip/index.d.ts +6 -0
  107. package/dist/components/primitives/tooltip/index.js +8 -0
  108. package/dist/components/primitives/tooltip/tooltip-content.svelte +34 -0
  109. package/dist/components/primitives/tooltip/tooltip-content.svelte.d.ts +10 -0
  110. package/dist/components/primitives/tooltip/tooltip-portal.svelte +7 -0
  111. package/dist/components/primitives/tooltip/tooltip-portal.svelte.d.ts +4 -0
  112. package/dist/components/primitives/tooltip/tooltip-provider.svelte +7 -0
  113. package/dist/components/primitives/tooltip/tooltip-provider.svelte.d.ts +4 -0
  114. package/dist/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
  115. package/dist/components/primitives/tooltip/tooltip-trigger.svelte.d.ts +4 -0
  116. package/dist/components/primitives/tooltip/tooltip.svelte +7 -0
  117. package/dist/components/primitives/tooltip/tooltip.svelte.d.ts +4 -0
  118. package/dist/components/viewer/MeshMetadataPanel.svelte +2 -2
  119. package/dist/components/viewer/SceneManager.svelte +32 -21
  120. package/dist/components/viewer/SceneManager.svelte.d.ts +3 -1
  121. package/dist/components/viewer/Viewer.svelte +128 -178
  122. package/dist/components/viewer/Viewer.svelte.d.ts +7 -2
  123. package/dist/components/viewer/ViewerDock.svelte +404 -0
  124. package/dist/components/viewer/ViewerDock.svelte.d.ts +42 -0
  125. package/dist/composables/useFooterItem.svelte.d.ts +1 -1
  126. package/dist/composables/useFooterItem.svelte.js +1 -1
  127. package/dist/compute/liveProgress.svelte.d.ts +16 -0
  128. package/dist/compute/liveProgress.svelte.js +90 -0
  129. package/dist/compute/solving.svelte.d.ts +7 -9
  130. package/dist/compute/solving.svelte.js +56 -48
  131. package/dist/constants.d.ts +6 -8
  132. package/dist/constants.js +8 -11
  133. package/dist/contexts/hostContext.svelte.d.ts +1 -1
  134. package/dist/features/chart/plotly-compat.d.ts +15 -0
  135. package/dist/features/chart/plotly-compat.js +124 -0
  136. package/dist/i18n/messages.d.ts +17 -0
  137. package/dist/i18n/messages.js +26 -0
  138. package/dist/index.d.ts +2 -0
  139. package/dist/index.js +2 -0
  140. package/dist/public.d.ts +1 -0
  141. package/dist/public.js +1 -0
  142. package/dist/schema/visibility-rules.d.ts +7 -1
  143. package/dist/schema/visibility-rules.js +17 -0
  144. package/dist/styles/base.css +93 -86
  145. package/dist/utils/color-space.d.ts +21 -0
  146. package/dist/utils/color-space.js +90 -0
  147. package/package.json +31 -23
  148. package/src/lib/components/ErrorScreen.svelte +1 -1
  149. package/src/lib/components/compute/AppLayout.svelte +74 -46
  150. package/src/lib/components/compute/CollapsedPanelStrip.svelte +4 -2
  151. package/src/lib/components/compute/ComputeApp.svelte +6 -2
  152. package/src/lib/components/compute/ComputeMessagesDialog.svelte +4 -4
  153. package/src/lib/components/compute/ParameterPresetManager.svelte +1 -1
  154. package/src/lib/components/compute/SolveMessages.svelte +81 -90
  155. package/src/lib/components/layout/AppShell.svelte +2 -2
  156. package/src/lib/components/layout/FooterItemRenderer.svelte +2 -2
  157. package/src/lib/components/layout/PageContent.svelte +3 -2
  158. package/src/lib/components/layout/PageFooter.svelte +5 -5
  159. package/src/lib/components/layout/PageHeader.svelte +3 -3
  160. package/src/lib/components/layout/SideNav.svelte +4 -4
  161. package/src/lib/components/layout/SubNav.svelte +2 -2
  162. package/src/lib/components/preview/ChartOutput.svelte +141 -50
  163. package/src/lib/components/preview/Group.svelte +9 -9
  164. package/src/lib/components/preview/HelpButton.svelte +1 -1
  165. package/src/lib/components/preview/ImageOutput.svelte +13 -10
  166. package/src/lib/components/preview/InputControl.svelte +13 -12
  167. package/src/lib/components/preview/OutputDisplay.svelte +26 -17
  168. package/src/lib/components/preview/TabBar.svelte +8 -6
  169. package/src/lib/components/preview/TabContent.svelte +8 -8
  170. package/src/lib/components/preview/TabLayout.svelte +6 -7
  171. package/src/lib/components/preview/inputs/CheckboxInput.svelte +1 -1
  172. package/src/lib/components/preview/inputs/ChecklistInput.svelte +5 -5
  173. package/src/lib/components/preview/inputs/ColorInput.svelte +356 -14
  174. package/src/lib/components/preview/inputs/DropdownInput.svelte +3 -3
  175. package/src/lib/components/preview/inputs/FileInput.svelte +17 -12
  176. package/src/lib/components/preview/inputs/GeometryInput.svelte +4 -4
  177. package/src/lib/components/preview/inputs/NumberInput.svelte +8 -8
  178. package/src/lib/components/preview/inputs/OptionGlyph.svelte +2 -2
  179. package/src/lib/components/preview/inputs/SegmentedInput.svelte +3 -2
  180. package/src/lib/components/preview/inputs/TextInput.svelte +5 -5
  181. package/src/lib/components/preview/inputs/TileInput.svelte +8 -5
  182. package/src/lib/components/primitives/CalculateButton.svelte +10 -4
  183. package/src/lib/components/primitives/Callout.svelte +9 -7
  184. package/src/lib/components/primitives/DataTable.svelte +1 -1
  185. package/src/lib/components/primitives/FilterableDropdown.svelte +14 -2
  186. package/src/lib/components/primitives/ImageUploadField.svelte +1 -1
  187. package/src/lib/components/primitives/IssueList.svelte +1 -1
  188. package/src/lib/components/primitives/SeverityIcon.svelte +1 -1
  189. package/src/lib/components/primitives/SolvingIndicator.svelte +242 -41
  190. package/src/lib/components/primitives/StateDisplay.svelte +1 -1
  191. package/src/lib/components/primitives/alert-dialog/alert-dialog-action.svelte +2 -2
  192. package/src/lib/components/primitives/alert-dialog/alert-dialog-cancel.svelte +2 -2
  193. package/src/lib/components/primitives/alert-dialog/alert-dialog-content.svelte +2 -2
  194. package/src/lib/components/primitives/alert-dialog/alert-dialog-description.svelte +1 -1
  195. package/src/lib/components/primitives/alert-dialog/alert-dialog-footer.svelte +1 -1
  196. package/src/lib/components/primitives/alert-dialog/alert-dialog-header.svelte +1 -1
  197. package/src/lib/components/primitives/alert-dialog/alert-dialog-overlay.svelte +1 -1
  198. package/src/lib/components/primitives/alert-dialog/alert-dialog-title.svelte +1 -1
  199. package/src/lib/components/primitives/badge/badge.svelte +3 -3
  200. package/src/lib/components/primitives/button/button.svelte +7 -8
  201. package/src/lib/components/primitives/button-group/button-group-separator.svelte +2 -2
  202. package/src/lib/components/primitives/button-group/button-group-text.svelte +1 -1
  203. package/src/lib/components/primitives/button-group/button-group.svelte +1 -1
  204. package/src/lib/components/primitives/card/card-content.svelte +1 -1
  205. package/src/lib/components/primitives/card/card-description.svelte +1 -1
  206. package/src/lib/components/primitives/card/card-footer.svelte +1 -1
  207. package/src/lib/components/primitives/card/card-header.svelte +1 -1
  208. package/src/lib/components/primitives/card/card-title.svelte +1 -1
  209. package/src/lib/components/primitives/card/card.svelte +2 -2
  210. package/src/lib/components/primitives/checkbox/checkbox.svelte +2 -2
  211. package/src/lib/components/primitives/command/command-dialog.svelte +2 -2
  212. package/src/lib/components/primitives/command/command-empty.svelte +1 -1
  213. package/src/lib/components/primitives/command/command-group.svelte +1 -1
  214. package/src/lib/components/primitives/command/command-input.svelte +3 -3
  215. package/src/lib/components/primitives/command/command-item.svelte +2 -2
  216. package/src/lib/components/primitives/command/command-link-item.svelte +2 -2
  217. package/src/lib/components/primitives/command/command-list.svelte +1 -1
  218. package/src/lib/components/primitives/command/command-separator.svelte +1 -1
  219. package/src/lib/components/primitives/command/command-shortcut.svelte +1 -1
  220. package/src/lib/components/primitives/command/command.svelte +2 -2
  221. package/src/lib/components/primitives/context-menu/context-menu-checkbox-item.svelte +2 -2
  222. package/src/lib/components/primitives/context-menu/context-menu-content.svelte +2 -2
  223. package/src/lib/components/primitives/context-menu/context-menu-group-heading.svelte +1 -1
  224. package/src/lib/components/primitives/context-menu/context-menu-item.svelte +2 -2
  225. package/src/lib/components/primitives/context-menu/context-menu-label.svelte +1 -1
  226. package/src/lib/components/primitives/context-menu/context-menu-radio-item.svelte +2 -2
  227. package/src/lib/components/primitives/context-menu/context-menu-separator.svelte +1 -1
  228. package/src/lib/components/primitives/context-menu/context-menu-shortcut.svelte +1 -1
  229. package/src/lib/components/primitives/context-menu/context-menu-sub-content.svelte +2 -2
  230. package/src/lib/components/primitives/context-menu/context-menu-sub-trigger.svelte +2 -2
  231. package/src/lib/components/primitives/dialog/dialog-content.svelte +4 -4
  232. package/src/lib/components/primitives/dialog/dialog-description.svelte +1 -1
  233. package/src/lib/components/primitives/dialog/dialog-footer.svelte +1 -1
  234. package/src/lib/components/primitives/dialog/dialog-header.svelte +1 -1
  235. package/src/lib/components/primitives/dialog/dialog-overlay.svelte +1 -1
  236. package/src/lib/components/primitives/dialog/dialog-title.svelte +1 -1
  237. package/src/lib/components/primitives/drawer/Drawer.svelte +1 -1
  238. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +32 -12
  239. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-content.svelte +6 -2
  240. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-group-heading.svelte +1 -1
  241. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-item.svelte +5 -3
  242. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-label.svelte +1 -1
  243. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +2 -2
  244. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-separator.svelte +1 -1
  245. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +2 -2
  246. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +2 -2
  247. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +2 -2
  248. package/src/lib/components/primitives/empty/empty-content.svelte +1 -1
  249. package/src/lib/components/primitives/empty/empty-description.svelte +1 -1
  250. package/src/lib/components/primitives/empty/empty-header.svelte +1 -1
  251. package/src/lib/components/primitives/empty/empty-media.svelte +1 -1
  252. package/src/lib/components/primitives/empty/empty-title.svelte +1 -1
  253. package/src/lib/components/primitives/empty/empty.svelte +1 -1
  254. package/src/lib/components/primitives/field/field-content.svelte +1 -1
  255. package/src/lib/components/primitives/field/field-description.svelte +1 -1
  256. package/src/lib/components/primitives/field/field-error.svelte +1 -1
  257. package/src/lib/components/primitives/field/field-group.svelte +1 -1
  258. package/src/lib/components/primitives/field/field-label.svelte +2 -2
  259. package/src/lib/components/primitives/field/field-legend.svelte +1 -1
  260. package/src/lib/components/primitives/field/field-separator.svelte +2 -2
  261. package/src/lib/components/primitives/field/field-set.svelte +1 -1
  262. package/src/lib/components/primitives/field/field-title.svelte +1 -1
  263. package/src/lib/components/primitives/field/field.svelte +1 -1
  264. package/src/lib/components/primitives/index.ts +1 -1
  265. package/src/lib/components/primitives/input/input.svelte +3 -3
  266. package/src/lib/components/primitives/input-group/input-group-addon.svelte +1 -1
  267. package/src/lib/components/primitives/input-group/input-group-button.svelte +2 -2
  268. package/src/lib/components/primitives/input-group/input-group-input.svelte +2 -2
  269. package/src/lib/components/primitives/input-group/input-group-text.svelte +1 -1
  270. package/src/lib/components/primitives/input-group/input-group-textarea.svelte +2 -2
  271. package/src/lib/components/primitives/input-group/input-group.svelte +2 -2
  272. package/src/lib/components/primitives/label/label.svelte +1 -1
  273. package/src/lib/components/primitives/mode-toggle/mode-toggle.svelte +2 -2
  274. package/src/lib/components/primitives/popover/popover-content.svelte +2 -2
  275. package/src/lib/components/primitives/popover/popover-description.svelte +1 -1
  276. package/src/lib/components/primitives/popover/popover-header.svelte +1 -1
  277. package/src/lib/components/primitives/popover/popover-title.svelte +1 -1
  278. package/src/lib/components/primitives/popover/popover-trigger.svelte +1 -1
  279. package/src/lib/components/primitives/resizable/resizable-handle.svelte +3 -3
  280. package/src/lib/components/primitives/resizable/resizable-pane-group.svelte +1 -1
  281. package/src/lib/components/primitives/scroll-area/scroll-area-scrollbar.svelte +1 -1
  282. package/src/lib/components/primitives/scroll-area/scroll-area.svelte +1 -1
  283. package/src/lib/components/primitives/search/search.svelte +2 -2
  284. package/src/lib/components/primitives/select/select-content.svelte +2 -2
  285. package/src/lib/components/primitives/select/select-group-heading.svelte +1 -1
  286. package/src/lib/components/primitives/select/select-item.svelte +2 -2
  287. package/src/lib/components/primitives/select/select-label.svelte +1 -1
  288. package/src/lib/components/primitives/select/select-scroll-down-button.svelte +1 -1
  289. package/src/lib/components/primitives/select/select-scroll-up-button.svelte +1 -1
  290. package/src/lib/components/primitives/select/select-separator.svelte +2 -2
  291. package/src/lib/components/primitives/select/select-trigger.svelte +2 -2
  292. package/src/lib/components/primitives/separator/separator.svelte +1 -1
  293. package/src/lib/components/primitives/slider/slider.svelte +2 -2
  294. package/src/lib/components/primitives/spinner/spinner.svelte +1 -1
  295. package/src/lib/components/primitives/switch/switch.svelte +2 -2
  296. package/src/lib/components/primitives/tabs/tabs-content.svelte +1 -1
  297. package/src/lib/components/primitives/tabs/tabs-list.svelte +3 -3
  298. package/src/lib/components/primitives/tabs/tabs-trigger.svelte +3 -3
  299. package/src/lib/components/primitives/tabs/tabs.svelte +1 -1
  300. package/src/lib/components/primitives/textarea/textarea.svelte +2 -2
  301. package/src/lib/components/primitives/toggle/toggle.svelte +9 -3
  302. package/src/lib/components/primitives/toggle-group/toggle-group-item.svelte +3 -3
  303. package/src/lib/components/primitives/toggle-group/toggle-group.svelte +3 -3
  304. package/src/lib/components/primitives/tooltip/index.ts +19 -0
  305. package/src/lib/components/primitives/tooltip/tooltip-content.svelte +34 -0
  306. package/src/lib/components/primitives/tooltip/tooltip-portal.svelte +7 -0
  307. package/src/lib/components/primitives/tooltip/tooltip-provider.svelte +7 -0
  308. package/src/lib/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
  309. package/src/lib/components/primitives/tooltip/tooltip.svelte +7 -0
  310. package/src/lib/components/viewer/MeshMetadataPanel.svelte +2 -2
  311. package/src/lib/components/viewer/SceneManager.svelte +32 -21
  312. package/src/lib/components/viewer/Viewer.svelte +129 -179
  313. package/src/lib/components/viewer/ViewerDock.svelte +404 -0
  314. package/src/lib/composables/useFooterItem.svelte.ts +1 -1
  315. package/src/lib/compute/liveProgress.svelte.ts +103 -0
  316. package/src/lib/compute/solving.svelte.ts +56 -55
  317. package/src/lib/constants.ts +8 -11
  318. package/src/lib/contexts/hostContext.svelte.ts +1 -1
  319. package/src/lib/features/chart/plotly-compat.ts +141 -0
  320. package/src/lib/i18n/messages.ts +43 -0
  321. package/src/lib/index.ts +2 -0
  322. package/src/lib/public.ts +1 -0
  323. package/src/lib/schema/visibility-rules.ts +27 -1
  324. package/src/lib/styles/base.css +93 -86
  325. package/src/lib/utils/color-space.ts +107 -0
  326. package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
  327. package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte.d.ts +0 -3
  328. package/dist/components/primitives/theme-switcher/index.d.ts +0 -1
  329. package/dist/components/primitives/theme-switcher/index.js +0 -1
  330. package/dist/styles/themes/cyberpunk.css +0 -98
  331. package/dist/styles/themes/neutral.css +0 -72
  332. package/dist/styles/themes/ocean.css +0 -75
  333. package/dist/styles/themes/selva.css +0 -105
  334. package/dist/theme/themeStore.svelte.d.ts +0 -12
  335. package/dist/theme/themeStore.svelte.js +0 -40
  336. package/dist/theme/themes.d.ts +0 -5
  337. package/dist/theme/themes.js +0 -13
  338. package/src/lib/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
  339. package/src/lib/components/primitives/theme-switcher/index.ts +0 -1
  340. package/src/lib/styles/themes/cyberpunk.css +0 -98
  341. package/src/lib/styles/themes/neutral.css +0 -72
  342. package/src/lib/styles/themes/ocean.css +0 -75
  343. package/src/lib/styles/themes/selva.css +0 -105
  344. package/src/lib/theme/themeStore.svelte.ts +0 -50
  345. package/src/lib/theme/themes.ts +0 -18
@@ -1,10 +1,14 @@
1
1
  <script lang="ts">
2
2
  import type { OutputChartLayoutItem } from '@selvajs/schemas';
3
- import { onMount } from 'svelte';
3
+ import { onMount, tick } from 'svelte';
4
+ import { mode } from 'mode-watcher';
4
5
  import { Loader, Maximize, Minimize } from '@lucide/svelte';
5
- import { loadScript } from '../../utils/loadScript';
6
- import { getLocaleContext } from '../../i18n/localeContext.svelte';
7
- import { formatMessage } from '../../i18n/messages';
6
+ import { loadScript } from '../../utils/loadScript.js';
7
+ import { getLocaleContext } from '../../i18n/localeContext.svelte.js';
8
+ import { formatMessage } from '../../i18n/messages.js';
9
+ import { upgradePlotlyFigure, type PlotlyFigure } from '../../features/chart/plotly-compat.js';
10
+ import { saveBlob } from '../../utils/host-files.js';
11
+ import { toast } from '../primitives/sonner/index.js';
8
12
 
9
13
  interface Props {
10
14
  item: OutputChartLayoutItem;
@@ -16,19 +20,18 @@
16
20
  const locale = getLocaleContext();
17
21
  const t = $derived(locale.messages);
18
22
 
19
- const MAP_TYPE_SET = new Set(['scattermap', 'scattermapbox', 'choropleth', 'scattergeo']);
20
-
21
- type PlotlyTrace = Record<string, unknown>;
22
- type PlotlyFigure = {
23
- data: PlotlyTrace[];
24
- layout: Record<string, unknown>;
25
- config?: Record<string, unknown>;
26
- };
23
+ const MAP_TYPE_SET = new Set([
24
+ 'scattermap',
25
+ 'choroplethmap',
26
+ 'densitymap',
27
+ 'choropleth',
28
+ 'scattergeo'
29
+ ]);
27
30
 
28
31
  const figData = $derived.by(() => {
29
32
  if (!value) return null;
30
33
  try {
31
- return JSON.parse(value) as PlotlyFigure;
34
+ return upgradePlotlyFigure(JSON.parse(value) as PlotlyFigure);
32
35
  } catch {
33
36
  return null;
34
37
  }
@@ -46,9 +49,9 @@
46
49
  if (window.Plotly) return window.Plotly;
47
50
 
48
51
  // Pinned by hash: the plugin's web UI runs this on the origin that holds its bridge secret.
49
- await loadScript('https://cdn.plot.ly/plotly-3.4.0.min.js', {
52
+ await loadScript('https://cdn.plot.ly/plotly-4.1.2.min.js', {
50
53
  crossOrigin: 'anonymous',
51
- integrity: 'sha384-pFOQ7loGBChmUyS4Tszy+he8OWeYkwTFjc2xii4aJUWWiGwf2u2OEc04T5iDRpMp'
54
+ integrity: 'sha384-hHv6D3tTUUBpp4tVv6t2Dc3oGuRhphmWOTKUR8jWyN0Pnon1g3iebKCNDNmKmxo8'
52
55
  });
53
56
  // @ts-expect-error — Plotly is loaded dynamically onto window
54
57
  return window.Plotly;
@@ -57,6 +60,19 @@
57
60
  // Some embedded WebViews (WKWebView in the Rhino panel) ship without the Fullscreen API at all.
58
61
  const fullscreenSupported = typeof document !== 'undefined' && !!document.fullscreenEnabled;
59
62
 
63
+ // `Plots.resize()`/`relayout({autosize: true})` ask Plotly to re-measure the container itself,
64
+ // which it silently fails to do across a Fullscreen transition — _fullLayout keeps the
65
+ // pre-toggle width/height even though clientWidth/clientHeight are already correct. Passing
66
+ // the measured size explicitly is the only call that actually takes.
67
+ function resizeChart() {
68
+ // @ts-expect-error — Plotly is loaded dynamically onto window
69
+ if (!containerEl || !window.Plotly) return;
70
+ const { width, height } = containerEl.getBoundingClientRect();
71
+ if (width === 0 || height === 0) return;
72
+ // @ts-expect-error — Plotly is loaded dynamically onto window
73
+ window.Plotly.relayout(containerEl, { width, height });
74
+ }
75
+
60
76
  function toggleFullscreen() {
61
77
  if (!wrapperEl) return;
62
78
  if (!document.fullscreenElement) {
@@ -73,27 +89,67 @@
73
89
  $effect(() => {
74
90
  function onFullscreenChange() {
75
91
  isFullscreen = !!document.fullscreenElement;
76
- Promise.resolve().then(() => {
77
- // @ts-expect-error — Plotly is loaded dynamically onto window
78
- if (containerEl && window.Plotly) {
79
- // @ts-expect-error — Plotly is loaded dynamically onto window
80
- window.Plotly.Plots.resize(containerEl);
81
- }
82
- });
92
+ // `tick()` waits for the h-dvh/h-95 class swap this state drives to actually reach the
93
+ // DOM before resizeChart measures it.
94
+ tick().then(resizeChart);
83
95
  }
84
96
  document.addEventListener('fullscreenchange', onFullscreenChange);
85
97
  return () => document.removeEventListener('fullscreenchange', onFullscreenChange);
86
98
  });
87
99
 
88
- function getThemeColors(): { textColor: string; gridColor: string } {
89
- if (!containerEl) return { textColor: '#333', gridColor: '#eee' };
100
+ // Chromium's getComputedStyle returns color values in whatever function the CSS used to
101
+ // declare them — oklch() here, since base.css's theme tokens are oklch(). Plotly's own color
102
+ // parser doesn't recognize oklch() and silently falls back to its #444 default instead of
103
+ // erroring, so every chart read dark axis text even in dark mode. `fillStyle` alone just
104
+ // echoes the oklch() string back unconverted; actually rasterizing a pixel and reading its
105
+ // bytes is what forces a real rgb() value Plotly can parse.
106
+ function toRgb(cssColor: string): string {
107
+ const canvas = document.createElement('canvas');
108
+ canvas.width = 1;
109
+ canvas.height = 1;
110
+ const ctx = canvas.getContext('2d');
111
+ if (!ctx) return cssColor;
112
+ ctx.fillStyle = cssColor;
113
+ ctx.fillRect(0, 0, 1, 1);
114
+ const [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;
115
+ return a === 255 ? `rgb(${r}, ${g}, ${b})` : `rgba(${r}, ${g}, ${b}, ${(a / 255).toFixed(3)})`;
116
+ }
117
+
118
+ function getThemeColors(): {
119
+ textColor: string;
120
+ gridColor: string;
121
+ fontFamily: string;
122
+ colorway: string[];
123
+ } {
124
+ if (!containerEl) return { textColor: '#333', gridColor: '#eee', fontFamily: '', colorway: [] };
90
125
  const style = getComputedStyle(containerEl);
91
- const textColor = style.getPropertyValue('color').trim() || '#333';
92
- const gridColor =
126
+ const textColor = toRgb(style.getPropertyValue('color').trim() || '#333');
127
+ const gridColor = toRgb(
93
128
  style.getPropertyValue('--border')?.trim() ||
94
- style.getPropertyValue('--color-border')?.trim() ||
95
- 'rgba(128,128,128,0.2)';
96
- return { textColor, gridColor };
129
+ style.getPropertyValue('--color-border')?.trim() ||
130
+ 'rgba(128,128,128,0.2)'
131
+ );
132
+ // Figures that leave colours unset take Selva's chart palette rather than Plotly's.
133
+ const colorway = [1, 2, 3, 4, 5]
134
+ .map((i) => style.getPropertyValue(`--chart-${i}`).trim())
135
+ .filter(Boolean)
136
+ .map(toRgb);
137
+ return { textColor, gridColor, fontFamily: style.fontFamily, colorway };
138
+ }
139
+
140
+ async function saveChartImage(
141
+ Plotly: Awaited<ReturnType<typeof loadPlotly>>,
142
+ gd: HTMLElement,
143
+ options: { format?: string; filename?: string } = {}
144
+ ) {
145
+ const format = options.format ?? 'png';
146
+ try {
147
+ const dataUrl: string = await Plotly.toImage(gd, { ...options, format });
148
+ const blob = await (await fetch(dataUrl)).blob();
149
+ await saveBlob(blob, `${options.filename ?? 'chart'}.${format}`);
150
+ } catch {
151
+ toast.error(t.downloadFailed);
152
+ }
97
153
  }
98
154
 
99
155
  async function renderChart() {
@@ -102,7 +158,7 @@
102
158
  loading = true;
103
159
  try {
104
160
  const Plotly = await loadPlotly();
105
- const { textColor, gridColor } = getThemeColors();
161
+ const { textColor, gridColor, fontFamily, colorway } = getThemeColors();
106
162
  const isMapFigure = figData.data?.some((t) => MAP_TYPE_SET.has(t.type as string));
107
163
 
108
164
  const {
@@ -122,23 +178,58 @@
122
178
  ...layoutRest,
123
179
  autosize: true,
124
180
  margin: { t: 24, r: 8, b: 40, l: 60, pad: 0 },
125
- font: { color: textColor },
181
+ font: { color: textColor, ...(fontFamily ? { family: fontFamily } : {}) },
182
+ ...(colorway.length && !layoutRest.colorway ? { colorway } : {}),
126
183
  paper_bgcolor: layoutRest.paper_bgcolor ?? 'transparent',
127
184
  plot_bgcolor: layoutRest.plot_bgcolor ?? 'transparent',
128
- ...(!isMapFigure && layoutRest.xaxis
129
- ? { xaxis: { ...(layoutRest.xaxis as object), gridcolor: gridColor, color: textColor } }
130
- : {}),
131
- ...(!isMapFigure && layoutRest.yaxis
132
- ? { yaxis: { ...(layoutRest.yaxis as object), gridcolor: gridColor, color: textColor } }
185
+ // Plotly's axis tick/label color doesn't inherit the top-level `font.color`, so this
186
+ // has to be set even when the figure's own JSON never declared an xaxis/yaxis —
187
+ // which the mock's figures don't. Gating on `layoutRest.xaxis` existing left every
188
+ // axis on Plotly's built-in #444 default, light or dark mode.
189
+ ...(!isMapFigure
190
+ ? {
191
+ xaxis: { ...(layoutRest.xaxis as object), gridcolor: gridColor, color: textColor },
192
+ yaxis: { ...(layoutRest.yaxis as object), gridcolor: gridColor, color: textColor }
193
+ }
133
194
  : {})
134
195
  };
135
196
 
136
- Plotly.react(containerEl, figData.data, layout, {
137
- responsive: true,
138
- displayModeBar: 'hover',
139
- displaylogo: false,
140
- modeBarButtonsToRemove: ['sendDataToCloud', 'lasso2d', 'select2d'],
141
- ...figData.config
197
+ const figConfig = (figData.config ?? {}) as {
198
+ modeBarButtonsToRemove?: string[];
199
+ modeBarButtonsToAdd?: unknown[];
200
+ toImageButtonOptions?: { format?: string; filename?: string };
201
+ };
202
+ Plotly.react(containerEl, {
203
+ data: figData.data,
204
+ layout,
205
+ // Animated figures (e.g. Canopy's Animate) carry their frames here.
206
+ frames: figData.frames ?? [],
207
+ config: {
208
+ responsive: true,
209
+ displayModeBar: 'hover',
210
+ displaylogo: false,
211
+ // Plotly 4's "Share chart" button uploads the figure to Plotly's cloud.
212
+ showSendToCloud: false,
213
+ ...figConfig,
214
+ // Plotly's own toImage button downloads through an <a download>, which the Rhino
215
+ // panel's WebView blocks; this one saves through saveBlob like every other file.
216
+ modeBarButtonsToRemove: [
217
+ 'sendDataToCloud',
218
+ 'lasso2d',
219
+ 'select2d',
220
+ 'toImage',
221
+ ...(figConfig.modeBarButtonsToRemove ?? [])
222
+ ],
223
+ modeBarButtonsToAdd: [
224
+ {
225
+ name: 'toImage',
226
+ title: t.downloadChartImage,
227
+ icon: Plotly.Icons.camera,
228
+ click: (gd: HTMLElement) => saveChartImage(Plotly, gd, figConfig.toImageButtonOptions)
229
+ },
230
+ ...(figConfig.modeBarButtonsToAdd ?? [])
231
+ ]
232
+ }
142
233
  });
143
234
  } catch (e) {
144
235
  error = e instanceof Error ? e.message : t.chartRenderFailed;
@@ -154,11 +245,7 @@
154
245
  const ro = new ResizeObserver(() => {
155
246
  if (resizeTimer) clearTimeout(resizeTimer);
156
247
  resizeTimer = setTimeout(() => {
157
- // @ts-expect-error — Plotly is loaded dynamically onto window
158
- if (containerEl && window.Plotly) {
159
- // @ts-expect-error — Plotly is loaded dynamically onto window
160
- window.Plotly.Plots.resize(containerEl);
161
- }
248
+ resizeChart();
162
249
  resizeTimer = null;
163
250
  }, 150);
164
251
  });
@@ -175,6 +262,10 @@
175
262
  let renderTimeout: ReturnType<typeof setTimeout> | null = null;
176
263
 
177
264
  $effect(() => {
265
+ // Re-reads mode.current so a theme toggle re-renders with the new axis/font colors —
266
+ // getThemeColors() only reads the DOM once, at render time, and nothing else repaints an
267
+ // already-drawn chart when the page's color scheme changes under it.
268
+ void mode.current;
178
269
  if (!value || !mounted || !containerEl) return;
179
270
  if (renderTimeout) clearTimeout(renderTimeout);
180
271
  renderTimeout = setTimeout(() => {
@@ -189,7 +280,7 @@
189
280
 
190
281
  <div
191
282
  bind:this={wrapperEl}
192
- class="group rounded relative overflow-hidden border border-border {isFullscreen
283
+ class="group relative overflow-hidden rounded-lg border border-border-strong {isFullscreen
193
284
  ? 'bg-background'
194
285
  : ''}"
195
286
  >
@@ -208,7 +299,7 @@
208
299
  >
209
300
  {#if loading}
210
301
  <div
211
- class="rounded p-1.5 backdrop-blur-sm flex items-center border border-border bg-background/80 text-muted-foreground"
302
+ class="p-1.5 backdrop-blur-sm flex items-center rounded-sm border border-border-strong bg-background/80 text-muted-foreground"
212
303
  >
213
304
  <Loader size={14} class="animate-spin" />
214
305
  </div>
@@ -220,7 +311,7 @@
220
311
  disabled={loading}
221
312
  title={isFullscreen ? t.exitFullscreen : t.fullscreen}
222
313
  aria-label={isFullscreen ? t.exitFullscreen : t.fullscreen}
223
- class="rounded p-1.5 backdrop-blur-sm flex items-center border border-border bg-background/80 text-foreground transition-colors hover:bg-background disabled:cursor-not-allowed disabled:opacity-50"
314
+ class="p-1.5 backdrop-blur-sm flex items-center rounded-sm border border-border-strong bg-background/80 text-foreground transition-colors hover:bg-background disabled:cursor-not-allowed disabled:opacity-50"
224
315
  >
225
316
  {#if isFullscreen}
226
317
  <Minimize size={14} />
@@ -2,7 +2,7 @@
2
2
  import type { LayoutItem, InputLayoutItem, OutputLayoutItem } from '@selvajs/schemas';
3
3
  import type { Snippet } from 'svelte';
4
4
  import { ChevronDown } from '@lucide/svelte';
5
- import { buildVisibilityMap, itemKey } from '../../schema/visibility-rules';
5
+ import { buildVisibilityMap, itemKey } from '../../schema/visibility-rules.js';
6
6
 
7
7
  interface Props {
8
8
  label: string;
@@ -69,7 +69,7 @@
69
69
  </div>
70
70
  {/snippet}
71
71
 
72
- <section class="shadow-xs rounded-xl border bg-card">
72
+ <section class="rounded-xl border bg-card shadow-raised">
73
73
  {#if flat}
74
74
  <div class="p-4">
75
75
  {@render grid()}
@@ -80,18 +80,18 @@
80
80
  <h3>
81
81
  <button
82
82
  type="button"
83
- class="gap-3 px-4 pt-3.5 flex w-full items-start text-left outline-none select-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset {description
83
+ class="gap-3 px-4 pt-4 flex w-full items-start text-left outline-none select-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset {description
84
84
  ? 'pb-0'
85
- : 'pb-3.5'}"
85
+ : 'pb-3'}"
86
86
  aria-expanded={!collapsed}
87
87
  aria-describedby={description ? descriptionId : undefined}
88
88
  onclick={onToggle}
89
89
  >
90
- <span class="min-w-0 text-base font-semibold leading-snug flex-1 text-foreground"
90
+ <span class="min-w-0 text-sm font-semibold leading-snug flex-1 text-foreground"
91
91
  >{label}</span
92
92
  >
93
93
  <ChevronDown
94
- class="mt-1 h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200 {collapsed
94
+ class="mt-0.5 h-4 w-4 shrink-0 text-faint-foreground transition-transform duration-200 {collapsed
95
95
  ? '-rotate-90'
96
96
  : ''}"
97
97
  />
@@ -100,14 +100,14 @@
100
100
  {#if description}
101
101
  <p
102
102
  id={descriptionId}
103
- class="pl-4 pr-11 pt-0.5 pb-3.5 text-xs leading-snug text-muted-foreground"
103
+ class="pl-4 pr-11 pt-0.5 pb-3 text-xs leading-snug text-muted-foreground"
104
104
  >
105
105
  {description}
106
106
  </p>
107
107
  {/if}
108
108
  <div class="content-wrapper" class:collapsed inert={collapsed}>
109
109
  <div class="content-inner">
110
- <div class="px-4 pt-1 pb-5">
110
+ <div class="px-4 pt-2 pb-5">
111
111
  {@render grid()}
112
112
  </div>
113
113
  </div>
@@ -152,7 +152,7 @@
152
152
  .schema-grid {
153
153
  display: grid;
154
154
  grid-template-columns: repeat(var(--schema-cols), minmax(0, 1fr));
155
- gap: 1rem var(--column-gap);
155
+ gap: 1.25rem var(--column-gap);
156
156
  align-items: start;
157
157
  }
158
158
 
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { HelpCircle } from '@lucide/svelte';
3
- import * as Dialog from '../primitives/dialog';
3
+ import * as Dialog from '../primitives/dialog/index.js';
4
4
 
5
5
  interface Props {
6
6
  /** The field's label: the dialog title and the button's accessible name. */
@@ -12,9 +12,9 @@
12
12
  ZoomIn,
13
13
  ZoomOut
14
14
  } from '@lucide/svelte';
15
- import { downloadFiles, isFileData, MIME_BY_EXT } from '../../utils/file-download';
16
- import { getLocaleContext } from '../../i18n/localeContext.svelte';
17
- import { formatMessage } from '../../i18n/messages';
15
+ import { downloadFiles, isFileData, MIME_BY_EXT } from '../../utils/file-download.js';
16
+ import { getLocaleContext } from '../../i18n/localeContext.svelte.js';
17
+ import { formatMessage } from '../../i18n/messages.js';
18
18
 
19
19
  interface Props {
20
20
  item: OutputImageLayoutItem;
@@ -65,7 +65,8 @@
65
65
  // Some embedded WebViews (WKWebView in the Rhino panel) ship without the Fullscreen API at all.
66
66
  const fullscreenSupported = typeof document !== 'undefined' && !!document.fullscreenEnabled;
67
67
  const allowFullscreen = $derived((cfg.allowFullscreen ?? true) && fullscreenSupported);
68
- const backgroundColor = $derived(cfg.backgroundColor);
68
+ // SVGs are line drawings (often black on transparent), so a checkerboard hurts legibility.
69
+ const backgroundColor = $derived(cfg.backgroundColor ?? (isSvg ? '#ffffff' : undefined));
69
70
 
70
71
  let wrapperEl = $state<HTMLDivElement | null>(null);
71
72
  let stageEl = $state<HTMLDivElement | null>(null);
@@ -296,14 +297,14 @@
296
297
  }
297
298
 
298
299
  const toolButton =
299
- 'flex h-7 min-w-7 items-center justify-center rounded px-1.5 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground disabled:pointer-events-none disabled:opacity-40';
300
+ 'flex h-7 min-w-7 items-center justify-center rounded-sm px-1.5 text-muted-foreground transition-colors hover:bg-hover hover:text-foreground disabled:pointer-events-none disabled:opacity-40';
300
301
  </script>
301
302
 
302
303
  <!-- The layout hides this output until a solve returns a file, so there is no empty state here. -->
303
304
  {#if error || unsupported || current}
304
305
  <div
305
306
  bind:this={wrapperEl}
306
- class="rounded flex flex-col overflow-hidden border border-border bg-background {isFullscreen
307
+ class="flex flex-col overflow-hidden rounded-lg border border-border-strong bg-background {isFullscreen
307
308
  ? 'h-dvh'
308
309
  : ''}"
309
310
  >
@@ -319,6 +320,7 @@
319
320
  {:else if current}
320
321
  <!-- The stage is a pan/zoom surface with its own keyboard shortcuts; no native element fits. -->
321
322
  <!-- svelte-ignore a11y_no_noninteractive_tabindex, a11y_no_noninteractive_element_interactions -->
323
+ <!-- eslint-disable shadcn/no-inline-styles -- backgroundColor is the author's per-output color, not a theme token -->
322
324
  <div
323
325
  bind:this={stageEl}
324
326
  role="application"
@@ -338,6 +340,7 @@
338
340
  ondblclick={onDoubleClick}
339
341
  onkeydown={onKeyDown}
340
342
  >
343
+ <!-- eslint-enable shadcn/no-inline-styles -->
341
344
  {#if decodeFailed}
342
345
  <div class="inset-0 text-sm absolute flex items-center justify-center text-destructive">
343
346
  {formatMessage(t.imageDecodeFailed, { file: `${current.fileName}${current.fileType}` })}
@@ -372,7 +375,7 @@
372
375
  onclick={() => step(-1)}
373
376
  title="{t.previousImage} (←)"
374
377
  aria-label={t.previousImage}
375
- class="left-2 p-1.5 backdrop-blur-sm absolute top-1/2 -translate-y-1/2 rounded-full border border-border bg-background/80 text-foreground hover:bg-background"
378
+ class="left-2 p-1.5 backdrop-blur-sm absolute top-1/2 -translate-y-1/2 rounded-full border border-border-strong bg-background/80 text-foreground hover:bg-background"
376
379
  >
377
380
  <ChevronLeft size={16} />
378
381
  </button>
@@ -380,14 +383,14 @@
380
383
  onclick={() => step(1)}
381
384
  title="{t.nextImage} (→)"
382
385
  aria-label={t.nextImage}
383
- class="right-2 p-1.5 backdrop-blur-sm absolute top-1/2 -translate-y-1/2 rounded-full border border-border bg-background/80 text-foreground hover:bg-background"
386
+ class="right-2 p-1.5 backdrop-blur-sm absolute top-1/2 -translate-y-1/2 rounded-full border border-border-strong bg-background/80 text-foreground hover:bg-background"
384
387
  >
385
388
  <ChevronRight size={16} />
386
389
  </button>
387
390
  {/if}
388
391
 
389
392
  <div
390
- class="px-2.5 py-1 text-xs bottom-2 rounded pointer-events-none absolute left-1/2 -translate-x-1/2 bg-foreground/80 text-background transition-opacity {showWheelHint
393
+ class="px-2.5 py-1 text-xs bottom-2 pointer-events-none absolute left-1/2 -translate-x-1/2 rounded-sm bg-foreground text-background transition-opacity {showWheelHint
391
394
  ? 'opacity-100'
392
395
  : 'opacity-0'}"
393
396
  >
@@ -401,7 +404,7 @@
401
404
  <button
402
405
  onclick={() => select(i)}
403
406
  title="{image.fileName}{image.fileType}"
404
- class="h-12 w-16 rounded shrink-0 overflow-hidden border-2 bg-muted transition-colors {i ===
407
+ class="h-12 w-16 shrink-0 overflow-hidden rounded-sm border-2 bg-muted transition-colors {i ===
405
408
  currentIndex
406
409
  ? 'border-primary'
407
410
  : 'border-transparent opacity-70 hover:opacity-100'}"
@@ -16,9 +16,9 @@
16
16
  isFileWidget,
17
17
  isColorWidget
18
18
  } from '@selvajs/schemas';
19
- import * as Field from '../primitives/field';
20
- import { Button } from '../primitives/button';
21
- import { toast } from '../primitives/sonner';
19
+ import * as Field from '../primitives/field/index.js';
20
+ import { Button } from '../primitives/button/index.js';
21
+ import { toast } from '../primitives/sonner/index.js';
22
22
  import HelpButton from './HelpButton.svelte';
23
23
  import {
24
24
  CheckboxInput,
@@ -31,16 +31,16 @@
31
31
  SegmentedInput,
32
32
  TextInput,
33
33
  TileInput
34
- } from './inputs';
35
- import { getClientSlot } from '../../contexts/clientSlotContext.svelte';
34
+ } from './inputs/index.js';
35
+ import { getClientSlot } from '../../contexts/clientSlotContext.svelte.js';
36
36
  import {
37
37
  getHostContext,
38
38
  type GeometryPickTarget,
39
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';
40
+ } from '../../contexts/hostContext.svelte.js';
41
+ import { getLocaleContext } from '../../i18n/localeContext.svelte.js';
42
+ import { isGeometryParamType, isTriggerItem } from '../../schema/host-support.js';
43
+ import { resolveOptionDisplay } from '../../schema/option-display.js';
44
44
 
45
45
  interface Props {
46
46
  item: InputLayoutItem;
@@ -283,7 +283,7 @@
283
283
 
284
284
  {#if isClientSlot}
285
285
  {#if clientSlot}
286
- <div role="group" class="group/field gap-1.5 min-w-0 flex flex-col">
286
+ <div role="group" class="group/field gap-2 min-w-0 flex flex-col">
287
287
  {@render fieldHeader()}
288
288
  {@render clientSlot({
289
289
  inputId: item.paramId,
@@ -294,7 +294,7 @@
294
294
  </div>
295
295
  {/if}
296
296
  {:else if isGeometry}
297
- <div role="group" class="group/field gap-1.5 min-w-0 flex flex-col">
297
+ <div role="group" class="group/field gap-2 min-w-0 flex flex-col">
298
298
  {@render fieldHeader(inputId)}
299
299
  <GeometryInput
300
300
  {inputId}
@@ -322,7 +322,7 @@
322
322
  {@render helpButton()}
323
323
  </div>
324
324
  {:else if !hideDynamicListWhenEmpty}
325
- <div role="group" class="group/field gap-1.5 min-w-0 flex flex-col">
325
+ <div role="group" class="group/field gap-2 min-w-0 flex flex-col">
326
326
  {#if !isCheckboxWidget(item)}
327
327
  {@render fieldHeader(inputId)}
328
328
  {/if}
@@ -378,6 +378,7 @@
378
378
  {inputId}
379
379
  value={typeof value === 'string' ? value : '#000000'}
380
380
  onChange={(newValue) => commit(newValue)}
381
+ {disabled}
381
382
  />
382
383
  {/if}
383
384
  </div>
@@ -8,14 +8,14 @@
8
8
  formatFileSize,
9
9
  getBase64FileSize,
10
10
  isFileData
11
- } from '../../utils/file-download';
11
+ } from '../../utils/file-download.js';
12
12
  import { Button } from '../primitives';
13
13
  import { Folder, FolderOpen, FileIcon, ChevronRight } from '@lucide/svelte';
14
14
  import HelpButton from './HelpButton.svelte';
15
15
  import { SvelteMap, SvelteSet } from 'svelte/reactivity';
16
- import { Label } from '../primitives/label';
17
- import { getLocaleContext } from '../../i18n/localeContext.svelte';
18
- import { formatCount, formatMessage } from '../../i18n/messages';
16
+ import { Label } from '../primitives/label/index.js';
17
+ import { getLocaleContext } from '../../i18n/localeContext.svelte.js';
18
+ import { formatCount, formatMessage } from '../../i18n/messages.js';
19
19
 
20
20
  interface Props {
21
21
  item: OutputLayoutItem;
@@ -38,7 +38,7 @@
38
38
  );
39
39
  const hasValue = $derived(value != null);
40
40
 
41
- const boxClass = 'min-h-12.5 rounded px-3 py-3 font-mono text-sm border border-border';
41
+ const boxClass = 'min-h-12.5 rounded-md px-3 py-3 text-sm border border-border-strong';
42
42
 
43
43
  async function copyToClipboard() {
44
44
  try {
@@ -157,7 +157,11 @@
157
157
 
158
158
  {#snippet fieldHeader()}
159
159
  <div class="gap-2 flex items-center">
160
- <Label>{label}</Label>
160
+ <Label>
161
+ <span class={item.widgetType === 'number' ? 'text-xs font-normal text-muted-foreground' : ''}
162
+ >{label}</span
163
+ >
164
+ </Label>
161
165
  {#if item.description}
162
166
  <HelpButton {label} description={item.description} />
163
167
  {/if}
@@ -190,7 +194,7 @@
190
194
  <span class="font-medium">{node.name}</span>
191
195
  </button>
192
196
  {#if isOpen}
193
- <div class="ml-4 pl-2 border-l border-border/50">
197
+ <div class="ml-4 pl-2 border-l border-border-strong">
194
198
  {@render treeNodes(node.children, folderPath)}
195
199
  </div>
196
200
  {/if}
@@ -213,12 +217,14 @@
213
217
 
214
218
  {#snippet fileDisplay()}
215
219
  {#if fileCount === 0}
216
- <div class="rounded px-3 py-3 text-sm border border-border bg-muted text-muted-foreground">
220
+ <div
221
+ class="px-3 py-3 text-sm rounded-md border border-border-strong bg-muted text-muted-foreground"
222
+ >
217
223
  {t.waitingForFiles}
218
224
  </div>
219
225
  {:else}
220
226
  <div class="gap-2 flex flex-col">
221
- <div class="rounded px-3 py-2 border border-border bg-muted">
227
+ <div class="px-3 py-2 rounded-md border border-border-strong bg-muted">
222
228
  <div class="gap-2 flex items-center justify-between">
223
229
  <span class="min-w-0 text-sm font-medium truncate text-foreground">
224
230
  {fileCount === 1
@@ -248,7 +254,7 @@
248
254
  </div>
249
255
  {#if hasDuplicates}
250
256
  <div
251
- class="rounded px-3 py-2 text-sm border border-destructive bg-destructive/10 text-destructive"
257
+ class="px-3 py-2 text-sm rounded-md border border-destructive bg-destructive/10 text-destructive"
252
258
  >
253
259
  <div class="font-medium">{t.duplicateFilesTitle}</div>
254
260
  <div class="mt-1 text-xs">
@@ -264,7 +270,7 @@
264
270
  {/if}
265
271
  {#if downloadError}
266
272
  <div
267
- class="rounded px-3 py-2 text-sm border border-destructive bg-destructive/10 text-destructive"
273
+ class="px-3 py-2 text-sm rounded-md border border-destructive bg-destructive/10 text-destructive"
268
274
  >
269
275
  {downloadError}
270
276
  </div>
@@ -282,7 +288,10 @@
282
288
 
283
289
  <!-- Dynamic value list outputs are routing sinks (their options feed an input), not displayed. -->
284
290
  {#if item.widgetType !== 'dynamicValueList'}
285
- <div role="group" class="group/field gap-2 flex flex-col">
291
+ <div
292
+ role="group"
293
+ class="group/field flex flex-col {item.widgetType === 'number' ? 'gap-0.5' : 'gap-2'}"
294
+ >
286
295
  {@render fieldHeader()}
287
296
 
288
297
  {#if item.widgetType === 'chart'}
@@ -295,21 +304,21 @@
295
304
  {:else if item.widgetType === 'file'}
296
305
  {@render fileDisplay()}
297
306
  {:else if item.widgetType === 'number'}
298
- <div class="{boxClass} flex items-center bg-muted/50 wrap-break-word">
307
+ <div class="min-h-8 text-2xl font-semibold wrap-break-word text-foreground tabular-nums">
299
308
  {#if hasValue}
300
- <span class="font-bold text-primary">{formattedValue}</span>
309
+ {formattedValue}
301
310
  {:else}
302
- {@render placeholder()}
311
+ <span class="text-base font-normal">{@render placeholder()}</span>
303
312
  {/if}
304
313
  </div>
305
314
  {:else if item.widgetType === 'text'}
306
315
  <div class="group relative">
307
316
  {#if isObjectValue}
308
317
  <pre
309
- class="{boxClass} max-h-96 overflow-auto bg-muted/10 wrap-anywhere text-foreground">{formattedValue}</pre>
318
+ class="{boxClass} max-h-96 font-mono overflow-auto bg-muted wrap-anywhere text-foreground">{formattedValue}</pre>
310
319
  {:else}
311
320
  <div
312
- class="{boxClass} bg-muted/10 wrap-anywhere wrap-break-word whitespace-pre-wrap text-foreground"
321
+ class="{boxClass} bg-muted wrap-anywhere wrap-break-word whitespace-pre-wrap text-foreground"
313
322
  >
314
323
  {#if hasValue}{value}{:else}{@render placeholder()}{/if}
315
324
  </div>