@selvajs/ui 6.6.0-beta.9 → 7.0.1-beta.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 +230 -85
  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 +9 -6
  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 +452 -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 +100 -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 +231 -86
  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 +9 -6
  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 +452 -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 +100 -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
@@ -16,10 +16,11 @@
16
16
  import { LoaderCircle } from '@lucide/svelte';
17
17
  import type { SolveDiagnostic } from '@selvajs/solve/shared';
18
18
  import type { LiveSolveState, SolvePhase } from '@selvajs/solve/client';
19
- import { Button } from '$lib/components/primitives/button';
20
- import IssueList, { type Issue } from '$lib/components/primitives/IssueList.svelte';
21
- import SeverityIcon from '$lib/components/primitives/SeverityIcon.svelte';
22
- import { getLocaleContext } from '$lib/i18n/localeContext.svelte';
19
+ import { Button } from '#lib/components/primitives/button/index.js';
20
+ import IssueList, { type Issue } from '#lib/components/primitives/IssueList.svelte';
21
+ import SeverityIcon from '#lib/components/primitives/SeverityIcon.svelte';
22
+ import { getLocaleContext } from '#lib/i18n/localeContext.svelte.js';
23
+ import { createLiveProgress } from '#lib/compute/liveProgress.svelte.js';
23
24
 
24
25
  interface Props {
25
26
  /** What the running (or most recent) solve has said over the live channel. */
@@ -38,6 +39,11 @@
38
39
  freezesDuringSolve?: boolean;
39
40
  /** `floating` overlays the bottom centre; `inline` sits in the flow below the host's content. */
40
41
  placement?: 'floating' | 'inline';
42
+ /**
43
+ * The host shows progress and Abort itself (`AppLayout`'s solve status), so the live view
44
+ * keeps only the messages that arrive mid-solve.
45
+ */
46
+ progressShownByHost?: boolean;
41
47
  }
42
48
 
43
49
  let {
@@ -48,7 +54,8 @@
48
54
  onconfirm,
49
55
  ondiscard,
50
56
  freezesDuringSolve = false,
51
- placement = 'floating'
57
+ placement = 'floating',
58
+ progressShownByHost = false
52
59
  }: Props = $props();
53
60
 
54
61
  const locale = getLocaleContext();
@@ -56,50 +63,10 @@
56
63
 
57
64
  const REMARK_LINGER_MS = 6000;
58
65
 
59
- const progress = $derived([...live.progress.values()]);
60
-
61
- // A report only arrives when a step starts, so a bar that just shows `fraction` stands still
62
- // through the step and then jumps. When the plugin knows how long the step took last time, the
63
- // bar runs linearly to where the step will end, over that time. Steps are weighted by time, so
64
- // linear gives one steady speed across the solve; any easing curve visibly speeds up and
65
- // crawls within each step. A slower run waits at the step's end; a faster one snaps ahead.
66
- let bars = $state.raw<Record<string, { width: number; ms: number }>>({});
67
- // Any live event re-runs the effect below. Only a source with a new report may re-snap;
68
- // the rest keep easing where they are.
69
- let seen = new Map<string, unknown>();
70
- let targets: Record<string, { width: number; ms: number }> = {};
71
- $effect(() => {
72
- const snapped: Record<string, { width: number; ms: number }> = {};
73
- const eased: Record<string, { width: number; ms: number }> = {};
74
- const current = untrack(() => bars);
75
- // eslint-disable-next-line svelte/prefer-svelte-reactivity -- bookkeeping for this effect; reactive reads here would re-trigger it
76
- const nextSeen = new Map<string, unknown>();
77
- for (const p of progress) {
78
- if (p.fraction === undefined) continue;
79
- const key = p.source ?? '';
80
- nextSeen.set(key, p);
81
- if (seen.get(key) === p && current[key]) {
82
- snapped[key] = current[key];
83
- // This run's cleanup cancelled the frame that would have started the ease.
84
- if (targets[key] && current[key] !== targets[key]) eased[key] = targets[key];
85
- continue;
86
- }
87
- snapped[key] = { width: p.fraction, ms: 150 };
88
- if (p.nextFraction !== undefined && p.stepMs !== undefined) {
89
- eased[key] = { width: p.nextFraction, ms: p.stepMs };
90
- }
91
- }
92
- seen = nextSeen;
93
- targets = eased;
94
- bars = snapped;
95
- if (Object.keys(eased).length === 0) return;
96
- // Two frames: the snapped width must be painted before the eased one is set, or the
97
- // browser folds both into one style change and there is nothing to transition from.
98
- let frame = requestAnimationFrame(() => {
99
- frame = requestAnimationFrame(() => (bars = { ...snapped, ...eased }));
100
- });
101
- return () => cancelAnimationFrame(frame);
102
- });
66
+ const liveProgress = createLiveProgress(() => live);
67
+ const progress = $derived(liveProgress.progress);
68
+ const bars = $derived(liveProgress.bars);
69
+ const headline = $derived(liveProgress.headline);
103
70
  // Grasshopper's own complaints stay in the footer log; this panel shows what the author wrote.
104
71
  const authored = $derived(diagnostics.filter((d) => d.isGate));
105
72
 
@@ -126,16 +93,30 @@
126
93
  // Keyed on the diagnostics array's identity, which every report renews, rather than on a
127
94
  // solve id: only the live channel has one, and on the Compute path remarks arrive with the
128
95
  // result. Once per array, so remarks that sat behind a review do not reappear after Continue.
96
+ //
97
+ // A remark is shown once while it stays raised, not after every solve. Every report repeats
98
+ // it: Grasshopper keeps runtime messages on a Message component an input change did not
99
+ // reach, and Compute re-solves the whole definition. It shows again once a solve stops
100
+ // raising it and a later one raises it anew.
129
101
  let lingering = $state(false);
130
102
  let lingeredFor: SolveDiagnostic[] | null = null;
103
+ let shownRemarks: ReadonlySet<string> = new Set();
104
+ let freshRemarks = $state.raw<SolveDiagnostic[]>([]);
105
+ const remarkKey = (d: SolveDiagnostic) => `${d.source ?? ''}\u0000${d.message}`;
131
106
  $effect(() => {
132
107
  if (phase === 'live') {
133
108
  lingering = false;
134
109
  return;
135
110
  }
136
- if (authoredRemarks.length === 0 || lingeredFor === diagnostics) return;
111
+ if (lingeredFor === diagnostics) return;
137
112
  lingeredFor = diagnostics;
138
- if (phase !== 'idle') return;
113
+ const raised = authoredRemarks.map(remarkKey);
114
+ const stillShown = raised.filter((k) => shownRemarks.has(k));
115
+ const fresh = authoredRemarks.filter((d) => !shownRemarks.has(remarkKey(d)));
116
+ const showNow = phase === 'idle' && fresh.length > 0;
117
+ shownRemarks = new Set(showNow ? [...stillShown, ...fresh.map(remarkKey)] : stillShown);
118
+ if (!showNow) return;
119
+ freshRemarks = fresh;
139
120
  lingering = true;
140
121
  const timer = setTimeout(() => (lingering = false), REMARK_LINGER_MS);
141
122
  return () => clearTimeout(timer);
@@ -181,7 +162,7 @@
181
162
  // While solving, the live channel is all there is. Once the result lands it is authoritative
182
163
  // — it carries remarks too — so the live list is dropped entirely and nothing is shown twice.
183
164
  const rows = $derived<SolveDiagnostic[]>(
184
- view === 'live' ? [...live.diagnostics] : view === 'idle' ? authoredRemarks : authoredGating
165
+ view === 'live' ? [...live.diagnostics] : view === 'idle' ? freshRemarks : authoredGating
185
166
  );
186
167
 
187
168
  // A remark states something without asking anything, so it reads as a quiet note.
@@ -193,37 +174,11 @@
193
174
  }))
194
175
  );
195
176
 
196
- // Steps a few milliseconds long would swap the headline faster than it can be read. Each one
197
- // stays up for at least this long; steps that end sooner are skipped in the label but still
198
- // count in the bar. The label and its step count move together so they never disagree.
199
- const HEADLINE_MIN_MS = 200;
200
- let headline = $state.raw<(typeof progress)[number] | undefined>(undefined);
201
- let headlineAt = 0;
202
- $effect(() => {
203
- const next = progress[0];
204
- const shown = untrack(() => headline);
205
- if (next?.label === shown?.label && next?.done === shown?.done) {
206
- headline = next;
207
- return;
208
- }
209
- const show = () => {
210
- headline = next;
211
- headlineAt = performance.now();
212
- };
213
- const wait = HEADLINE_MIN_MS - (performance.now() - headlineAt);
214
- if (!shown || wait <= 0) {
215
- show();
216
- return;
217
- }
218
- const timer = setTimeout(show, wait);
219
- return () => clearTimeout(timer);
220
- });
221
-
222
177
  const visible = $derived(
223
178
  view === 'review' || view === 'blocked'
224
179
  ? true
225
180
  : view === 'live'
226
- ? revealed && (rows.length > 0 || progress.length > 0)
181
+ ? revealed && (rows.length > 0 || (!progressShownByHost && progress.length > 0))
227
182
  : rows.length > 0 && lingering
228
183
  );
229
184
 
@@ -245,10 +200,14 @@
245
200
  }
246
201
 
247
202
  // Escape resolves to the safe side — discard, keeping what is on screen — never to silently
248
- // applying a result the user has not accepted.
203
+ // applying a result the user has not accepted. A frozen host gets no keydown until the solve
204
+ // ends; there the plugin aborts on the key state, which only counts while Rhino is in front, so
205
+ // a browser tab (local or Compute) has to abort from the page.
249
206
  function handleKeydown(e: KeyboardEvent) {
250
207
  if (e.key !== 'Escape') return;
251
- if (phase === 'review') ondiscard();
208
+ if (phase === 'live') {
209
+ if (!freezesDuringSolve) onabort();
210
+ } else if (phase === 'review') ondiscard();
252
211
  else if (phase === 'blocked') dismiss();
253
212
  }
254
213
  </script>
@@ -269,18 +228,17 @@
269
228
  </p>
270
229
  {/if}
271
230
  {:else if visible}
231
+ <!-- Inline, it is a row of the host's footer like the Calculate row under it, not a card: a
232
+ framed box inside an edge-to-edge column reads as a dialog glued into the page. -->
272
233
  <div
273
- class="p-3 border {placement === 'inline'
274
- ? 'mt-3 rounded-md bg-muted/40'
275
- : 'bottom-4 shadow-lg w-lg fixed left-1/2 z-50 max-w-screen-inset -translate-x-1/2 rounded-lg bg-background'} {view ===
276
- 'blocked'
277
- ? 'border-destructive/50'
278
- : ''}"
234
+ class={placement === 'inline'
235
+ ? `px-2 py-2 border-t ${view === 'blocked' ? 'border-destructive/40' : 'border-border'}`
236
+ : `p-3 bottom-4 shadow-lg w-lg fixed left-1/2 z-50 max-w-screen-inset -translate-x-1/2 rounded-lg border bg-background ${view === 'blocked' ? 'border-destructive/50' : ''}`}
279
237
  role={view === 'review' || view === 'blocked' ? 'alert' : undefined}
280
238
  data-testid="solve-messages"
281
239
  data-view={view}
282
240
  >
283
- {#if view === 'live'}
241
+ {#if view === 'live' && !progressShownByHost}
284
242
  {@const head = headline ?? progress[0]}
285
243
  <div>
286
244
  <div>
@@ -298,8 +256,13 @@
298
256
  class="-my-1 shrink-0"
299
257
  disabled={finishing}
300
258
  onclick={onabort}
259
+ aria-keyshortcuts="Escape"
260
+ title={t.solveMessagesEscHint}
301
261
  >
302
262
  {t.solveMessagesAbort}
263
+ <kbd class="px-1 rounded-sm border border-border font-sans text-2xs opacity-70">
264
+ Esc
265
+ </kbd>
303
266
  </Button>
304
267
  </div>
305
268
  {#each progress as p, i (p.source ?? '')}
@@ -338,6 +301,30 @@
338
301
  {/each}
339
302
  </div>
340
303
  </div>
304
+ {:else if (view === 'review' || view === 'blocked') && placement === 'inline'}
305
+ <!-- Each message carries its own icon, so the label goes without one; the buttons share
306
+ its row rather than adding one under a single line of text. -->
307
+ <div class="mb-1.5 gap-2 flex items-center">
308
+ <span
309
+ class="min-w-0 text-xs font-medium flex-1 truncate {view === 'blocked'
310
+ ? 'text-destructive'
311
+ : 'text-muted-foreground'}"
312
+ >
313
+ {view === 'blocked' ? t.solveBlockedTitle : t.solveMessagesTitle}
314
+ </span>
315
+ {#if view === 'blocked'}
316
+ <Button variant="ghost" size="xs" class="-my-1 shrink-0" onclick={dismiss}>
317
+ {t.solveMessagesDismiss}
318
+ </Button>
319
+ {:else}
320
+ <Button variant="ghost" size="xs" class="-my-1 shrink-0" onclick={ondiscard}>
321
+ {t.solveMessagesDiscard}
322
+ </Button>
323
+ <Button size="xs" class="-my-1 shrink-0" onclick={onconfirm}>
324
+ {t.solveMessagesConfirm}
325
+ </Button>
326
+ {/if}
327
+ </div>
341
328
  {:else if view === 'review' || view === 'blocked'}
342
329
  <div class="mb-2">
343
330
  <div class="gap-2 text-sm font-medium flex items-center">
@@ -356,12 +343,16 @@
356
343
  {/if}
357
344
 
358
345
  {#if rows.length > 0}
359
- <div class="max-h-40 overflow-y-auto {view === 'live' ? 'mt-3 pt-3 border-t' : ''}">
346
+ <div
347
+ class="max-h-40 overflow-y-auto {view === 'live' && !progressShownByHost
348
+ ? 'mt-3 pt-3 border-t'
349
+ : ''}"
350
+ >
360
351
  <IssueList {issues} variant="plain" />
361
352
  </div>
362
353
  {/if}
363
354
 
364
- {#if view === 'review' || view === 'blocked'}
355
+ {#if (view === 'review' || view === 'blocked') && placement === 'floating'}
365
356
  <div class="mt-3 gap-2 flex justify-end">
366
357
  {#if view === 'blocked'}
367
358
  <Button variant="outline" size="sm" onclick={dismiss}>{t.solveMessagesDismiss}</Button>
@@ -94,14 +94,14 @@
94
94
  const sidenavWrapClass = $derived(
95
95
  _mode === 'fixed'
96
96
  ? 'flex shrink-0'
97
- : 'flex shrink-0 sm:self-start sm:sticky sm:top-(--header-h) sm:max-h-[calc(100svh-var(--header-h))]'
97
+ : 'flex shrink-0 sm:self-start sm:sticky sm:top-(--header-h) sm:max-h-(--below-header-h)'
98
98
  );
99
99
 
100
100
  // The sticky wrapper is only as tall as its content, so in scroll mode the divider comes
101
101
  // from the main column's left edge — that one spans the full body height.
102
102
  const mainClass = $derived(
103
103
  _mode === 'fixed'
104
- ? 'min-h-0 flex-1 overflow-y-auto'
104
+ ? 'min-h-0 min-w-0 flex-1 overflow-y-auto'
105
105
  : 'min-w-0 flex-1 overflow-y-auto border-border sm:border-l'
106
106
  );
107
107
  </script>
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import type { FooterItem } from '$lib/contexts/footerContext.svelte';
2
+ import type { FooterItem } from '#lib/contexts/footerContext.svelte.js';
3
3
 
4
4
  let { item }: { item: FooterItem } = $props();
5
5
 
@@ -9,7 +9,7 @@
9
9
  {#if item.onClick}
10
10
  <button
11
11
  onclick={item.onClick}
12
- class="gap-1.5 px-2 py-0.5 rounded flex cursor-pointer items-center transition-colors hover:bg-muted"
12
+ class="gap-1.5 px-2 py-0.5 flex cursor-pointer items-center rounded-sm transition-colors hover:bg-hover"
13
13
  >
14
14
  <item.component {...itemProps} />
15
15
  </button>
@@ -7,6 +7,7 @@
7
7
  let { class: className = '', children }: PageContentProps = $props();
8
8
  </script>
9
9
 
10
- <main class={`px-(--page-px) py-(--page-py) ${className}`}>
10
+ <!-- One content width for every page, so moving between pages doesn't change the frame. -->
11
+ <div class={`max-w-6xl min-w-0 mx-auto w-full px-(--page-px) py-(--page-py) ${className}`}>
11
12
  {@render children?.()}
12
- </main>
13
+ </div>
@@ -2,11 +2,11 @@
2
2
  import type { Snippet } from 'svelte';
3
3
  import { CircleAlert, TriangleAlert, Info } from '@lucide/svelte';
4
4
  import type { SolveDiagnostic } from '@selvajs/solve/shared';
5
- import { useFooter } from '$lib/contexts/footerContext.svelte';
5
+ import { useFooter } from '#lib/contexts/footerContext.svelte.js';
6
6
  import ComputeMessagesDialog from '../compute/ComputeMessagesDialog.svelte';
7
7
  import FooterItemRenderer from './FooterItemRenderer.svelte';
8
- import { getLocaleContext } from '$lib/i18n/localeContext.svelte';
9
- import { formatCount, formatMessage } from '$lib/i18n/messages';
8
+ import { getLocaleContext } from '#lib/i18n/localeContext.svelte.js';
9
+ import { formatCount, formatMessage } from '#lib/i18n/messages.js';
10
10
 
11
11
  interface Props {
12
12
  errors?: string[];
@@ -88,12 +88,12 @@
88
88
  <ComputeMessagesDialog {errors} {warnings} {diagnostics}>
89
89
  {#snippet trigger()}
90
90
  <div
91
- class="gap-1.5 px-2 py-1 rounded flex cursor-pointer items-center transition-colors hover:bg-muted {errorCount >
91
+ class="gap-1.5 px-2 py-1 flex cursor-pointer items-center rounded-sm transition-colors hover:bg-hover {errorCount >
92
92
  0
93
93
  ? 'text-destructive hover:bg-destructive/10'
94
94
  : warningCount > 0
95
95
  ? 'text-warning hover:bg-warning/10'
96
- : 'hover:bg-muted'}"
96
+ : 'hover:bg-hover'}"
97
97
  title={formatCount(totalCount, t.lastSolveMessagesOne, t.lastSolveMessagesOther)}
98
98
  >
99
99
  {#if errorCount > 0}
@@ -137,7 +137,10 @@
137
137
  {/each}
138
138
 
139
139
  {#if copyrightLine}
140
- <p class="truncate">{copyrightLine}</p>
140
+ <!-- On a phone, upright or on its side, the row is for status and messages. -->
141
+ <p class="max-sm:hidden truncate [@media(pointer:coarse)_and_(max-height:500px)]:hidden">
142
+ {copyrightLine}
143
+ </p>
141
144
  {/if}
142
145
  </div>
143
146
  </footer>
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
- import { ModeToggle } from '$lib/components/primitives/mode-toggle';
3
+ import { ModeToggle } from '#lib/components/primitives/mode-toggle/index.js';
4
4
 
5
5
  interface PageHeaderProps {
6
6
  homeUrl?: string;
@@ -34,7 +34,7 @@
34
34
  <div class="gap-2 sm:gap-5 flex h-(--header-h) items-center px-(--page-px)">
35
35
  <!-- Logo -->
36
36
  <a href={homeUrl} class="gap-2 flex shrink-0 items-center" aria-label={brandName}>
37
- <img src={logo} alt="" aria-hidden="true" class="h-5 w-5" />
37
+ <img src={logo} alt="" aria-hidden="true" class="h-7 w-7" />
38
38
  <!-- On a phone the page title needs the room more than the brand does. -->
39
39
  <span
40
40
  class="font-semibold text-sm tracking-tight {title !== undefined ? 'sm:inline hidden' : ''}"
@@ -66,7 +66,7 @@
66
66
  </div>
67
67
 
68
68
  {#if subnav}
69
- <div class="h-10 flex items-center border-t border-border/60 px-(--page-px)">
69
+ <div class="h-10 flex items-center border-t border-border px-(--page-px)">
70
70
  {@render subnav()}
71
71
  </div>
72
72
  {/if}
@@ -15,7 +15,7 @@
15
15
  import { page } from '$app/state';
16
16
  import ChevronsUpDown from '@lucide/svelte/icons/chevrons-up-down';
17
17
  import Check from '@lucide/svelte/icons/check';
18
- import * as DropdownMenu from '$lib/components/primitives/dropdown-menu/index.js';
18
+ import * as DropdownMenu from '#lib/components/primitives/dropdown-menu/index.js';
19
19
 
20
20
  interface SideNavProps {
21
21
  items: SideNavItem[];
@@ -119,8 +119,8 @@
119
119
  aria-current={active ? 'page' : undefined}
120
120
  class={`group gap-2 py-1.5 pr-2.5 relative flex w-full items-center text-left transition-colors ${
121
121
  active
122
- ? 'pl-4 rounded-r-md bg-accent text-accent-foreground'
123
- : 'mx-2 pl-2.5 rounded-md text-muted-foreground hover:bg-muted/60 hover:text-foreground'
122
+ ? 'pl-4 rounded-r-md bg-selected text-foreground'
123
+ : 'mx-2 pl-2.5 rounded-md text-muted-foreground hover:bg-hover hover:text-foreground'
124
124
  }`}
125
125
  >
126
126
  {#if active}
@@ -138,7 +138,7 @@
138
138
  </nav>
139
139
 
140
140
  {#if footer}
141
- <div class="px-3 py-3 sm:block hidden border-t border-border/60">
141
+ <div class="px-3 py-3 sm:block hidden border-t border-border">
142
142
  {@render footer()}
143
143
  </div>
144
144
  {/if}
@@ -31,8 +31,8 @@
31
31
  class={[
32
32
  'h-7 px-3 gap-1.5 text-sm font-medium flex items-center rounded-md transition-colors',
33
33
  active
34
- ? 'bg-accent text-accent-foreground'
35
- : 'text-muted-foreground hover:bg-accent/50 hover:text-foreground'
34
+ ? 'bg-selected text-foreground'
35
+ : 'text-muted-foreground hover:bg-hover hover:text-foreground'
36
36
  ].join(' ')}
37
37
  >
38
38
  {#if item.icon}