@morscherlab/mint-sdk 1.4.0-beta.2 → 1.4.0-beta.21

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 (353) hide show
  1. package/README.md +14 -3
  2. package/dist/{ActionMenu-CScINahU.js → AlertBox-DwgNTEqf.js} +40 -209
  3. package/dist/AlertBox-DwgNTEqf.js.map +1 -0
  4. package/dist/{AppSidebar-BmiiPfz9.js → AppSidebar-CZZaxni0.js} +1249 -239
  5. package/dist/AppSidebar-CZZaxni0.js.map +1 -0
  6. package/dist/{ConfirmDialog-CJ7hqYUP.js → ConfirmDialog-CjWoxAD1.js} +2 -2
  7. package/dist/{ConfirmDialog-CJ7hqYUP.js.map → ConfirmDialog-CjWoxAD1.js.map} +1 -1
  8. package/dist/ExperimentPopover-DujiuQIO.js +337 -0
  9. package/dist/ExperimentPopover-DujiuQIO.js.map +1 -0
  10. package/dist/{ExperimentSelectorModal-D-9z7cNx.js → ExperimentSelectorModal-B4j4eUOJ.js} +244 -211
  11. package/dist/ExperimentSelectorModal-B4j4eUOJ.js.map +1 -0
  12. package/dist/{SegmentedControl-DERBN-Xd.js → SegmentedControl-DyUPH3I5.js} +2 -2
  13. package/dist/{SegmentedControl-DERBN-Xd.js.map → SegmentedControl-DyUPH3I5.js.map} +1 -1
  14. package/dist/{SettingsModal-CSLE31yg.js → SettingsModal-D2MOOtuO.js} +28 -27
  15. package/dist/SettingsModal-D2MOOtuO.js.map +1 -0
  16. package/dist/__stories__/experiment-helpers.d.ts +10 -0
  17. package/dist/__tests__/components/AppTopBarOnboarding.test.d.ts +1 -0
  18. package/dist/__tests__/components/FloatingPanelsInModal.test.d.ts +1 -0
  19. package/dist/__tests__/composables/useFloatingPanel.test.d.ts +1 -0
  20. package/dist/__tests__/composables/useOnboarding.test.d.ts +1 -0
  21. package/dist/__tests__/styles/paletteTokens.test.d.ts +1 -0
  22. package/dist/__tests__/styles/v2AuditRules.test.d.ts +1 -0
  23. package/dist/components/AppSidebar.vue.d.ts +1 -1
  24. package/dist/components/AppTopBar.vue.d.ts +20 -5
  25. package/dist/components/ArtifactSaveDialog.vue.d.ts +9 -1
  26. package/dist/components/AuditTrail.vue.d.ts +1 -1
  27. package/dist/components/BaseButton.vue.d.ts +4 -2
  28. package/dist/components/BaseSelect.vue.d.ts +2 -2
  29. package/dist/components/ChartContainer.vue.d.ts +2 -0
  30. package/dist/components/DatePicker.vue.d.ts +1 -1
  31. package/dist/components/ExperimentPopover.vue.d.ts +18 -0
  32. package/dist/components/ExperimentSelectorModal.vue.d.ts +15 -5
  33. package/dist/components/FilePicker.vue.d.ts +1 -1
  34. package/dist/components/FileUploader.vue.d.ts +2 -2
  35. package/dist/components/JobsStatusTray.vue.d.ts +15 -4
  36. package/dist/components/PluginIcon.vue.d.ts +2 -2
  37. package/dist/components/PluginWorkspaceView.props.d.ts +3 -0
  38. package/dist/components/PluginWorkspaceView.vue.d.ts +3 -0
  39. package/dist/components/SampleSelector.vue.d.ts +6 -6
  40. package/dist/components/SequenceProgressBar.vue.d.ts +3 -0
  41. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +3 -3
  42. package/dist/components/StepWizard.vue.d.ts +3 -0
  43. package/dist/components/internal/AppTopBarOnboardingInternal.vue.d.ts +7 -0
  44. package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -1
  45. package/dist/components/internal/AutoGroupModalInternal.vue.d.ts +3 -3
  46. package/dist/components/internal/DatePickerTimeInternal.vue.d.ts +1 -1
  47. package/dist/components/internal/OnboardingLayerInternal.vue.d.ts +7 -0
  48. package/dist/components/internal/ResourcePickerListInternal.vue.d.ts +2 -7
  49. package/dist/components/internal/SelectMultipleInternal.vue.d.ts +4 -0
  50. package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +8 -0
  51. package/dist/composables/createClient.d.ts +2 -0
  52. package/dist/composables/index.d.ts +1 -0
  53. package/dist/composables/pluginIdentity.d.ts +24 -0
  54. package/dist/composables/pluginWorkspaceModel.d.ts +2 -2
  55. package/dist/composables/useAppExperiment.d.ts +8 -0
  56. package/dist/composables/useCalendarGrid.d.ts +1 -1
  57. package/dist/composables/useExperimentSelector.d.ts +6 -2
  58. package/dist/composables/useFileImport.d.ts +7 -0
  59. package/dist/composables/useFloatingPanel.d.ts +29 -0
  60. package/dist/composables/useJobCenter.d.ts +41 -3
  61. package/dist/composables/useOnboarding.d.ts +119 -0
  62. package/dist/composables/usePlatform.d.ts +1 -0
  63. package/dist/{controlSchemaModel-CP5-_nAj.js → controlSchemaModel-Bsg0t5Ab.js} +2 -2
  64. package/dist/{controlSchemaModel-CP5-_nAj.js.map → controlSchemaModel-Bsg0t5Ab.js.map} +1 -1
  65. package/dist/{data-C2PwI_dn.js → data-Boeh4uPI.js} +180 -125
  66. package/dist/data-Boeh4uPI.js.map +1 -0
  67. package/dist/data.d.ts +1 -1
  68. package/dist/data.js +9 -9
  69. package/dist/{experiment-43OJtH7R.js → experiment-DyO54FQB.js} +25 -61
  70. package/dist/experiment-DyO54FQB.js.map +1 -0
  71. package/dist/{experimentStatus-BZmU4czV.js → experimentStatus-DCn2QKG7.js} +3 -3
  72. package/dist/{experimentStatus-BZmU4czV.js.map → experimentStatus-DCn2QKG7.js.map} +1 -1
  73. package/dist/index.js +20 -20
  74. package/dist/{install-DAID6c2-.js → install-BEHp7Mo-.js} +15 -14
  75. package/dist/{install-DAID6c2-.js.map → install-BEHp7Mo-.js.map} +1 -1
  76. package/dist/install.js +1 -1
  77. package/dist/{lab-DLwRl_Ql.js → lab-D61eaX6f.js} +136 -148
  78. package/dist/lab-D61eaX6f.js.map +1 -0
  79. package/dist/lab.js +4 -3
  80. package/dist/{records-BzTcxekG.js → records-D4aQXyZu.js} +647 -389
  81. package/dist/records-D4aQXyZu.js.map +1 -0
  82. package/dist/{runtime-D6gVat6r.js → runtime-q-R0CNLh.js} +417 -54
  83. package/dist/runtime-q-R0CNLh.js.map +1 -0
  84. package/dist/runtime.d.ts +1 -1
  85. package/dist/runtime.js +7 -7
  86. package/dist/{shell-5ju97nOS.js → shell-6CGFvUUw.js} +10 -5
  87. package/dist/{shell-5ju97nOS.js.map → shell-6CGFvUUw.js.map} +1 -1
  88. package/dist/shell.d.ts +1 -0
  89. package/dist/shell.js +6 -6
  90. package/dist/stores/index.d.ts +1 -1
  91. package/dist/stores/index.js +2 -2
  92. package/dist/stores/settings.d.ts +4 -12
  93. package/dist/styles.css +2753 -2101
  94. package/dist/types/componentWorkflowTypes.d.ts +2 -0
  95. package/dist/types/components.d.ts +2 -0
  96. package/dist/types/generated/platformContext.d.ts +1 -0
  97. package/dist/types/generated-ui.d.ts +4 -0
  98. package/dist/types/index.d.ts +1 -1
  99. package/dist/types/jobs.d.ts +9 -0
  100. package/dist/types/platform.d.ts +1 -1
  101. package/dist/{BaseModal-DfRIuVoj.js → useDropdownState-uFIz6Yv8.js} +75 -5
  102. package/dist/useDropdownState-uFIz6Yv8.js.map +1 -0
  103. package/dist/{useExperimentSamples-CxcnxZ8h.js → useExperimentSamples-QEFoq4tf.js} +48 -6
  104. package/dist/useExperimentSamples-QEFoq4tf.js.map +1 -0
  105. package/dist/{useListReorder-CcbEYxX-.js → useListReorder-DsuzwWGS.js} +219 -437
  106. package/dist/useListReorder-DsuzwWGS.js.map +1 -0
  107. package/dist/{useRackEditor-BD5NIo5s.js → useRackEditor-KpZ4iJ6o.js} +85 -81
  108. package/dist/useRackEditor-KpZ4iJ6o.js.map +1 -0
  109. package/dist/useRealtime-B58Lo-Tm.js +508 -0
  110. package/dist/useRealtime-B58Lo-Tm.js.map +1 -0
  111. package/dist/useRequest-BuDmW8Jc.js +215 -0
  112. package/dist/useRequest-BuDmW8Jc.js.map +1 -0
  113. package/dist/utils/time.d.ts +7 -0
  114. package/package.json +3 -2
  115. package/src/__stories__/experiment-helpers.ts +3 -3
  116. package/src/__tests__/components/ActionMenu.test.ts +2 -2
  117. package/src/__tests__/components/AppTopBar.test.ts +257 -3
  118. package/src/__tests__/components/AppTopBarOnboarding.test.ts +160 -0
  119. package/src/__tests__/components/AppTopBarPageSelector.test.ts +125 -9
  120. package/src/__tests__/components/AppTopBarPillNav.test.ts +35 -0
  121. package/src/__tests__/components/ArtifactSaveDialog.test.ts +78 -0
  122. package/src/__tests__/components/BaseButton.test.ts +19 -0
  123. package/src/__tests__/components/BaseModal.test.ts +13 -0
  124. package/src/__tests__/components/BaseSelect.multiple.test.ts +87 -32
  125. package/src/__tests__/components/BaseSelect.test.ts +2 -1
  126. package/src/__tests__/components/BatchProgressList.test.ts +16 -0
  127. package/src/__tests__/components/CalendarGridPanel.test.ts +2 -2
  128. package/src/__tests__/components/ChartContainer.test.ts +11 -0
  129. package/src/__tests__/components/ChemicalFormula.test.ts +6 -3
  130. package/src/__tests__/components/DatePicker.datetime.test.ts +6 -0
  131. package/src/__tests__/components/DatePicker.test.ts +21 -0
  132. package/src/__tests__/components/DatePicker.time.test.ts +2 -2
  133. package/src/__tests__/components/EmptyState.test.ts +1 -1
  134. package/src/__tests__/components/ExperimentPopover.test.ts +125 -16
  135. package/src/__tests__/components/ExperimentSelectorModal.test.ts +153 -14
  136. package/src/__tests__/components/FloatingPanelsInModal.test.ts +94 -0
  137. package/src/__tests__/components/GeneratedPluginView.test.ts +23 -2
  138. package/src/__tests__/components/InstrumentStateBadge.test.ts +4 -4
  139. package/src/__tests__/components/JobsStatusTray.test.ts +373 -71
  140. package/src/__tests__/components/PluginWorkspaceView.test.ts +63 -1
  141. package/src/__tests__/components/ResourcePickerListInternal.test.ts +0 -20
  142. package/src/__tests__/components/SampleSelector.test.ts +33 -8
  143. package/src/__tests__/components/SequenceProgressBar.test.ts +12 -0
  144. package/src/__tests__/components/SettingsModal.test.ts +9 -2
  145. package/src/__tests__/components/StepWizard.test.ts +11 -0
  146. package/src/__tests__/components/WellPlate.decoration.test.ts +11 -4
  147. package/src/__tests__/components/deprecationTags.test.ts +1 -1
  148. package/src/__tests__/composables/useAppExperiment.test.ts +27 -1
  149. package/src/__tests__/composables/useCalendarGrid.test.ts +4 -2
  150. package/src/__tests__/composables/useExperimentSelector.test.ts +111 -0
  151. package/src/__tests__/composables/useFileImport.test.ts +36 -0
  152. package/src/__tests__/composables/useFloatingPanel.test.ts +68 -0
  153. package/src/__tests__/composables/useJobCenter.test.ts +262 -3
  154. package/src/__tests__/composables/useOnboarding.test.ts +317 -0
  155. package/src/__tests__/docs/frontendDocsCatalog.test.ts +4 -3
  156. package/src/__tests__/fixtures/table-import/cells.xlsx +0 -0
  157. package/src/__tests__/fixtures/table-import/samples.xlsx +0 -0
  158. package/src/__tests__/stores/settings.test.ts +21 -21
  159. package/src/__tests__/styles/baseControlsRules.test.ts +6 -2
  160. package/src/__tests__/styles/controlRefreshRules.test.ts +0 -6
  161. package/src/__tests__/styles/cssTokens.test.ts +6 -3
  162. package/src/__tests__/styles/menusShellRefresh.test.ts +22 -12
  163. package/src/__tests__/styles/paletteTokens.test.ts +44 -0
  164. package/src/__tests__/styles/v2AuditRules.test.ts +104 -0
  165. package/src/__tests__/utils/plotlyTemplate.test.ts +4 -4
  166. package/src/__tests__/utils/time.test.ts +18 -1
  167. package/src/components/ActionMenu.vue +6 -37
  168. package/src/components/AdductText.story.vue +7 -0
  169. package/src/components/AdductText.vue +1 -1
  170. package/src/components/AlertBox.story.vue +2 -2
  171. package/src/components/AlertBox.vue +18 -16
  172. package/src/components/AppSidebar.story.vue +0 -28
  173. package/src/components/AppTopBar.onboarding.story.vue +69 -0
  174. package/src/components/AppTopBar.story.vue +105 -15
  175. package/src/components/AppTopBar.vue +248 -122
  176. package/src/components/ArtifactSaveDialog.story.vue +23 -0
  177. package/src/components/ArtifactSaveDialog.vue +102 -12
  178. package/src/components/AuditTrail.story.vue +2 -1
  179. package/src/components/AuditTrail.vue +2 -21
  180. package/src/components/Avatar.vue +10 -14
  181. package/src/components/BaseButton.vue +16 -2
  182. package/src/components/BaseModal.vue +2 -1
  183. package/src/components/BaseSelect.multiple.story.vue +13 -2
  184. package/src/components/BaseSelect.vue +4 -3
  185. package/src/components/BatchProgressList.vue +35 -25
  186. package/src/components/ChartContainer.story.vue +2 -1
  187. package/src/components/ChartContainer.vue +8 -6
  188. package/src/components/ConfirmDialog.story.vue +1 -1
  189. package/src/components/EmptyState.vue +1 -1
  190. package/src/components/ExperimentPopover.story.vue +165 -53
  191. package/src/components/ExperimentPopover.vue +169 -187
  192. package/src/components/ExperimentSelectorModal.story.vue +73 -31
  193. package/src/components/ExperimentSelectorModal.vue +144 -111
  194. package/src/components/FormField.story.vue +8 -48
  195. package/src/components/GeneratedPluginView.vue +11 -10
  196. package/src/components/GeneratedResultRenderer.vue +3 -4
  197. package/src/components/InstrumentStateBadge.vue +1 -1
  198. package/src/components/JobsStatusTray.story.vue +97 -43
  199. package/src/components/JobsStatusTray.vue +287 -290
  200. package/src/components/LayoutResizeHandle.story.vue +65 -4
  201. package/src/components/LoadingSpinner.vue +1 -1
  202. package/src/components/NumberInput.vue +3 -6
  203. package/src/components/PluginIcon.story.vue +2 -10
  204. package/src/components/PluginIcon.vue +2 -2
  205. package/src/components/PluginWorkspaceView.props.ts +3 -0
  206. package/src/components/PluginWorkspaceView.story.vue +1 -1
  207. package/src/components/PluginWorkspaceView.vue +17 -0
  208. package/src/components/RuntimeUpdateNotice.vue +1 -1
  209. package/src/components/SampleSelector.story.vue +22 -7
  210. package/src/components/SampleSelector.vue +34 -37
  211. package/src/components/SampleSelectorGroupNode.vue +1 -1
  212. package/src/components/SectionCard.story.vue +35 -2
  213. package/src/components/SequenceProgressBar.story.vue +9 -0
  214. package/src/components/SequenceProgressBar.vue +6 -1
  215. package/src/components/SettingsModal.schema.ts +1 -1
  216. package/src/components/SettingsModal.vue +9 -14
  217. package/src/components/SmartGroupFieldRecipe.story.vue +1 -1
  218. package/src/components/SmartGroupManual.story.vue +1 -1
  219. package/src/components/StepWizard.story.vue +33 -0
  220. package/src/components/StepWizard.vue +8 -1
  221. package/src/components/Tooltip.vue +9 -32
  222. package/src/components/WellPlate.story.vue +3 -1
  223. package/src/components/WellPlate.vue +7 -0
  224. package/src/components/internal/AppTopBarOnboardingInternal.vue +172 -0
  225. package/src/components/internal/AppTopBarPageSelectorInternal.vue +140 -72
  226. package/src/components/internal/AppTopBarPillNavInternal.vue +33 -2
  227. package/src/components/internal/DatePickerDateInternal.vue +23 -85
  228. package/src/components/internal/DatePickerDateTimeInternal.vue +10 -14
  229. package/src/components/internal/DatePickerTimeInternal.vue +13 -9
  230. package/src/components/internal/NumberUnitInputInternal.vue +4 -18
  231. package/src/components/internal/OnboardingLayerInternal.vue +173 -0
  232. package/src/components/internal/ResourcePickerListInternal.vue +45 -85
  233. package/src/components/internal/SelectMultipleInternal.vue +187 -65
  234. package/src/components/internal/SelectSearchableInternal.vue +8 -4
  235. package/src/components/internal/WellEditPopupInternal.vue +11 -22
  236. package/src/components/internal/WorkspaceShellInternal.vue +12 -0
  237. package/src/composables/createClient.ts +2 -0
  238. package/src/composables/index.ts +1 -0
  239. package/src/composables/pluginIdentity.ts +31 -0
  240. package/src/composables/pluginWorkspaceModel.ts +2 -2
  241. package/src/composables/useAppExperiment.ts +20 -0
  242. package/src/composables/useCalendarGrid.ts +4 -3
  243. package/src/composables/useExperimentSelector.ts +77 -31
  244. package/src/composables/useFileImport.ts +51 -1
  245. package/src/composables/useFloatingPanel.ts +107 -0
  246. package/src/composables/useJobCenter.ts +188 -6
  247. package/src/composables/useOnboarding.ts +465 -0
  248. package/src/composables/usePluginWorkspace.ts +1 -1
  249. package/src/data.ts +1 -0
  250. package/src/runtime.ts +2 -1
  251. package/src/shell.ts +17 -0
  252. package/src/stores/index.ts +0 -2
  253. package/src/stores/settings.ts +20 -50
  254. package/src/styles/components/action-menu.css +1 -1
  255. package/src/styles/components/adduct-text.css +13 -5
  256. package/src/styles/components/alert-box.css +39 -58
  257. package/src/styles/components/app-layout.css +10 -6
  258. package/src/styles/components/app-page-selector.css +121 -44
  259. package/src/styles/components/app-pill-nav.css +11 -12
  260. package/src/styles/components/app-sidebar.css +9 -18
  261. package/src/styles/components/app-top-bar.css +219 -55
  262. package/src/styles/components/artifact-save-dialog.css +153 -2
  263. package/src/styles/components/audit-trail.css +16 -19
  264. package/src/styles/components/avatar.css +6 -4
  265. package/src/styles/components/batch-progress-list.css +38 -36
  266. package/src/styles/components/button.css +36 -59
  267. package/src/styles/components/calendar.css +12 -12
  268. package/src/styles/components/chart-container.css +34 -23
  269. package/src/styles/components/checkbox.css +2 -12
  270. package/src/styles/components/collapsible-card.css +27 -29
  271. package/src/styles/components/confirm-dialog.css +13 -14
  272. package/src/styles/components/dataframe.css +13 -5
  273. package/src/styles/components/date-picker.css +84 -94
  274. package/src/styles/components/datetime-picker.css +35 -47
  275. package/src/styles/components/divider.css +20 -20
  276. package/src/styles/components/dose-calculator.css +3 -3
  277. package/src/styles/components/empty-state.css +20 -17
  278. package/src/styles/components/experiment-code-badge.css +2 -0
  279. package/src/styles/components/experiment-popover.css +174 -329
  280. package/src/styles/components/experiment-selector-modal.css +88 -56
  281. package/src/styles/components/file-picker.css +3 -3
  282. package/src/styles/components/file-uploader.css +38 -49
  283. package/src/styles/components/form-builder.css +3 -3
  284. package/src/styles/components/formula-input.css +1 -1
  285. package/src/styles/components/icon-button.css +18 -24
  286. package/src/styles/components/input.css +5 -4
  287. package/src/styles/components/instrument-monitor.css +13 -15
  288. package/src/styles/components/jobs-status-tray.css +140 -296
  289. package/src/styles/components/layout-resize-handle.css +59 -16
  290. package/src/styles/components/modal.css +5 -7
  291. package/src/styles/components/molecule-input.css +2 -2
  292. package/src/styles/components/multi-select.css +65 -117
  293. package/src/styles/components/number-input.css +26 -19
  294. package/src/styles/components/onboarding.css +368 -0
  295. package/src/styles/components/pill.css +3 -2
  296. package/src/styles/components/plate-editor.css +0 -1
  297. package/src/styles/components/plugin-icon.css +26 -23
  298. package/src/styles/components/popover.css +2 -2
  299. package/src/styles/components/presence-avatars.css +1 -1
  300. package/src/styles/components/progress-bar.css +3 -3
  301. package/src/styles/components/protocol-step-editor.css +1 -3
  302. package/src/styles/components/resource-card.css +2 -2
  303. package/src/styles/components/resource-picker-list.css +6 -57
  304. package/src/styles/components/sample-hierarchy-tree.css +4 -4
  305. package/src/styles/components/sample-selector.css +138 -79
  306. package/src/styles/components/schedule-calendar.css +8 -8
  307. package/src/styles/components/searchable-select.css +15 -19
  308. package/src/styles/components/section-card.css +54 -49
  309. package/src/styles/components/segmented-control.css +18 -15
  310. package/src/styles/components/select.css +3 -3
  311. package/src/styles/components/sequence-input.css +2 -2
  312. package/src/styles/components/sequence-progress-bar.css +17 -8
  313. package/src/styles/components/settings-modal.css +7 -2
  314. package/src/styles/components/smart-group.css +18 -18
  315. package/src/styles/components/step-wizard.css +52 -16
  316. package/src/styles/components/tabs.css +2 -2
  317. package/src/styles/components/textarea.css +3 -3
  318. package/src/styles/components/time-picker.css +37 -25
  319. package/src/styles/components/toast.css +13 -11
  320. package/src/styles/components/toggle.css +1 -11
  321. package/src/styles/components/tooltip.css +12 -11
  322. package/src/styles/components/unit-input.css +9 -8
  323. package/src/styles/components/well-edit-popup.css +2 -2
  324. package/src/styles/components/well-plate.css +9 -2
  325. package/src/styles/index.css +1 -0
  326. package/src/styles/variables.css +247 -78
  327. package/src/types/componentWorkflowTypes.ts +2 -0
  328. package/src/types/components.ts +2 -0
  329. package/src/types/generated/platformContext.ts +1 -0
  330. package/src/types/generated-ui.ts +4 -0
  331. package/src/types/index.ts +1 -0
  332. package/src/types/jobs.ts +10 -0
  333. package/src/types/platform.ts +1 -1
  334. package/src/utils/time.ts +21 -0
  335. package/dist/ActionMenu-CScINahU.js.map +0 -1
  336. package/dist/AppSidebar-BmiiPfz9.js.map +0 -1
  337. package/dist/BaseModal-DfRIuVoj.js.map +0 -1
  338. package/dist/ExperimentPopover-C4sGw-is.js +0 -359
  339. package/dist/ExperimentPopover-C4sGw-is.js.map +0 -1
  340. package/dist/ExperimentSelectorModal-D-9z7cNx.js.map +0 -1
  341. package/dist/SettingsModal-CSLE31yg.js.map +0 -1
  342. package/dist/data-C2PwI_dn.js.map +0 -1
  343. package/dist/experiment-43OJtH7R.js.map +0 -1
  344. package/dist/lab-DLwRl_Ql.js.map +0 -1
  345. package/dist/records-BzTcxekG.js.map +0 -1
  346. package/dist/runtime-D6gVat6r.js.map +0 -1
  347. package/dist/useExperimentSamples-CxcnxZ8h.js.map +0 -1
  348. package/dist/useListReorder-CcbEYxX-.js.map +0 -1
  349. package/dist/useRackEditor-BD5NIo5s.js.map +0 -1
  350. package/dist/useRealtime-PalKue84.js +0 -696
  351. package/dist/useRealtime-PalKue84.js.map +0 -1
  352. package/dist/useRequest-D5JDfsgZ.js +0 -76
  353. package/dist/useRequest-D5JDfsgZ.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"runtime-D6gVat6r.js","names":["$emit","$attrs"],"sources":["../src/composables/useToast.ts","../src/components/AppToastContainer.vue","../src/components/AppToastContainer.vue","../src/composables/controlWorkspaceOptions.ts","../src/composables/useControlWorkspace.ts","../src/components/internal/WorkspaceControlsInternal.vue","../src/components/internal/WorkspaceControlsInternal.vue","../src/components/internal/WorkspaceShellInternal.vue","../src/components/internal/WorkspaceShellInternal.vue","../src/components/internal/WorkspaceSidebarInternal.vue","../src/components/internal/WorkspaceSidebarInternal.vue","../src/components/PluginWorkspaceView.vue","../src/components/PluginWorkspaceView.vue","../src/components/Avatar.vue","../src/components/Avatar.vue","../src/generated/schema.ts","../src/components/GeneratedPluginView.vue","../src/components/GeneratedPluginView.vue","../src/components/internal/PlateEditorBindingInternal.vue","../src/components/internal/PlateEditorBindingInternal.vue","../src/components/ComponentBindingRenderer.vue","../src/components/ComponentBindingRenderer.vue","../src/components/RuntimeUpdateNotice.vue","../src/components/RuntimeUpdateNotice.vue","../src/composables/usePresence.ts","../src/utils/presenceAvatars.ts","../src/components/PresenceAvatars.vue","../src/components/PresenceAvatars.vue","../src/runtime.ts"],"sourcesContent":["import { ref } from 'vue'\nimport type { Toast, ToastOptions } from '../types'\n\nconst toasts = ref<Toast[]>([])\nlet nextId = 0\n\n/** Options of `success()`, `error()`, `warning()` and `info()`: the message is the title. */\ntype ToastMessageOptions = Omit<ToastOptions, 'title' | 'type'>\n\n/** Reactive global toast queue with success/error/warning/info variants and auto-dismiss timers. */\nexport function useToast() {\n /** Push a structured toast. `progress: 'indeterminate'` is the in-progress form and never auto-dismisses. */\n function push(options: ToastOptions): number {\n const id = nextId++\n const duration = options.duration ?? 3500\n toasts.value.push({\n id,\n type: 'success',\n ...options,\n message: options.message ?? options.title,\n duration,\n actions: options.actions?.slice(0, 2),\n })\n if (options.progress !== 'indeterminate') {\n setTimeout(() => dismiss(id), duration)\n }\n return id\n }\n\n function notify(type: Toast['type'], duration: number, message: string, options: ToastMessageOptions = {}): number {\n return push({ duration, ...options, title: message, type })\n }\n\n function success(message: string, options?: ToastMessageOptions): number {\n return notify('success', 3500, message, options)\n }\n\n function error(message: string, options?: ToastMessageOptions): number {\n return notify('error', 5000, message, options)\n }\n\n function warning(message: string, options?: ToastMessageOptions): number {\n return notify('warning', 4000, message, options)\n }\n\n function info(message: string, options?: ToastMessageOptions): number {\n return notify('info', 3500, message, options)\n }\n\n function dismiss(id: number) {\n toasts.value = toasts.value.filter(t => t.id !== id)\n }\n\n function clear() {\n toasts.value = []\n }\n\n return { toasts, push, success, error, warning, info, dismiss, clear }\n}\n","<script setup lang=\"ts\">\n/** Preferred toast container driven by useToast: title/detail, up to two actions, TTL or indeterminate bar, click-to-close. */\nimport { useToast } from '../composables/useToast'\nimport type { Toast, ToastAction } from '../types'\n\nconst { toasts, dismiss } = useToast()\n\nfunction title(toast: Toast): string {\n return toast.title ?? toast.message\n}\n\nfunction actions(toast: Toast): ToastAction[] {\n return (toast.actions ?? []).slice(0, 2)\n}\n\nfunction progress(toast: Toast): NonNullable<Toast['progress']> {\n return toast.progress ?? 'ttl'\n}\n\nfunction runAction(toast: Toast, action: ToastAction) {\n action.onClick()\n dismiss(toast.id)\n}\n</script>\n\n<template>\n <Teleport to=\"body\">\n <div class=\"mint-toast__container\">\n <TransitionGroup name=\"toast\">\n <div\n v-for=\"toast in toasts\"\n :key=\"toast.id\"\n :class=\"[\n 'mint-toast__item',\n `mint-toast__item--${toast.type}`,\n (toast.count ?? 1) > 1 ? 'mint-toast__item--stacked' : '',\n ]\"\n :role=\"toast.type === 'error' || toast.type === 'warning' ? 'alert' : 'status'\"\n @click=\"dismiss(toast.id)\"\n >\n <!-- Lucide circle-check -->\n <svg v-if=\"toast.type === 'success'\" class=\"mint-toast__icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" /><path d=\"m9 12 2 2 4-4\" />\n </svg>\n <!-- Lucide circle-x -->\n <svg v-else-if=\"toast.type === 'error'\" class=\"mint-toast__icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" /><path d=\"m15 9-6 6\" /><path d=\"m9 9 6 6\" />\n </svg>\n <!-- Lucide triangle-alert -->\n <svg v-else-if=\"toast.type === 'warning'\" class=\"mint-toast__icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" /><path d=\"M12 9v4\" /><path d=\"M12 17h.01\" />\n </svg>\n <!-- Lucide info -->\n <svg v-else class=\"mint-toast__icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" /><path d=\"M12 16v-4\" /><path d=\"M12 8h.01\" />\n </svg>\n\n <div class=\"mint-toast__body\">\n <div class=\"mint-toast__title\">\n <span class=\"mint-toast__message\">{{ title(toast) }}</span>\n <span v-if=\"(toast.count ?? 1) > 1\" class=\"mint-toast__count\">×{{ toast.count }}</span>\n </div>\n <div v-if=\"toast.detail\" class=\"mint-toast__detail\">{{ toast.detail }}</div>\n <div v-if=\"actions(toast).length\" class=\"mint-toast__actions\">\n <button\n v-for=\"action in actions(toast)\"\n :key=\"action.label\"\n type=\"button\"\n :class=\"['mint-toast__action', action.primary ? 'mint-toast__action--primary' : '']\"\n @click.stop=\"runAction(toast, action)\"\n >\n {{ action.label }}\n </button>\n </div>\n </div>\n\n <button\n v-if=\"toast.dismissible !== false\"\n type=\"button\"\n class=\"mint-toast__close\"\n aria-label=\"Dismiss\"\n @click.stop=\"dismiss(toast.id)\"\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" aria-hidden=\"true\">\n <path d=\"M18 6 6 18\" /><path d=\"m6 6 12 12\" />\n </svg>\n </button>\n\n <span\n v-if=\"progress(toast) === 'ttl'\"\n class=\"mint-toast__progress\"\n :style=\"{ animationDuration: `${toast.duration ?? 3500}ms` }\"\n />\n <span\n v-else-if=\"progress(toast) === 'indeterminate'\"\n class=\"mint-toast__progress mint-toast__progress--indeterminate\"\n />\n </div>\n </TransitionGroup>\n </div>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\n/** Preferred toast container driven by useToast: title/detail, up to two actions, TTL or indeterminate bar, click-to-close. */\nimport { useToast } from '../composables/useToast'\nimport type { Toast, ToastAction } from '../types'\n\nconst { toasts, dismiss } = useToast()\n\nfunction title(toast: Toast): string {\n return toast.title ?? toast.message\n}\n\nfunction actions(toast: Toast): ToastAction[] {\n return (toast.actions ?? []).slice(0, 2)\n}\n\nfunction progress(toast: Toast): NonNullable<Toast['progress']> {\n return toast.progress ?? 'ttl'\n}\n\nfunction runAction(toast: Toast, action: ToastAction) {\n action.onClick()\n dismiss(toast.id)\n}\n</script>\n\n<template>\n <Teleport to=\"body\">\n <div class=\"mint-toast__container\">\n <TransitionGroup name=\"toast\">\n <div\n v-for=\"toast in toasts\"\n :key=\"toast.id\"\n :class=\"[\n 'mint-toast__item',\n `mint-toast__item--${toast.type}`,\n (toast.count ?? 1) > 1 ? 'mint-toast__item--stacked' : '',\n ]\"\n :role=\"toast.type === 'error' || toast.type === 'warning' ? 'alert' : 'status'\"\n @click=\"dismiss(toast.id)\"\n >\n <!-- Lucide circle-check -->\n <svg v-if=\"toast.type === 'success'\" class=\"mint-toast__icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" /><path d=\"m9 12 2 2 4-4\" />\n </svg>\n <!-- Lucide circle-x -->\n <svg v-else-if=\"toast.type === 'error'\" class=\"mint-toast__icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" /><path d=\"m15 9-6 6\" /><path d=\"m9 9 6 6\" />\n </svg>\n <!-- Lucide triangle-alert -->\n <svg v-else-if=\"toast.type === 'warning'\" class=\"mint-toast__icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" /><path d=\"M12 9v4\" /><path d=\"M12 17h.01\" />\n </svg>\n <!-- Lucide info -->\n <svg v-else class=\"mint-toast__icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" /><path d=\"M12 16v-4\" /><path d=\"M12 8h.01\" />\n </svg>\n\n <div class=\"mint-toast__body\">\n <div class=\"mint-toast__title\">\n <span class=\"mint-toast__message\">{{ title(toast) }}</span>\n <span v-if=\"(toast.count ?? 1) > 1\" class=\"mint-toast__count\">×{{ toast.count }}</span>\n </div>\n <div v-if=\"toast.detail\" class=\"mint-toast__detail\">{{ toast.detail }}</div>\n <div v-if=\"actions(toast).length\" class=\"mint-toast__actions\">\n <button\n v-for=\"action in actions(toast)\"\n :key=\"action.label\"\n type=\"button\"\n :class=\"['mint-toast__action', action.primary ? 'mint-toast__action--primary' : '']\"\n @click.stop=\"runAction(toast, action)\"\n >\n {{ action.label }}\n </button>\n </div>\n </div>\n\n <button\n v-if=\"toast.dismissible !== false\"\n type=\"button\"\n class=\"mint-toast__close\"\n aria-label=\"Dismiss\"\n @click.stop=\"dismiss(toast.id)\"\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" aria-hidden=\"true\">\n <path d=\"M18 6 6 18\" /><path d=\"m6 6 12 12\" />\n </svg>\n </button>\n\n <span\n v-if=\"progress(toast) === 'ttl'\"\n class=\"mint-toast__progress\"\n :style=\"{ animationDuration: `${toast.duration ?? 3500}ms` }\"\n />\n <span\n v-else-if=\"progress(toast) === 'indeterminate'\"\n class=\"mint-toast__progress mint-toast__progress--indeterminate\"\n />\n </div>\n </TransitionGroup>\n </div>\n </Teleport>\n</template>\n","import type {\n ControlWorkspaceOptions,\n} from './controlSchemaTypes'\n\nexport function mergeControlWorkspaceOptions(\n base?: ControlWorkspaceOptions,\n override?: ControlWorkspaceOptions,\n): ControlWorkspaceOptions {\n return {\n ...(base ?? {}),\n ...(override ?? {}),\n initialValues: {\n ...(base?.initialValues ?? {}),\n ...(override?.initialValues ?? {}),\n },\n topBarSettings: {\n ...(base?.topBarSettings ?? {}),\n ...(override?.topBarSettings ?? {}),\n },\n }\n}\n","import {\n computed,\n reactive,\n ref,\n watch,\n} from 'vue'\nimport type {\n PillNavItem,\n TopBarSettingsConfig,\n} from '../types'\nimport {\n replaceRecord,\n} from './controlSchemaUtils'\nimport {\n mergeControlWorkspaceOptions,\n} from './controlWorkspaceOptions'\nimport {\n controlValuesToComponentBindings,\n controlValuesToComponentBindingsById,\n controlValuesToComponentProps,\n} from './controlComponentBindings'\nimport {\n isControlModelBinding,\n} from './controlSchemaModel'\nimport {\n useControlSchema,\n} from './useControlSchema'\nimport type {\n ControlComponentBinding,\n ControlComponentBindingsById,\n ControlComponentBindingsConfig,\n ControlComponentPropsByIdMap,\n ControlComponentPropsMap,\n ControlModelBinding,\n ControlSchema,\n ControlValues,\n ControlWorkspaceComponentBindings,\n ControlWorkspaceFormBinding,\n ControlWorkspaceOptions,\n ControlWorkspacePillNavBinding,\n ControlWorkspaceSidebarBinding,\n ControlWorkspaceTopBarBinding,\n ControlWorkspaceTopBarSettingsBinding,\n UseControlWorkspaceReturn,\n} from './controlSchemaTypes'\n\n/**\n * Prepare shared reactive values plus AppTopBar/AppSidebar/FormBuilder bindings from one simple controls data model.\n *\n * @example Recommended\n * ```ts\n * const workspace = useControlWorkspace(workspaceModel)\n * const { form, sidebar, topBar } = workspace.bindings\n * ```\n */\nexport function useControlWorkspace<TControls extends ControlSchema>(\n controlsOrModel: TControls | (ControlModelBinding & { controls: TControls }),\n options: ControlWorkspaceOptions = {},\n): UseControlWorkspaceReturn<TControls> {\n const model = isControlModelBinding<ControlModelBinding & { controls: TControls }>(controlsOrModel)\n ? controlsOrModel\n : undefined\n const controls: TControls = model ? model.controls : controlsOrModel as TControls\n const workspaceOptions = model\n ? mergeControlWorkspaceOptions(model.controlOptions, options)\n : options\n const { initialValues, topBarSettings, ...schemaOptions } = workspaceOptions\n const schema = useControlSchema(controls, schemaOptions)\n const activeView = ref(schema.defaultView)\n const values = reactive({\n ...schema.initialValues,\n ...(initialValues ?? {}),\n }) as ControlValues<TControls> & Record<string, unknown>\n\n function setActiveView(viewId: string) {\n syncActiveView(viewId)\n }\n\n function syncActiveView(viewId: string) {\n if (!schema.viewIds.includes(viewId)) return\n if (activeView.value !== viewId) activeView.value = viewId\n if (sidebar.activeView !== viewId) sidebar.activeView = viewId\n if (pillNav.currentItemId !== viewId) pillNav.currentItemId = viewId\n }\n\n function setValues(nextValues: Record<string, unknown>) {\n Object.assign(values, nextValues)\n }\n\n function resetValues(nextValues: Record<string, unknown> = {}) {\n replaceRecord(values, {\n ...schema.initialValues,\n ...nextValues,\n })\n }\n\n function getComponentProps(\n mapping?: ControlComponentPropsMap<ControlValues<TControls> & Record<string, unknown>>,\n ): Record<string, unknown> {\n return controlValuesToComponentProps(values, mapping)\n }\n\n function getComponentPropsById(\n mappings?: ControlComponentPropsByIdMap<ControlValues<TControls> & Record<string, unknown>>,\n ): Record<string, Record<string, unknown>> {\n if (mappings === undefined) return {}\n\n return Object.fromEntries(\n Object.entries(mappings).map(([id, mapping]) => [\n id,\n controlValuesToComponentProps(values, mapping),\n ]),\n )\n }\n\n function getComponentBindings(\n bindings?: ControlComponentBindingsConfig<ControlValues<TControls> & Record<string, unknown>>,\n ): ControlComponentBinding[] {\n return controlValuesToComponentBindings(values, bindings)\n }\n\n function getComponentBindingsById(\n bindings?: ControlComponentBindingsConfig<ControlValues<TControls> & Record<string, unknown>>,\n ): ControlComponentBindingsById {\n return controlValuesToComponentBindingsById(values, bindings)\n }\n\n const componentProps = computed(() => (\n model?.componentProps === undefined ? {} : getComponentProps(model.componentProps)\n ))\n const componentPropsById = computed(() => getComponentPropsById(model?.componentPropsById))\n const componentBindings = computed(() => getComponentBindings(model?.componentBindings))\n const componentBindingsById = computed(() => getComponentBindingsById(model?.componentBindings))\n const form = {\n ...schema.form,\n modelValue: values,\n 'onUpdate:modelValue': setValues,\n } as ControlWorkspaceFormBinding\n\n const topBarSettingsConfig: TopBarSettingsConfig = {\n ...schema.topBarSettingsConfig,\n ...(topBarSettings ?? {}),\n values,\n }\n const sidebar = reactive({\n ...schema.sidebar,\n activeView: activeView.value,\n values,\n 'onUpdate:values': setValues,\n }) as ControlWorkspaceSidebarBinding\n const pillNav = reactive({\n items: schema.viewItems,\n currentItemId: activeView.value,\n onSelect: (item: PillNavItem) => setActiveView(item.id),\n }) as ControlWorkspacePillNavBinding\n const topBarSettingsBinding = {\n spec: { settings: topBarSettingsConfig },\n onSettingsValuesChange: setValues,\n } as ControlWorkspaceTopBarSettingsBinding\n const topBarProps = computed<ControlWorkspaceTopBarBinding>(() => ({\n spec: { pills: pillNav.items, settings: topBarSettingsConfig },\n pill: pillNav.currentItemId,\n onPillSelect: pillNav.onSelect,\n onSettingsValuesChange: setValues,\n }))\n const bindings: ControlWorkspaceComponentBindings = {\n form,\n sidebar,\n topBar: topBarProps,\n topBarSettings: topBarSettingsBinding,\n pillNav,\n componentBindings,\n componentBindingsById,\n componentProps,\n componentPropsById,\n }\n\n watch(activeView, syncActiveView, { flush: 'sync' })\n watch(() => sidebar.activeView, syncActiveView, { flush: 'sync' })\n watch(() => pillNav.currentItemId, syncActiveView, { flush: 'sync' })\n\n return {\n ...schema,\n schema,\n values,\n activeView,\n topBarSettingsConfig,\n form,\n sidebar,\n topBar: topBarProps,\n pillNav,\n topBarSettings: topBarSettingsBinding,\n bindings,\n componentBindings,\n componentBindingsById,\n componentProps,\n componentPropsById,\n setActiveView,\n setValues,\n resetValues,\n getComponentProps,\n getComponentPropsById,\n getComponentBindings,\n getComponentBindingsById,\n }\n}\n","<script setup lang=\"ts\">\n/**\n * Internal: renders PluginWorkspaceView's default (main content) slot bound to the\n * control-schema-derived scoped-slot payload (active view, values, component bindings/props).\n * Not part of the public SDK surface — see PluginWorkspaceView.vue for the public component.\n */\nimport type { PluginWorkspaceControlsModel } from '../../composables/pluginWorkspaceModel'\n\ndefineProps<{\n controls: PluginWorkspaceControlsModel\n}>()\n\ndefineSlots<{\n default?: (props: PluginWorkspaceControlsModel) => unknown\n}>()\n</script>\n\n<template>\n <slot v-bind=\"controls\" />\n</template>\n","<script setup lang=\"ts\">\n/**\n * Internal: renders PluginWorkspaceView's default (main content) slot bound to the\n * control-schema-derived scoped-slot payload (active view, values, component bindings/props).\n * Not part of the public SDK surface — see PluginWorkspaceView.vue for the public component.\n */\nimport type { PluginWorkspaceControlsModel } from '../../composables/pluginWorkspaceModel'\n\ndefineProps<{\n controls: PluginWorkspaceControlsModel\n}>()\n\ndefineSlots<{\n default?: (props: PluginWorkspaceControlsModel) => unknown\n}>()\n</script>\n\n<template>\n <slot v-bind=\"controls\" />\n</template>\n","<script setup lang=\"ts\">\n/**\n * Internal: AppLayout + AppTopBar for PluginWorkspaceView, driven by a single `shell` model.\n * Owns the responsive/collapse layout props and the top bar's default rendering; the caller\n * decides whether to override the `topbar`/`sidebar` slots and supplies the sidebar content.\n * Not part of the public SDK surface — see PluginWorkspaceView.vue for the public component.\n */\nimport type {\n PillNavItem,\n PillNavOption,\n} from '../../types'\nimport AppLayout from '../AppLayout.vue'\nimport AppTopBar from '../AppTopBar.vue'\nimport type { PluginWorkspaceShellModel } from '../../composables/pluginWorkspaceModel'\n\ndefineProps<{\n shell: PluginWorkspaceShellModel\n}>()\n\nconst emit = defineEmits<{\n 'pill-select': [item: PillNavItem]\n 'pill-option-select': [option: PillNavOption, item: PillNavItem]\n 'settings-values-change': [data: Record<string, unknown>]\n}>()\n\nfunction handlePillOptionSelect(option: PillNavOption, item: PillNavItem) {\n emit('pill-option-select', option, item)\n}\n\ndefineSlots<{\n topbar?: (props: PluginWorkspaceShellModel['controls']) => unknown\n sidebar?: (props: PluginWorkspaceShellModel['controls']) => unknown\n default?: (props: PluginWorkspaceShellModel['controls']) => unknown\n icon?: (props: Record<string, unknown>) => unknown\n logo?: (props: Record<string, unknown>) => unknown\n nav?: (props: Record<string, unknown>) => unknown\n center?: (props: Record<string, unknown>) => unknown\n actions?: (props: Record<string, unknown>) => unknown\n 'settings-appearance'?: (props: Record<string, unknown>) => unknown\n}>()\n</script>\n\n<template>\n <AppLayout\n class=\"mint-plugin-workspace-view\"\n :sidebar-position=\"shell.sidebarPosition\"\n :sidebar-width=\"shell.sidebarWidth\"\n :floating=\"shell.floating\"\n :responsive-sidebar=\"shell.responsiveSidebar\"\n :sidebar-toggle-label=\"shell.sidebarToggleLabel\"\n :sidebar-close-label=\"shell.sidebarCloseLabel\"\n >\n <template #topbar>\n <slot name=\"topbar\" v-bind=\"shell.controls\">\n <AppTopBar\n v-if=\"shell.topBar\"\n :title=\"shell.title\"\n :subtitle=\"shell.subtitle\"\n :spec=\"shell.topBar\"\n :pill=\"shell.pill\"\n @pill-select=\"emit('pill-select', $event)\"\n @pill-option-select=\"handlePillOptionSelect\"\n @settings-values-change=\"emit('settings-values-change', $event)\"\n >\n <template\n v-for=\"slotName in shell.topBarSlotNames\"\n :key=\"slotName\"\n #[slotName]=\"slotProps\"\n >\n <!-- @vue-ignore dynamic SDK slot forwarding for AppTopBar passthrough slots -->\n <slot\n :name=\"slotName\"\n v-bind=\"slotProps ?? {}\"\n />\n </template>\n </AppTopBar>\n </slot>\n </template>\n\n <template v-if=\"shell.hasSidebarSurface\" #sidebar>\n <slot name=\"sidebar\" v-bind=\"shell.controls\" />\n </template>\n\n <slot v-bind=\"shell.controls\" />\n </AppLayout>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Internal: AppLayout + AppTopBar for PluginWorkspaceView, driven by a single `shell` model.\n * Owns the responsive/collapse layout props and the top bar's default rendering; the caller\n * decides whether to override the `topbar`/`sidebar` slots and supplies the sidebar content.\n * Not part of the public SDK surface — see PluginWorkspaceView.vue for the public component.\n */\nimport type {\n PillNavItem,\n PillNavOption,\n} from '../../types'\nimport AppLayout from '../AppLayout.vue'\nimport AppTopBar from '../AppTopBar.vue'\nimport type { PluginWorkspaceShellModel } from '../../composables/pluginWorkspaceModel'\n\ndefineProps<{\n shell: PluginWorkspaceShellModel\n}>()\n\nconst emit = defineEmits<{\n 'pill-select': [item: PillNavItem]\n 'pill-option-select': [option: PillNavOption, item: PillNavItem]\n 'settings-values-change': [data: Record<string, unknown>]\n}>()\n\nfunction handlePillOptionSelect(option: PillNavOption, item: PillNavItem) {\n emit('pill-option-select', option, item)\n}\n\ndefineSlots<{\n topbar?: (props: PluginWorkspaceShellModel['controls']) => unknown\n sidebar?: (props: PluginWorkspaceShellModel['controls']) => unknown\n default?: (props: PluginWorkspaceShellModel['controls']) => unknown\n icon?: (props: Record<string, unknown>) => unknown\n logo?: (props: Record<string, unknown>) => unknown\n nav?: (props: Record<string, unknown>) => unknown\n center?: (props: Record<string, unknown>) => unknown\n actions?: (props: Record<string, unknown>) => unknown\n 'settings-appearance'?: (props: Record<string, unknown>) => unknown\n}>()\n</script>\n\n<template>\n <AppLayout\n class=\"mint-plugin-workspace-view\"\n :sidebar-position=\"shell.sidebarPosition\"\n :sidebar-width=\"shell.sidebarWidth\"\n :floating=\"shell.floating\"\n :responsive-sidebar=\"shell.responsiveSidebar\"\n :sidebar-toggle-label=\"shell.sidebarToggleLabel\"\n :sidebar-close-label=\"shell.sidebarCloseLabel\"\n >\n <template #topbar>\n <slot name=\"topbar\" v-bind=\"shell.controls\">\n <AppTopBar\n v-if=\"shell.topBar\"\n :title=\"shell.title\"\n :subtitle=\"shell.subtitle\"\n :spec=\"shell.topBar\"\n :pill=\"shell.pill\"\n @pill-select=\"emit('pill-select', $event)\"\n @pill-option-select=\"handlePillOptionSelect\"\n @settings-values-change=\"emit('settings-values-change', $event)\"\n >\n <template\n v-for=\"slotName in shell.topBarSlotNames\"\n :key=\"slotName\"\n #[slotName]=\"slotProps\"\n >\n <!-- @vue-ignore dynamic SDK slot forwarding for AppTopBar passthrough slots -->\n <slot\n :name=\"slotName\"\n v-bind=\"slotProps ?? {}\"\n />\n </template>\n </AppTopBar>\n </slot>\n </template>\n\n <template v-if=\"shell.hasSidebarSurface\" #sidebar>\n <slot name=\"sidebar\" v-bind=\"shell.controls\" />\n </template>\n\n <slot v-bind=\"shell.controls\" />\n </AppLayout>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Internal: AppSidebar for PluginWorkspaceView, driven by a single `sidebar` model covering\n * chrome, panels/forms, collapse behavior, and the compact control-schema props that drive\n * AppSidebar's auto-generated form.\n * Not part of the public SDK surface — see PluginWorkspaceView.vue for the public component.\n */\nimport AppSidebar from '../AppSidebar.vue'\nimport type { PluginWorkspaceSidebarModel } from '../../composables/pluginWorkspaceModel'\n\ndefineProps<{\n sidebar: PluginWorkspaceSidebarModel\n}>()\n\ndefineEmits<{\n 'update:values': [values: Record<string, unknown>]\n 'update:collapsed': [value: boolean]\n 'update:toggle': [sectionId: string, value: boolean]\n 'section-action': [sectionId: string, actionId: string]\n 'form-submit': [sectionId: string, values: Record<string, unknown>]\n 'form-cancel': [sectionId: string]\n}>()\n\ndefineSlots<{\n header?: (props: Record<string, unknown>) => unknown\n collapsed?: (props: Record<string, unknown>) => unknown\n 'collapsed-footer'?: (props: Record<string, unknown>) => unknown\n footer?: (props: Record<string, unknown>) => unknown\n}>()\n</script>\n\n<template>\n <AppSidebar\n :spec=\"sidebar.spec\"\n :active-view=\"sidebar.activeView\"\n :values=\"sidebar.values\"\n :collapsed=\"sidebar.collapsed\"\n :form-loading=\"sidebar.formLoading\"\n :form-disabled=\"sidebar.formDisabled\"\n :form-readonly=\"sidebar.formReadonly\"\n @update:values=\"$emit('update:values', $event)\"\n @update:collapsed=\"$emit('update:collapsed', $event)\"\n @update:toggle=\"(sectionId, value) => $emit('update:toggle', sectionId, value)\"\n @section-action=\"(sectionId, actionId) => $emit('section-action', sectionId, actionId)\"\n @form-submit=\"(sectionId, values) => $emit('form-submit', sectionId, values)\"\n @form-cancel=\"$emit('form-cancel', $event)\"\n >\n <template\n v-for=\"slotName in sidebar.slotNames\"\n :key=\"slotName\"\n #[slotName]=\"slotProps\"\n >\n <!-- @vue-ignore dynamic SDK slot forwarding for AppSidebar section-* passthrough slots -->\n <slot\n :name=\"slotName\"\n v-bind=\"slotProps ?? {}\"\n />\n </template>\n </AppSidebar>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Internal: AppSidebar for PluginWorkspaceView, driven by a single `sidebar` model covering\n * chrome, panels/forms, collapse behavior, and the compact control-schema props that drive\n * AppSidebar's auto-generated form.\n * Not part of the public SDK surface — see PluginWorkspaceView.vue for the public component.\n */\nimport AppSidebar from '../AppSidebar.vue'\nimport type { PluginWorkspaceSidebarModel } from '../../composables/pluginWorkspaceModel'\n\ndefineProps<{\n sidebar: PluginWorkspaceSidebarModel\n}>()\n\ndefineEmits<{\n 'update:values': [values: Record<string, unknown>]\n 'update:collapsed': [value: boolean]\n 'update:toggle': [sectionId: string, value: boolean]\n 'section-action': [sectionId: string, actionId: string]\n 'form-submit': [sectionId: string, values: Record<string, unknown>]\n 'form-cancel': [sectionId: string]\n}>()\n\ndefineSlots<{\n header?: (props: Record<string, unknown>) => unknown\n collapsed?: (props: Record<string, unknown>) => unknown\n 'collapsed-footer'?: (props: Record<string, unknown>) => unknown\n footer?: (props: Record<string, unknown>) => unknown\n}>()\n</script>\n\n<template>\n <AppSidebar\n :spec=\"sidebar.spec\"\n :active-view=\"sidebar.activeView\"\n :values=\"sidebar.values\"\n :collapsed=\"sidebar.collapsed\"\n :form-loading=\"sidebar.formLoading\"\n :form-disabled=\"sidebar.formDisabled\"\n :form-readonly=\"sidebar.formReadonly\"\n @update:values=\"$emit('update:values', $event)\"\n @update:collapsed=\"$emit('update:collapsed', $event)\"\n @update:toggle=\"(sectionId, value) => $emit('update:toggle', sectionId, value)\"\n @section-action=\"(sectionId, actionId) => $emit('section-action', sectionId, actionId)\"\n @form-submit=\"(sectionId, values) => $emit('form-submit', sectionId, values)\"\n @form-cancel=\"$emit('form-cancel', $event)\"\n >\n <template\n v-for=\"slotName in sidebar.slotNames\"\n :key=\"slotName\"\n #[slotName]=\"slotProps\"\n >\n <!-- @vue-ignore dynamic SDK slot forwarding for AppSidebar section-* passthrough slots -->\n <slot\n :name=\"slotName\"\n v-bind=\"slotProps ?? {}\"\n />\n </template>\n </AppSidebar>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Standard plugin workspace shell that combines AppLayout, AppTopBar, and AppSidebar with LEAF-style defaults.\n *\n * The structure is one `:spec` built with `definePluginWorkspaceView()`: title,\n * top bar, sidebar (a `defineControlModel()` result generates its sections),\n * the experiment chip and its save action. The active pill, view, sidebar\n * values and collapse state are `v-model`s. It renders the toast container\n * unless `spec.toasts` is false.\n *\n * @example Recommended\n * ```vue\n * <PluginWorkspaceView :spec=\"workspace\" v-model:pill=\"tab\">\n * <router-view />\n * </PluginWorkspaceView>\n * ```\n */\nimport { computed, toValue, useSlots } from 'vue'\nimport type {\n PillNavItem,\n PillNavOption,\n} from '../types'\nimport { useAppExperiment } from '../composables/useAppExperiment'\nimport { usePluginWorkspace } from '../composables/usePluginWorkspace'\nimport AppToastContainer from './AppToastContainer.vue'\nimport WorkspaceControlsInternal from './internal/WorkspaceControlsInternal.vue'\nimport WorkspaceShellInternal from './internal/WorkspaceShellInternal.vue'\nimport WorkspaceSidebarInternal from './internal/WorkspaceSidebarInternal.vue'\nimport type {\n PluginWorkspaceForwardedSlotProps,\n PluginWorkspaceSlotProps,\n PluginWorkspaceViewEmits,\n PluginWorkspaceViewProps,\n} from './PluginWorkspaceView.props'\n\nconst props = withDefaults(defineProps<PluginWorkspaceViewProps>(), {\n spec: () => ({}),\n pill: undefined,\n view: undefined,\n values: undefined,\n sidebarCollapsed: undefined,\n formLoading: false,\n formDisabled: false,\n formReadonly: false,\n})\n\nconst emit = defineEmits<PluginWorkspaceViewEmits>()\n\ndefineSlots<{\n default?: (props: PluginWorkspaceSlotProps) => unknown\n topbar?: (props: PluginWorkspaceSlotProps) => unknown\n sidebar?: (props: PluginWorkspaceSlotProps) => unknown\n icon?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n logo?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n nav?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n center?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n actions?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n 'settings-appearance'?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n header?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n collapsed?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n 'collapsed-footer'?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n footer?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n}>()\n\nconst slots = useSlots()\n\n// The experiment chip is setup-time structure, like the rest of the spec.\nif (props.spec.experiment) {\n const save = props.spec.save\n useAppExperiment({\n onSelect: experiment => emit('experiment-select', experiment),\n onSave: save ? async () => (await save.handler()) ?? null : undefined,\n onDetach: () => emit('experiment-detach'),\n saveDisabled: computed(() => toValue(save?.disabled) ?? false),\n saveDisabledMessage: computed(() => toValue(save?.reason)),\n })\n}\n\nconst {\n shell,\n sidebar,\n controls,\n handleControlValuesUpdate,\n handlePillSelect,\n} = usePluginWorkspace({\n props,\n slots,\n emit,\n})\n\nfunction handleToggle(sectionId: string, value: boolean) {\n emit('update:toggle', sectionId, value)\n}\n\nfunction handleFormSubmit(sectionId: string, values: Record<string, unknown>) {\n emit('form-submit', sectionId, values)\n}\n\nfunction handleFormCancel(sectionId: string) {\n emit('form-cancel', sectionId)\n}\n\n</script>\n\n<template>\n <WorkspaceShellInternal\n :shell=\"shell\"\n @pill-select=\"handlePillSelect\"\n @pill-option-select=\"(option: PillNavOption, item: PillNavItem) => emit('pill-option-select', option, item)\"\n @settings-values-change=\"emit('settings-values-change', $event)\"\n >\n <template v-if=\"slots.topbar\" #topbar=\"scope\">\n <slot name=\"topbar\" v-bind=\"scope\" />\n </template>\n\n <template\n v-for=\"slotName in shell.topBarSlotNames\"\n :key=\"slotName\"\n #[slotName]=\"slotProps\"\n >\n <!-- @vue-ignore dynamic SDK slot forwarding for AppTopBar passthrough slots -->\n <slot\n :name=\"slotName\"\n v-bind=\"slotProps ?? {}\"\n />\n </template>\n\n <template v-if=\"shell.hasSidebarSurface\" #sidebar=\"scope\">\n <slot name=\"sidebar\" v-bind=\"scope\">\n <WorkspaceSidebarInternal\n :sidebar=\"sidebar\"\n @update:values=\"handleControlValuesUpdate\"\n @update:collapsed=\"emit('update:sidebarCollapsed', $event)\"\n @update:toggle=\"handleToggle\"\n @section-action=\"(sectionId: string, actionId: string) => emit('section-action', sectionId, actionId)\"\n @form-submit=\"handleFormSubmit\"\n @form-cancel=\"handleFormCancel\"\n >\n <template\n v-for=\"slotName in sidebar.slotNames\"\n :key=\"slotName\"\n #[slotName]=\"slotProps\"\n >\n <!-- @vue-ignore dynamic SDK slot forwarding for AppSidebar section-* passthrough slots -->\n <slot\n :name=\"slotName\"\n v-bind=\"slotProps ?? {}\"\n />\n </template>\n </WorkspaceSidebarInternal>\n </slot>\n </template>\n\n <template #default>\n <WorkspaceControlsInternal :controls=\"controls\">\n <template #default=\"controlsScope\">\n <slot v-bind=\"controlsScope\" />\n </template>\n </WorkspaceControlsInternal>\n <AppToastContainer v-if=\"spec.toasts !== false\" />\n </template>\n </WorkspaceShellInternal>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Standard plugin workspace shell that combines AppLayout, AppTopBar, and AppSidebar with LEAF-style defaults.\n *\n * The structure is one `:spec` built with `definePluginWorkspaceView()`: title,\n * top bar, sidebar (a `defineControlModel()` result generates its sections),\n * the experiment chip and its save action. The active pill, view, sidebar\n * values and collapse state are `v-model`s. It renders the toast container\n * unless `spec.toasts` is false.\n *\n * @example Recommended\n * ```vue\n * <PluginWorkspaceView :spec=\"workspace\" v-model:pill=\"tab\">\n * <router-view />\n * </PluginWorkspaceView>\n * ```\n */\nimport { computed, toValue, useSlots } from 'vue'\nimport type {\n PillNavItem,\n PillNavOption,\n} from '../types'\nimport { useAppExperiment } from '../composables/useAppExperiment'\nimport { usePluginWorkspace } from '../composables/usePluginWorkspace'\nimport AppToastContainer from './AppToastContainer.vue'\nimport WorkspaceControlsInternal from './internal/WorkspaceControlsInternal.vue'\nimport WorkspaceShellInternal from './internal/WorkspaceShellInternal.vue'\nimport WorkspaceSidebarInternal from './internal/WorkspaceSidebarInternal.vue'\nimport type {\n PluginWorkspaceForwardedSlotProps,\n PluginWorkspaceSlotProps,\n PluginWorkspaceViewEmits,\n PluginWorkspaceViewProps,\n} from './PluginWorkspaceView.props'\n\nconst props = withDefaults(defineProps<PluginWorkspaceViewProps>(), {\n spec: () => ({}),\n pill: undefined,\n view: undefined,\n values: undefined,\n sidebarCollapsed: undefined,\n formLoading: false,\n formDisabled: false,\n formReadonly: false,\n})\n\nconst emit = defineEmits<PluginWorkspaceViewEmits>()\n\ndefineSlots<{\n default?: (props: PluginWorkspaceSlotProps) => unknown\n topbar?: (props: PluginWorkspaceSlotProps) => unknown\n sidebar?: (props: PluginWorkspaceSlotProps) => unknown\n icon?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n logo?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n nav?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n center?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n actions?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n 'settings-appearance'?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n header?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n collapsed?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n 'collapsed-footer'?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n footer?: (props: PluginWorkspaceForwardedSlotProps) => unknown\n}>()\n\nconst slots = useSlots()\n\n// The experiment chip is setup-time structure, like the rest of the spec.\nif (props.spec.experiment) {\n const save = props.spec.save\n useAppExperiment({\n onSelect: experiment => emit('experiment-select', experiment),\n onSave: save ? async () => (await save.handler()) ?? null : undefined,\n onDetach: () => emit('experiment-detach'),\n saveDisabled: computed(() => toValue(save?.disabled) ?? false),\n saveDisabledMessage: computed(() => toValue(save?.reason)),\n })\n}\n\nconst {\n shell,\n sidebar,\n controls,\n handleControlValuesUpdate,\n handlePillSelect,\n} = usePluginWorkspace({\n props,\n slots,\n emit,\n})\n\nfunction handleToggle(sectionId: string, value: boolean) {\n emit('update:toggle', sectionId, value)\n}\n\nfunction handleFormSubmit(sectionId: string, values: Record<string, unknown>) {\n emit('form-submit', sectionId, values)\n}\n\nfunction handleFormCancel(sectionId: string) {\n emit('form-cancel', sectionId)\n}\n\n</script>\n\n<template>\n <WorkspaceShellInternal\n :shell=\"shell\"\n @pill-select=\"handlePillSelect\"\n @pill-option-select=\"(option: PillNavOption, item: PillNavItem) => emit('pill-option-select', option, item)\"\n @settings-values-change=\"emit('settings-values-change', $event)\"\n >\n <template v-if=\"slots.topbar\" #topbar=\"scope\">\n <slot name=\"topbar\" v-bind=\"scope\" />\n </template>\n\n <template\n v-for=\"slotName in shell.topBarSlotNames\"\n :key=\"slotName\"\n #[slotName]=\"slotProps\"\n >\n <!-- @vue-ignore dynamic SDK slot forwarding for AppTopBar passthrough slots -->\n <slot\n :name=\"slotName\"\n v-bind=\"slotProps ?? {}\"\n />\n </template>\n\n <template v-if=\"shell.hasSidebarSurface\" #sidebar=\"scope\">\n <slot name=\"sidebar\" v-bind=\"scope\">\n <WorkspaceSidebarInternal\n :sidebar=\"sidebar\"\n @update:values=\"handleControlValuesUpdate\"\n @update:collapsed=\"emit('update:sidebarCollapsed', $event)\"\n @update:toggle=\"handleToggle\"\n @section-action=\"(sectionId: string, actionId: string) => emit('section-action', sectionId, actionId)\"\n @form-submit=\"handleFormSubmit\"\n @form-cancel=\"handleFormCancel\"\n >\n <template\n v-for=\"slotName in sidebar.slotNames\"\n :key=\"slotName\"\n #[slotName]=\"slotProps\"\n >\n <!-- @vue-ignore dynamic SDK slot forwarding for AppSidebar section-* passthrough slots -->\n <slot\n :name=\"slotName\"\n v-bind=\"slotProps ?? {}\"\n />\n </template>\n </WorkspaceSidebarInternal>\n </slot>\n </template>\n\n <template #default>\n <WorkspaceControlsInternal :controls=\"controls\">\n <template #default=\"controlsScope\">\n <slot v-bind=\"controlsScope\" />\n </template>\n </WorkspaceControlsInternal>\n <AppToastContainer v-if=\"spec.toasts !== false\" />\n </template>\n </WorkspaceShellInternal>\n</template>\n","<script setup lang=\"ts\">\n/** Displays a user avatar as an image, a single derived initial, or a fallback icon, with a deterministic background color and optional status dot. */\nimport { computed } from 'vue'\n\ninterface Props {\n name?: string\n initials?: string\n src?: string\n alt?: string\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n color?: string\n status?: 'online' | 'away' | 'busy' | 'offline'\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n alt: '',\n size: 'md',\n})\n\nconst PALETTE = ['#3B82F6', '#8B5CF6', '#EC4899', '#F97316', '#10B981', '#F59E0B', '#06B6D4', '#6366F1']\n\n// Default: first letter of `name`, uppercased. Consumers wanting two letters\n// (e.g. role badges like \"PI\", \"QC\") pass `:initials=\"'XX'\"` explicitly.\nconst computedInitials = computed(() =>\n props.initials || props.name?.charAt(0).toUpperCase() || ''\n)\n\nconst backgroundColor = computed(() => {\n if (props.color) return props.color\n if (!props.name) return undefined\n\n let hash = 0\n for (let i = 0; i < props.name.length; i++) {\n hash = props.name.charCodeAt(i) + ((hash << 5) - hash)\n }\n return PALETTE[Math.abs(hash) % PALETTE.length]\n})\n</script>\n\n<template>\n <span\n :class=\"['mint-avatar', `mint-avatar--${size}`]\"\n role=\"img\"\n :aria-label=\"alt || name || 'User avatar'\"\n >\n <span\n class=\"mint-avatar__face\"\n :style=\"backgroundColor ? { backgroundColor } : undefined\"\n >\n <img\n v-if=\"src\"\n :src=\"src\"\n :alt=\"alt || name || ''\"\n class=\"mint-avatar__image\"\n >\n <span v-else-if=\"computedInitials\" class=\"mint-avatar__initials\">\n {{ computedInitials }}\n </span>\n <svg\n v-else\n class=\"mint-avatar__fallback\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <path d=\"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z\" />\n </svg>\n </span>\n <span\n v-if=\"status\"\n :class=\"['mint-avatar__status', `mint-avatar__status--${status}`]\"\n aria-hidden=\"true\"\n />\n </span>\n</template>\n","<script setup lang=\"ts\">\n/** Displays a user avatar as an image, a single derived initial, or a fallback icon, with a deterministic background color and optional status dot. */\nimport { computed } from 'vue'\n\ninterface Props {\n name?: string\n initials?: string\n src?: string\n alt?: string\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n color?: string\n status?: 'online' | 'away' | 'busy' | 'offline'\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n alt: '',\n size: 'md',\n})\n\nconst PALETTE = ['#3B82F6', '#8B5CF6', '#EC4899', '#F97316', '#10B981', '#F59E0B', '#06B6D4', '#6366F1']\n\n// Default: first letter of `name`, uppercased. Consumers wanting two letters\n// (e.g. role badges like \"PI\", \"QC\") pass `:initials=\"'XX'\"` explicitly.\nconst computedInitials = computed(() =>\n props.initials || props.name?.charAt(0).toUpperCase() || ''\n)\n\nconst backgroundColor = computed(() => {\n if (props.color) return props.color\n if (!props.name) return undefined\n\n let hash = 0\n for (let i = 0; i < props.name.length; i++) {\n hash = props.name.charCodeAt(i) + ((hash << 5) - hash)\n }\n return PALETTE[Math.abs(hash) % PALETTE.length]\n})\n</script>\n\n<template>\n <span\n :class=\"['mint-avatar', `mint-avatar--${size}`]\"\n role=\"img\"\n :aria-label=\"alt || name || 'User avatar'\"\n >\n <span\n class=\"mint-avatar__face\"\n :style=\"backgroundColor ? { backgroundColor } : undefined\"\n >\n <img\n v-if=\"src\"\n :src=\"src\"\n :alt=\"alt || name || ''\"\n class=\"mint-avatar__image\"\n >\n <span v-else-if=\"computedInitials\" class=\"mint-avatar__initials\">\n {{ computedInitials }}\n </span>\n <svg\n v-else\n class=\"mint-avatar__fallback\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <path d=\"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z\" />\n </svg>\n </span>\n <span\n v-if=\"status\"\n :class=\"['mint-avatar__status', `mint-avatar__status--${status}`]\"\n aria-hidden=\"true\"\n />\n </span>\n</template>\n","import type {\n FormFieldSchema,\n FormFieldType,\n FormSchema,\n} from '../types/form-builder'\nimport type {\n GeneratedJsonSchema,\n GeneratedJobDefinition,\n} from '../types/generated-ui'\n\ntype GeneratedReference = 'path'\n\ninterface ResolvedGeneratedField {\n schema: GeneratedJsonSchema\n reference?: GeneratedReference\n hasDefault: boolean\n defaultValue?: unknown\n}\n\nexport function generatedJobFormSchema(definition: GeneratedJobDefinition): FormSchema & { sections: NonNullable<FormSchema['sections']> } {\n const root = definition.input_schema\n const required = new Set(root.required ?? [])\n const fields = Object.entries(root.properties ?? {}).map(([name, schema]) =>\n toFormField(name, resolveGeneratedField(root, schema), required.has(name)),\n )\n return {\n sections: [{\n id: definition.id,\n title: definition.title,\n description: definition.description || undefined,\n columns: 1,\n fields,\n }],\n actions: true,\n submitLabel: 'Run analysis',\n }\n}\n\nexport function generatedJobDefaults(definition: GeneratedJobDefinition): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(definition.input_schema.properties ?? {})\n .map(([name, schema]) => [name, resolveGeneratedField(definition.input_schema, schema)] as const)\n .filter(([, field]) => field.hasDefault)\n .map(([name, field]) => [name, structuredClone(field.defaultValue)]),\n )\n}\n\nexport function normalizeGeneratedJobInput(\n definition: GeneratedJobDefinition,\n values: Record<string, unknown>,\n): Record<string, unknown> {\n const normalized: Record<string, unknown> = {}\n for (const [name, value] of Object.entries(values)) {\n const field = definition.input_schema.properties?.[name]\n if (!field) continue\n const { schema, reference } = resolveGeneratedField(definition.input_schema, field)\n if (reference !== 'path' && Array.isArray(value) && ['integer', 'number'].includes(String(schema.items?.type))) {\n normalized[name] = value.map(item => {\n const numeric = typeof item === 'string' && item.trim() !== '' ? Number(item) : item\n return typeof numeric === 'number' && Number.isFinite(numeric) ? numeric : item\n })\n } else if (reference !== 'path' && Array.isArray(value) && schema.items?.type === 'boolean') {\n normalized[name] = value.map(item => item === 'true' ? true : item === 'false' ? false : item)\n } else {\n normalized[name] = value === undefined && allowsNull(schema) ? null : value\n }\n }\n return normalized\n}\n\nfunction toFormField(\n name: string,\n resolved: ResolvedGeneratedField,\n required: boolean,\n): FormFieldSchema {\n const { schema, reference } = resolved\n const validation: NonNullable<FormFieldSchema['validation']> = {}\n const allowsEmpty = schema.type === 'array' || (\n schema.type === 'string' && reference !== 'path'\n && !(schema.minLength && schema.minLength > 0)\n && (!schema.enum || schema.enum.includes(''))\n )\n if (required && !allowsNull(schema) && !allowsEmpty) validation.required = true\n if (schema.minimum !== undefined) validation.min = schema.minimum\n if (schema.maximum !== undefined) validation.max = schema.maximum\n if (schema.minLength !== undefined) validation.minLength = schema.minLength\n if (schema.maxLength !== undefined) validation.maxLength = schema.maxLength\n\n const props: Record<string, unknown> = {}\n if (schema.enum) props.options = [...schema.enum]\n if (schema.type === 'integer') {\n if (schema.exclusiveMinimum !== undefined) validation.min = Math.max(Number(validation.min ?? -Infinity), Math.floor(schema.exclusiveMinimum) + 1)\n if (schema.exclusiveMaximum !== undefined) validation.max = Math.min(Number(validation.max ?? Infinity), Math.ceil(schema.exclusiveMaximum) - 1)\n if (validation.min !== undefined) validation.min = Math.ceil(Number(validation.min))\n if (validation.max !== undefined) validation.max = Math.floor(Number(validation.max))\n if (schema.multipleOf && Number.isInteger(schema.multipleOf)) {\n if (validation.min !== undefined) validation.min = Math.ceil(Number(validation.min) / schema.multipleOf) * schema.multipleOf\n if (validation.max !== undefined) validation.max = Math.floor(Number(validation.max) / schema.multipleOf) * schema.multipleOf\n }\n props.step = 1\n }\n if (schema.type === 'integer' || schema.type === 'number') {\n if (validation.min !== undefined) props.min = validation.min\n if (validation.max !== undefined) props.max = validation.max\n if (schema.multipleOf !== undefined) props.step = schema.multipleOf\n }\n if (schema.type === 'array' && reference !== 'path') {\n if (schema.items?.enum) props.options = [...schema.items.enum]\n else props.allowDuplicates = true\n }\n if (reference === 'path' && schema.type === 'array') props.multiple = true\n return {\n name,\n label: schema.title || humanize(name),\n type: fieldType(schema, reference),\n defaultValue: resolved.hasDefault ? structuredClone(resolved.defaultValue) : undefined,\n disabled: Object.prototype.hasOwnProperty.call(schema, 'const') || undefined,\n hint: schema.description,\n validation,\n props,\n itemType: schema.items?.type === 'number' || schema.items?.type === 'integer' ? 'number' : undefined,\n }\n}\n\nfunction resolveGeneratedField(\n root: GeneratedJsonSchema,\n field: GeneratedJsonSchema,\n): ResolvedGeneratedField {\n const candidate = field.anyOf?.find(item => item.type !== 'null')\n ?? field.allOf?.[0]\n ?? field\n let schema = { ...candidate, ...field }\n if (candidate.$ref) {\n const referenceParts = candidate.$ref.split('/')\n const key = referenceParts[referenceParts.length - 1]\n const referenced = key ? root.$defs?.[key] : undefined\n if (!referenced) throw new Error(`Generated field reference is missing: ${candidate.$ref}`)\n schema = { ...referenced, ...candidate, ...field }\n }\n if (schema.items) schema.items = resolveGeneratedField(root, schema.items).schema\n const constant = Object.prototype.hasOwnProperty.call(schema, 'const')\n return {\n schema,\n reference: schema['x-mint-component'],\n hasDefault: constant || hasOwnDefault(field) || allowsNull(schema),\n defaultValue: constant ? schema.const : hasOwnDefault(field) ? field.default : null,\n }\n}\n\nfunction fieldType(schema: GeneratedJsonSchema, reference?: GeneratedReference): FormFieldType {\n if (reference === 'path') return 'path'\n if (schema.enum) return 'select'\n const type = Array.isArray(schema.type) ? schema.type.find(value => value !== 'null') : schema.type\n if (type === 'boolean') return 'toggle'\n if (type === 'number' || type === 'integer') return 'number'\n if (type === 'array') return schema.items?.enum ? 'multiselect' : 'tags'\n return 'text'\n}\n\nfunction hasOwnDefault(schema: GeneratedJsonSchema): boolean {\n return Object.prototype.hasOwnProperty.call(schema, 'default')\n}\n\nfunction allowsNull(schema: GeneratedJsonSchema): boolean {\n return schema.type === 'null' || (Array.isArray(schema.type) && schema.type.includes('null'))\n || !!schema.anyOf?.some(item => item.type === 'null')\n}\n\nfunction humanize(value: string): string {\n return value.replace(/[_-]+/g, ' ').replace(/^\\w/, character => character.toUpperCase())\n}\n","<script setup lang=\"ts\">\n/**\n * Standard generated workspace for a plugin that exposes an SDK job manifest.\n *\n * @example Recommended\n * ```vue\n * <GeneratedPluginView base-url=\"/api/peak-qc\" />\n * ```\n */\nimport { computed, onMounted, provide, reactive, ref, watch } from 'vue'\n\nimport { generatedJobDefaults, generatedJobFormSchema, normalizeGeneratedJobInput } from '../generated/schema'\nimport type { FormSchema } from '../types/form-builder'\nimport type {\n GeneratedAnalysisJob,\n GeneratedAnalysisResult,\n GeneratedJobDefinition,\n} from '../types/generated-ui'\nimport type { PillNavItem, SidebarToolSection } from '../types'\nimport {\n useJobsEndpoint,\n type GeneratedAnalysisTransport,\n} from '../composables/useJobsEndpoint'\nimport AlertBox from './AlertBox.vue'\nimport EmptyState from './EmptyState.vue'\nimport GeneratedResultRenderer from './GeneratedResultRenderer.vue'\nimport JobsStatusTray from './JobsStatusTray.vue'\nimport LoadingSpinner from './LoadingSpinner.vue'\nimport PluginWorkspaceView from './PluginWorkspaceView.vue'\nimport { GENERATED_JOBS_API_KEY } from './internal/generatedJobsApi'\nimport { definePluginWorkspaceView } from '../composables/componentSpecs'\n\ninterface Props {\n baseUrl: string\n showStandaloneLabel?: boolean\n transport?: GeneratedAnalysisTransport\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n showStandaloneLabel: false,\n})\n\nconst generated = useJobsEndpoint({\n baseUrl: props.baseUrl,\n transport: props.transport,\n manifest: true,\n})\nprovide(GENERATED_JOBS_API_KEY, { baseUrl: props.baseUrl, transport: props.transport })\nconst activeDefinitionId = ref('')\nconst selectedJobId = ref('')\nconst valuesByDefinition = reactive<Record<string, Record<string, unknown>>>({})\nconst definitions = computed(() => generated.manifest.value?.jobs ?? [])\nconst activeDefinition = computed(() => (\n definitions.value.find(definition => definition.id === activeDefinitionId.value) ?? null\n))\n\nconst pillNav = computed<PillNavItem[]>(() => definitions.value.map(definition => ({\n id: definition.id,\n label: definition.title,\n})))\n\nconst panels = computed<Record<string, SidebarToolSection[]>>(() => Object.fromEntries(\n definitions.value.map(definition => [definition.id, [{\n id: definition.id,\n label: 'Parameters',\n subtitle: resourceSummary(definition),\n defaultOpen: true,\n }]]),\n))\n\nconst forms = computed<Record<string, FormSchema>>(() => Object.fromEntries(\n definitions.value.map(definition => [definition.id, generatedJobFormSchema(definition)]),\n))\n\nconst workspace = computed(() => definePluginWorkspaceView({\n title: generated.manifest.value?.ui.title ?? 'Analysis',\n subtitle: generated.manifest.value?.ui.description,\n // The platform shell renders the toasts around this view.\n toasts: false,\n topBar: {\n pills: pillNav.value,\n settings: false,\n standaloneLabel: props.showStandaloneLabel ? 'Standalone' : false,\n },\n sidebar: { title: 'Parameters', panels: panels.value, forms: forms.value },\n}))\n\nconst currentValues = computed(() => valuesByDefinition[activeDefinitionId.value] ?? {})\nconst currentJob = computed(() => {\n const currentSessionId = generated.session.value?.id\n const currentDefinitionId = activeDefinitionId.value\n const selected = generated.jobs.value.find(candidate => (\n candidate.job_id === selectedJobId.value\n && candidate.status === 'completed'\n && candidate.metadata.definition_id === currentDefinitionId\n && candidate.metadata.has_result === true\n ))\n return selected ?? generated.jobs.value.find(candidate => (\n candidate.session_id === currentSessionId\n && candidate.status === 'completed'\n && candidate.metadata.definition_id === currentDefinitionId\n && candidate.metadata.has_result === true\n ))\n})\nconst currentResult = computed<GeneratedAnalysisResult | null>(() => (\n currentJob.value ? generated.resultForJob(currentJob.value.job_id) : null\n))\n\nwatch(definitions, (nextDefinitions) => {\n for (const definition of nextDefinitions) {\n valuesByDefinition[definition.id] ??= generatedJobDefaults(definition)\n }\n if (!nextDefinitions.some(definition => definition.id === activeDefinitionId.value)) {\n activeDefinitionId.value = nextDefinitions[0]?.id ?? ''\n }\n}, { immediate: true })\n\nwatch(currentJob, (job) => {\n if (job) void generated.result(job)\n}, { immediate: true })\n\nfunction updateValues(values: Record<string, unknown>): void {\n if (activeDefinitionId.value) valuesByDefinition[activeDefinitionId.value] = { ...values }\n}\n\nasync function submitJob(sectionId: string, values: Record<string, unknown>): Promise<void> {\n const definition = definitions.value.find(candidate => candidate.id === sectionId)\n if (!definition) return\n selectedJobId.value = ''\n valuesByDefinition[definition.id] = { ...values }\n await generated.submit(definition.id, normalizeGeneratedJobInput(definition, values))\n}\n\nfunction selectJob(job: GeneratedAnalysisJob): void {\n selectedJobId.value = job.job_id\n activeDefinitionId.value = String(job.metadata.definition_id ?? activeDefinitionId.value)\n}\n\nfunction resourceSummary(definition: GeneratedJobDefinition): string {\n if (definition.lifecycle === 'service' || definition.profile?.kind === 'service') {\n return 'Host service'\n }\n if (definition.lifecycle === 'staged' || definition.profile?.kind === 'staged') {\n return 'Staged upload'\n }\n return `Up to ${definition.cpu} CPU`\n}\n\nonMounted(() => {\n void generated.refresh().catch(() => undefined)\n})\n</script>\n\n<template>\n <PluginWorkspaceView\n v-model:view=\"activeDefinitionId\"\n :spec=\"workspace\"\n :values=\"currentValues\"\n :form-loading=\"generated.isSubmitting.value\"\n :form-disabled=\"generated.isSubmitting.value\"\n @update:values=\"updateValues\"\n @form-submit=\"submitJob\"\n >\n <main class=\"mint-generated-workspace\">\n <div v-if=\"generated.isLoading.value\" class=\"mint-generated-workspace__loading\">\n <LoadingSpinner size=\"lg\" />\n <span>Loading analysis workspace</span>\n </div>\n\n <template v-else>\n <AlertBox v-if=\"generated.error.value\" tone=\"error\">{{ generated.error.value }}</AlertBox>\n\n <header v-if=\"activeDefinition\" class=\"mint-generated-workspace__header\">\n <div>\n <p class=\"mint-generated-workspace__eyebrow\">Analysis result</p>\n <h1>{{ activeDefinition.title }}</h1>\n <p v-if=\"activeDefinition.description\">{{ activeDefinition.description }}</p>\n </div>\n <div class=\"mint-generated-workspace__resources\" aria-label=\"Job resource requirements\">\n <span>{{ resourceSummary(activeDefinition) }}</span>\n </div>\n </header>\n\n <section class=\"mint-generated-workspace__result\">\n <GeneratedResultRenderer\n v-if=\"currentResult\"\n :result=\"currentResult\"\n />\n <EmptyState\n v-else\n title=\"No result yet\"\n description=\"Set the parameters and run the analysis. Jobs continue independently if you switch tabs.\"\n size=\"md\"\n />\n </section>\n </template>\n\n <JobsStatusTray\n :source=\"generated\"\n :teleport-to=\"false\"\n @select=\"selectJob\"\n />\n </main>\n </PluginWorkspaceView>\n</template>\n\n<style scoped>\n.mint-generated-workspace {\n position: relative;\n min-width: 0;\n min-height: calc(100vh - 5rem);\n padding: clamp(1rem, 2.5vw, 2.5rem);\n background: var(--bg-primary);\n}\n\n.mint-generated-workspace__loading {\n display: flex;\n min-height: 24rem;\n align-items: center;\n justify-content: center;\n gap: 0.75rem;\n color: var(--text-secondary);\n}\n\n.mint-generated-workspace__header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 1.5rem;\n max-width: 76rem;\n margin: 0 auto 1.25rem;\n}\n\n.mint-generated-workspace__header h1 {\n margin: 0;\n color: var(--text-primary);\n font-size: clamp(1.35rem, 2vw, 1.8rem);\n line-height: 1.2;\n}\n\n.mint-generated-workspace__header p:not(.mint-generated-workspace__eyebrow) {\n margin: 0.4rem 0 0;\n color: var(--text-secondary);\n}\n\n.mint-generated-workspace__eyebrow {\n margin: 0 0 0.35rem;\n color: var(--text-secondary);\n font-size: 0.72rem;\n font-weight: 700;\n}\n\n.mint-generated-workspace__resources {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: 0.4rem;\n}\n\n.mint-generated-workspace__resources span {\n padding: 0.3rem 0.55rem;\n border: 1px solid var(--border-color);\n border-radius: 999px;\n background: var(--bg-secondary);\n color: var(--text-secondary);\n font-size: 0.75rem;\n font-weight: 600;\n}\n\n.mint-generated-workspace__result {\n max-width: 76rem;\n min-height: 24rem;\n margin: 0 auto;\n padding: clamp(1rem, 2vw, 1.75rem);\n border: 1px solid var(--border-color);\n border-radius: 1rem;\n background: var(--bg-secondary);\n box-shadow: var(--shadow-sm);\n}\n\n@media (max-width: 640px) {\n .mint-generated-workspace__header {\n flex-direction: column;\n }\n\n .mint-generated-workspace__resources {\n justify-content: flex-start;\n }\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * Standard generated workspace for a plugin that exposes an SDK job manifest.\n *\n * @example Recommended\n * ```vue\n * <GeneratedPluginView base-url=\"/api/peak-qc\" />\n * ```\n */\nimport { computed, onMounted, provide, reactive, ref, watch } from 'vue'\n\nimport { generatedJobDefaults, generatedJobFormSchema, normalizeGeneratedJobInput } from '../generated/schema'\nimport type { FormSchema } from '../types/form-builder'\nimport type {\n GeneratedAnalysisJob,\n GeneratedAnalysisResult,\n GeneratedJobDefinition,\n} from '../types/generated-ui'\nimport type { PillNavItem, SidebarToolSection } from '../types'\nimport {\n useJobsEndpoint,\n type GeneratedAnalysisTransport,\n} from '../composables/useJobsEndpoint'\nimport AlertBox from './AlertBox.vue'\nimport EmptyState from './EmptyState.vue'\nimport GeneratedResultRenderer from './GeneratedResultRenderer.vue'\nimport JobsStatusTray from './JobsStatusTray.vue'\nimport LoadingSpinner from './LoadingSpinner.vue'\nimport PluginWorkspaceView from './PluginWorkspaceView.vue'\nimport { GENERATED_JOBS_API_KEY } from './internal/generatedJobsApi'\nimport { definePluginWorkspaceView } from '../composables/componentSpecs'\n\ninterface Props {\n baseUrl: string\n showStandaloneLabel?: boolean\n transport?: GeneratedAnalysisTransport\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n showStandaloneLabel: false,\n})\n\nconst generated = useJobsEndpoint({\n baseUrl: props.baseUrl,\n transport: props.transport,\n manifest: true,\n})\nprovide(GENERATED_JOBS_API_KEY, { baseUrl: props.baseUrl, transport: props.transport })\nconst activeDefinitionId = ref('')\nconst selectedJobId = ref('')\nconst valuesByDefinition = reactive<Record<string, Record<string, unknown>>>({})\nconst definitions = computed(() => generated.manifest.value?.jobs ?? [])\nconst activeDefinition = computed(() => (\n definitions.value.find(definition => definition.id === activeDefinitionId.value) ?? null\n))\n\nconst pillNav = computed<PillNavItem[]>(() => definitions.value.map(definition => ({\n id: definition.id,\n label: definition.title,\n})))\n\nconst panels = computed<Record<string, SidebarToolSection[]>>(() => Object.fromEntries(\n definitions.value.map(definition => [definition.id, [{\n id: definition.id,\n label: 'Parameters',\n subtitle: resourceSummary(definition),\n defaultOpen: true,\n }]]),\n))\n\nconst forms = computed<Record<string, FormSchema>>(() => Object.fromEntries(\n definitions.value.map(definition => [definition.id, generatedJobFormSchema(definition)]),\n))\n\nconst workspace = computed(() => definePluginWorkspaceView({\n title: generated.manifest.value?.ui.title ?? 'Analysis',\n subtitle: generated.manifest.value?.ui.description,\n // The platform shell renders the toasts around this view.\n toasts: false,\n topBar: {\n pills: pillNav.value,\n settings: false,\n standaloneLabel: props.showStandaloneLabel ? 'Standalone' : false,\n },\n sidebar: { title: 'Parameters', panels: panels.value, forms: forms.value },\n}))\n\nconst currentValues = computed(() => valuesByDefinition[activeDefinitionId.value] ?? {})\nconst currentJob = computed(() => {\n const currentSessionId = generated.session.value?.id\n const currentDefinitionId = activeDefinitionId.value\n const selected = generated.jobs.value.find(candidate => (\n candidate.job_id === selectedJobId.value\n && candidate.status === 'completed'\n && candidate.metadata.definition_id === currentDefinitionId\n && candidate.metadata.has_result === true\n ))\n return selected ?? generated.jobs.value.find(candidate => (\n candidate.session_id === currentSessionId\n && candidate.status === 'completed'\n && candidate.metadata.definition_id === currentDefinitionId\n && candidate.metadata.has_result === true\n ))\n})\nconst currentResult = computed<GeneratedAnalysisResult | null>(() => (\n currentJob.value ? generated.resultForJob(currentJob.value.job_id) : null\n))\n\nwatch(definitions, (nextDefinitions) => {\n for (const definition of nextDefinitions) {\n valuesByDefinition[definition.id] ??= generatedJobDefaults(definition)\n }\n if (!nextDefinitions.some(definition => definition.id === activeDefinitionId.value)) {\n activeDefinitionId.value = nextDefinitions[0]?.id ?? ''\n }\n}, { immediate: true })\n\nwatch(currentJob, (job) => {\n if (job) void generated.result(job)\n}, { immediate: true })\n\nfunction updateValues(values: Record<string, unknown>): void {\n if (activeDefinitionId.value) valuesByDefinition[activeDefinitionId.value] = { ...values }\n}\n\nasync function submitJob(sectionId: string, values: Record<string, unknown>): Promise<void> {\n const definition = definitions.value.find(candidate => candidate.id === sectionId)\n if (!definition) return\n selectedJobId.value = ''\n valuesByDefinition[definition.id] = { ...values }\n await generated.submit(definition.id, normalizeGeneratedJobInput(definition, values))\n}\n\nfunction selectJob(job: GeneratedAnalysisJob): void {\n selectedJobId.value = job.job_id\n activeDefinitionId.value = String(job.metadata.definition_id ?? activeDefinitionId.value)\n}\n\nfunction resourceSummary(definition: GeneratedJobDefinition): string {\n if (definition.lifecycle === 'service' || definition.profile?.kind === 'service') {\n return 'Host service'\n }\n if (definition.lifecycle === 'staged' || definition.profile?.kind === 'staged') {\n return 'Staged upload'\n }\n return `Up to ${definition.cpu} CPU`\n}\n\nonMounted(() => {\n void generated.refresh().catch(() => undefined)\n})\n</script>\n\n<template>\n <PluginWorkspaceView\n v-model:view=\"activeDefinitionId\"\n :spec=\"workspace\"\n :values=\"currentValues\"\n :form-loading=\"generated.isSubmitting.value\"\n :form-disabled=\"generated.isSubmitting.value\"\n @update:values=\"updateValues\"\n @form-submit=\"submitJob\"\n >\n <main class=\"mint-generated-workspace\">\n <div v-if=\"generated.isLoading.value\" class=\"mint-generated-workspace__loading\">\n <LoadingSpinner size=\"lg\" />\n <span>Loading analysis workspace</span>\n </div>\n\n <template v-else>\n <AlertBox v-if=\"generated.error.value\" tone=\"error\">{{ generated.error.value }}</AlertBox>\n\n <header v-if=\"activeDefinition\" class=\"mint-generated-workspace__header\">\n <div>\n <p class=\"mint-generated-workspace__eyebrow\">Analysis result</p>\n <h1>{{ activeDefinition.title }}</h1>\n <p v-if=\"activeDefinition.description\">{{ activeDefinition.description }}</p>\n </div>\n <div class=\"mint-generated-workspace__resources\" aria-label=\"Job resource requirements\">\n <span>{{ resourceSummary(activeDefinition) }}</span>\n </div>\n </header>\n\n <section class=\"mint-generated-workspace__result\">\n <GeneratedResultRenderer\n v-if=\"currentResult\"\n :result=\"currentResult\"\n />\n <EmptyState\n v-else\n title=\"No result yet\"\n description=\"Set the parameters and run the analysis. Jobs continue independently if you switch tabs.\"\n size=\"md\"\n />\n </section>\n </template>\n\n <JobsStatusTray\n :source=\"generated\"\n :teleport-to=\"false\"\n @select=\"selectJob\"\n />\n </main>\n </PluginWorkspaceView>\n</template>\n\n<style scoped>\n.mint-generated-workspace {\n position: relative;\n min-width: 0;\n min-height: calc(100vh - 5rem);\n padding: clamp(1rem, 2.5vw, 2.5rem);\n background: var(--bg-primary);\n}\n\n.mint-generated-workspace__loading {\n display: flex;\n min-height: 24rem;\n align-items: center;\n justify-content: center;\n gap: 0.75rem;\n color: var(--text-secondary);\n}\n\n.mint-generated-workspace__header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 1.5rem;\n max-width: 76rem;\n margin: 0 auto 1.25rem;\n}\n\n.mint-generated-workspace__header h1 {\n margin: 0;\n color: var(--text-primary);\n font-size: clamp(1.35rem, 2vw, 1.8rem);\n line-height: 1.2;\n}\n\n.mint-generated-workspace__header p:not(.mint-generated-workspace__eyebrow) {\n margin: 0.4rem 0 0;\n color: var(--text-secondary);\n}\n\n.mint-generated-workspace__eyebrow {\n margin: 0 0 0.35rem;\n color: var(--text-secondary);\n font-size: 0.72rem;\n font-weight: 700;\n}\n\n.mint-generated-workspace__resources {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: 0.4rem;\n}\n\n.mint-generated-workspace__resources span {\n padding: 0.3rem 0.55rem;\n border: 1px solid var(--border-color);\n border-radius: 999px;\n background: var(--bg-secondary);\n color: var(--text-secondary);\n font-size: 0.75rem;\n font-weight: 600;\n}\n\n.mint-generated-workspace__result {\n max-width: 76rem;\n min-height: 24rem;\n margin: 0 auto;\n padding: clamp(1rem, 2vw, 1.75rem);\n border: 1px solid var(--border-color);\n border-radius: 1rem;\n background: var(--bg-secondary);\n box-shadow: var(--shadow-sm);\n}\n\n@media (max-width: 640px) {\n .mint-generated-workspace__header {\n flex-direction: column;\n }\n\n .mint-generated-workspace__resources {\n justify-content: flex-start;\n }\n}\n</style>\n","<script setup lang=\"ts\">\n/** PlateEditor holding its own copy of the plates (useRackEditor), for ComponentBindingRenderer bindings. */\nimport { watch } from 'vue'\nimport type { PlateEditorSpec, Rack } from '../../types'\nimport { useRackEditor } from '../../composables/useRackEditor'\nimport PlateEditor from '../PlateEditor.vue'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = defineProps<{\n modelValue: Rack[]\n activeRack?: string\n spec?: PlateEditorSpec\n}>()\n\nconst editor = useRackEditor(props.modelValue)\nconst { racks, activeRackId, plateEditorListeners, canUndo, canRedo } = editor\n// A new binding (template reloaded) replaces the local copy and its history, then reselects: the\n// activeRack watch may have run first, before its rack existed.\nwatch(() => props.modelValue, (next) => {\n racks.value = next.map(rack => ({ ...rack, wells: { ...rack.wells } }))\n editor.clearHistory()\n if (props.activeRack) editor.setActiveRack(props.activeRack)\n})\nwatch(() => props.activeRack, (id) => { if (id) editor.setActiveRack(id) }, { immediate: true })\n</script>\n\n<template>\n <PlateEditor\n v-bind=\"$attrs\"\n :spec=\"{ history: true, ...spec }\"\n :model-value=\"racks\"\n :active-rack=\"activeRackId\"\n :can-undo=\"canUndo\"\n :can-redo=\"canRedo\"\n v-on=\"plateEditorListeners\"\n />\n</template>\n","<script setup lang=\"ts\">\n/** PlateEditor holding its own copy of the plates (useRackEditor), for ComponentBindingRenderer bindings. */\nimport { watch } from 'vue'\nimport type { PlateEditorSpec, Rack } from '../../types'\nimport { useRackEditor } from '../../composables/useRackEditor'\nimport PlateEditor from '../PlateEditor.vue'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = defineProps<{\n modelValue: Rack[]\n activeRack?: string\n spec?: PlateEditorSpec\n}>()\n\nconst editor = useRackEditor(props.modelValue)\nconst { racks, activeRackId, plateEditorListeners, canUndo, canRedo } = editor\n// A new binding (template reloaded) replaces the local copy and its history, then reselects: the\n// activeRack watch may have run first, before its rack existed.\nwatch(() => props.modelValue, (next) => {\n racks.value = next.map(rack => ({ ...rack, wells: { ...rack.wells } }))\n editor.clearHistory()\n if (props.activeRack) editor.setActiveRack(props.activeRack)\n})\nwatch(() => props.activeRack, (id) => { if (id) editor.setActiveRack(id) }, { immediate: true })\n</script>\n\n<template>\n <PlateEditor\n v-bind=\"$attrs\"\n :spec=\"{ history: true, ...spec }\"\n :model-value=\"racks\"\n :active-rack=\"activeRackId\"\n :can-undo=\"canUndo\"\n :can-redo=\"canRedo\"\n v-on=\"plateEditorListeners\"\n />\n</template>\n","<script setup lang=\"ts\">\n/**\n * Render generated SDK component bindings such as WellPlate, DoseCalculator, DataFrame, and PlateEditor.\n *\n * @example Recommended\n * ```vue\n * <ComponentBindingRenderer :bindings=\"workspace.componentBindings.value\" />\n * ```\n */\nimport { computed, type Component } from 'vue'\nimport DataFrame from './DataFrame.vue'\nimport DoseCalculator from './DoseCalculator.vue'\nimport PlateEditorBindingInternal from './internal/PlateEditorBindingInternal.vue'\nimport ScheduleCalendar from './ScheduleCalendar.vue'\nimport WellPlate from './WellPlate.vue'\nimport { isRecord } from '../utils/records'\n\nexport interface ComponentBindingRendererBinding {\n id?: string\n component: string\n props?: Record<string, unknown> | readonly string[]\n propsObject?: Record<string, unknown>\n description?: string\n}\n\ntype ComponentBindingRendererLayout = 'grid' | 'stack'\n\ninterface Props {\n /** Single generated SDK component binding to render. */\n binding?: ComponentBindingRendererBinding\n /** Generated SDK component bindings to render. */\n bindings?: ComponentBindingRendererBinding[]\n /** Optional allow-list of component names, for example ['WellPlate', 'DataFrame']. */\n include?: string[]\n /** Optional deny-list of component names. */\n exclude?: string[]\n /** Compact child component sizing. */\n dense?: boolean\n /** Prefer preview-safe props for editable components. */\n readonly?: boolean\n /** Show component labels above each rendered component. */\n showHeaders?: boolean\n /** Show binding descriptions in each header. */\n showDescriptions?: boolean\n /** Grid or vertical stack layout. */\n layout?: ComponentBindingRendererLayout\n /** Message shown when no binding can be rendered. */\n emptyText?: string\n}\n\ntype RenderableBinding = ComponentBindingRendererBinding & {\n id: string\n componentImpl: Component\n normalizedProps: Record<string, unknown>\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n binding: undefined,\n bindings: () => [],\n include: () => [],\n exclude: () => [],\n dense: false,\n readonly: true,\n showHeaders: true,\n showDescriptions: true,\n layout: 'grid',\n emptyText: 'No renderable SDK component bindings.',\n})\n\nconst componentRegistry: Record<string, Component> = {\n DataFrame,\n DoseCalculator,\n // Holds its own copy of the plates: PlateEditor itself is controlled.\n PlateEditor: PlateEditorBindingInternal,\n ScheduleCalendar,\n WellPlate,\n}\n\nconst inputBindings = computed<ComponentBindingRendererBinding[]>(() => [\n ...(props.binding ? [props.binding] : []),\n ...props.bindings,\n])\n\nconst renderableBindings = computed<RenderableBinding[]>(() =>\n inputBindings.value\n .filter(binding => isIncluded(binding.component))\n .map((binding, index) => {\n const componentImpl = componentRegistry[binding.component]\n if (!componentImpl) return null\n return {\n ...binding,\n id: binding.id ?? `${binding.component}-${index + 1}`,\n componentImpl,\n normalizedProps: normalizeProps(binding),\n }\n })\n .filter((binding): binding is RenderableBinding => binding !== null)\n)\n\nconst rendererClasses = computed(() => [\n 'mint-component-binding-renderer',\n `mint-component-binding-renderer--${props.layout}`,\n props.dense ? 'mint-component-binding-renderer--dense' : '',\n])\n\nfunction isIncluded(componentName: string): boolean {\n if (props.include.length > 0 && !props.include.includes(componentName)) return false\n return !props.exclude.includes(componentName)\n}\n\nfunction baseProps(binding: ComponentBindingRendererBinding): Record<string, unknown> {\n if (binding.propsObject) return { ...binding.propsObject }\n if (isRecord(binding.props)) return { ...binding.props }\n return {}\n}\n\nfunction normalizeProps(binding: ComponentBindingRendererBinding): Record<string, unknown> {\n const base = baseProps(binding)\n\n switch (binding.component) {\n case 'WellPlate':\n case 'PlateEditor': {\n const spec = isRecord(base.spec) ? base.spec : {}\n return {\n ...base,\n spec: { ...spec, size: props.dense ? 'md' : (spec.size ?? 'fill') },\n readonly: props.readonly || Boolean(base.readonly),\n }\n }\n case 'DataFrame': {\n const spec = isRecord(base.spec) ? base.spec : {}\n return {\n ...base,\n spec: {\n ...spec,\n size: props.dense ? 'sm' : (spec.size ?? 'md'),\n maxHeight: spec.maxHeight ?? (props.dense ? '280px' : undefined),\n },\n }\n }\n case 'ScheduleCalendar':\n return {\n ...base,\n readonly: props.readonly || Boolean(base.readonly),\n showNavigation: props.dense ? false : (base.showNavigation ?? true),\n showViewToggle: props.dense ? false : (base.showViewToggle ?? true),\n }\n default:\n return base\n }\n}\n\n</script>\n\n<template>\n <div :class=\"rendererClasses\">\n <section\n v-for=\"renderableBinding in renderableBindings\"\n :key=\"renderableBinding.id\"\n class=\"mint-component-binding-renderer__item\"\n :data-component-binding-id=\"renderableBinding.id\"\n >\n <header\n v-if=\"showHeaders\"\n class=\"mint-component-binding-renderer__header\"\n >\n <div class=\"mint-component-binding-renderer__title-group\">\n <p class=\"mint-component-binding-renderer__component\">\n {{ renderableBinding.component }}\n </p>\n <p\n v-if=\"renderableBinding.id\"\n class=\"mint-component-binding-renderer__source\"\n >\n {{ renderableBinding.id }}\n </p>\n </div>\n <p\n v-if=\"showDescriptions && renderableBinding.description\"\n class=\"mint-component-binding-renderer__description\"\n >\n {{ renderableBinding.description }}\n </p>\n </header>\n\n <div class=\"mint-component-binding-renderer__body\">\n <component\n :is=\"renderableBinding.componentImpl\"\n v-bind=\"renderableBinding.normalizedProps\"\n />\n </div>\n </section>\n\n <p\n v-if=\"renderableBindings.length === 0\"\n class=\"mint-component-binding-renderer__empty\"\n >\n {{ emptyText }}\n </p>\n </div>\n</template>\n\n<style scoped>\n.mint-component-binding-renderer {\n display: grid;\n gap: 1rem;\n min-width: 0;\n}\n\n.mint-component-binding-renderer--grid {\n grid-template-columns: repeat(auto-fit, minmax(min(100%, 28rem), 1fr));\n}\n\n.mint-component-binding-renderer--stack {\n grid-template-columns: minmax(0, 1fr);\n}\n\n.mint-component-binding-renderer--dense {\n gap: 0.75rem;\n}\n\n.mint-component-binding-renderer__item {\n min-width: 0;\n overflow: hidden;\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 0.5rem;\n background: var(--bg-card, #ffffff);\n box-shadow: var(--shadow-sm, 0 1px 2px rgb(15 23 42 / 0.06));\n}\n\n.mint-component-binding-renderer__header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 1rem;\n padding: 0.75rem 1rem;\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n background: var(--bg-secondary, #f8fafc);\n}\n\n.mint-component-binding-renderer__title-group {\n min-width: 0;\n}\n\n.mint-component-binding-renderer__component {\n margin: 0;\n color: var(--text-primary, #0f172a);\n font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);\n font-size: 0.8125rem;\n font-weight: 600;\n}\n\n.mint-component-binding-renderer__source,\n.mint-component-binding-renderer__description,\n.mint-component-binding-renderer__empty {\n margin: 0;\n color: var(--text-secondary, #475569);\n font-size: 0.75rem;\n line-height: 1.4;\n}\n\n.mint-component-binding-renderer__description {\n max-width: 24rem;\n text-align: right;\n}\n\n.mint-component-binding-renderer__body {\n min-width: 0;\n padding: 1rem;\n}\n\n.mint-component-binding-renderer--dense .mint-component-binding-renderer__header,\n.mint-component-binding-renderer--dense .mint-component-binding-renderer__body {\n padding: 0.75rem;\n}\n\n.mint-component-binding-renderer__empty {\n padding: 1rem;\n border: 1px dashed var(--border-color, #e5e7eb);\n border-radius: 0.5rem;\n background: var(--bg-secondary, #f8fafc);\n text-align: center;\n}\n\n@media (max-width: 720px) {\n .mint-component-binding-renderer__header {\n display: block;\n }\n\n .mint-component-binding-renderer__description {\n max-width: none;\n margin-top: 0.25rem;\n text-align: left;\n }\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * Render generated SDK component bindings such as WellPlate, DoseCalculator, DataFrame, and PlateEditor.\n *\n * @example Recommended\n * ```vue\n * <ComponentBindingRenderer :bindings=\"workspace.componentBindings.value\" />\n * ```\n */\nimport { computed, type Component } from 'vue'\nimport DataFrame from './DataFrame.vue'\nimport DoseCalculator from './DoseCalculator.vue'\nimport PlateEditorBindingInternal from './internal/PlateEditorBindingInternal.vue'\nimport ScheduleCalendar from './ScheduleCalendar.vue'\nimport WellPlate from './WellPlate.vue'\nimport { isRecord } from '../utils/records'\n\nexport interface ComponentBindingRendererBinding {\n id?: string\n component: string\n props?: Record<string, unknown> | readonly string[]\n propsObject?: Record<string, unknown>\n description?: string\n}\n\ntype ComponentBindingRendererLayout = 'grid' | 'stack'\n\ninterface Props {\n /** Single generated SDK component binding to render. */\n binding?: ComponentBindingRendererBinding\n /** Generated SDK component bindings to render. */\n bindings?: ComponentBindingRendererBinding[]\n /** Optional allow-list of component names, for example ['WellPlate', 'DataFrame']. */\n include?: string[]\n /** Optional deny-list of component names. */\n exclude?: string[]\n /** Compact child component sizing. */\n dense?: boolean\n /** Prefer preview-safe props for editable components. */\n readonly?: boolean\n /** Show component labels above each rendered component. */\n showHeaders?: boolean\n /** Show binding descriptions in each header. */\n showDescriptions?: boolean\n /** Grid or vertical stack layout. */\n layout?: ComponentBindingRendererLayout\n /** Message shown when no binding can be rendered. */\n emptyText?: string\n}\n\ntype RenderableBinding = ComponentBindingRendererBinding & {\n id: string\n componentImpl: Component\n normalizedProps: Record<string, unknown>\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n binding: undefined,\n bindings: () => [],\n include: () => [],\n exclude: () => [],\n dense: false,\n readonly: true,\n showHeaders: true,\n showDescriptions: true,\n layout: 'grid',\n emptyText: 'No renderable SDK component bindings.',\n})\n\nconst componentRegistry: Record<string, Component> = {\n DataFrame,\n DoseCalculator,\n // Holds its own copy of the plates: PlateEditor itself is controlled.\n PlateEditor: PlateEditorBindingInternal,\n ScheduleCalendar,\n WellPlate,\n}\n\nconst inputBindings = computed<ComponentBindingRendererBinding[]>(() => [\n ...(props.binding ? [props.binding] : []),\n ...props.bindings,\n])\n\nconst renderableBindings = computed<RenderableBinding[]>(() =>\n inputBindings.value\n .filter(binding => isIncluded(binding.component))\n .map((binding, index) => {\n const componentImpl = componentRegistry[binding.component]\n if (!componentImpl) return null\n return {\n ...binding,\n id: binding.id ?? `${binding.component}-${index + 1}`,\n componentImpl,\n normalizedProps: normalizeProps(binding),\n }\n })\n .filter((binding): binding is RenderableBinding => binding !== null)\n)\n\nconst rendererClasses = computed(() => [\n 'mint-component-binding-renderer',\n `mint-component-binding-renderer--${props.layout}`,\n props.dense ? 'mint-component-binding-renderer--dense' : '',\n])\n\nfunction isIncluded(componentName: string): boolean {\n if (props.include.length > 0 && !props.include.includes(componentName)) return false\n return !props.exclude.includes(componentName)\n}\n\nfunction baseProps(binding: ComponentBindingRendererBinding): Record<string, unknown> {\n if (binding.propsObject) return { ...binding.propsObject }\n if (isRecord(binding.props)) return { ...binding.props }\n return {}\n}\n\nfunction normalizeProps(binding: ComponentBindingRendererBinding): Record<string, unknown> {\n const base = baseProps(binding)\n\n switch (binding.component) {\n case 'WellPlate':\n case 'PlateEditor': {\n const spec = isRecord(base.spec) ? base.spec : {}\n return {\n ...base,\n spec: { ...spec, size: props.dense ? 'md' : (spec.size ?? 'fill') },\n readonly: props.readonly || Boolean(base.readonly),\n }\n }\n case 'DataFrame': {\n const spec = isRecord(base.spec) ? base.spec : {}\n return {\n ...base,\n spec: {\n ...spec,\n size: props.dense ? 'sm' : (spec.size ?? 'md'),\n maxHeight: spec.maxHeight ?? (props.dense ? '280px' : undefined),\n },\n }\n }\n case 'ScheduleCalendar':\n return {\n ...base,\n readonly: props.readonly || Boolean(base.readonly),\n showNavigation: props.dense ? false : (base.showNavigation ?? true),\n showViewToggle: props.dense ? false : (base.showViewToggle ?? true),\n }\n default:\n return base\n }\n}\n\n</script>\n\n<template>\n <div :class=\"rendererClasses\">\n <section\n v-for=\"renderableBinding in renderableBindings\"\n :key=\"renderableBinding.id\"\n class=\"mint-component-binding-renderer__item\"\n :data-component-binding-id=\"renderableBinding.id\"\n >\n <header\n v-if=\"showHeaders\"\n class=\"mint-component-binding-renderer__header\"\n >\n <div class=\"mint-component-binding-renderer__title-group\">\n <p class=\"mint-component-binding-renderer__component\">\n {{ renderableBinding.component }}\n </p>\n <p\n v-if=\"renderableBinding.id\"\n class=\"mint-component-binding-renderer__source\"\n >\n {{ renderableBinding.id }}\n </p>\n </div>\n <p\n v-if=\"showDescriptions && renderableBinding.description\"\n class=\"mint-component-binding-renderer__description\"\n >\n {{ renderableBinding.description }}\n </p>\n </header>\n\n <div class=\"mint-component-binding-renderer__body\">\n <component\n :is=\"renderableBinding.componentImpl\"\n v-bind=\"renderableBinding.normalizedProps\"\n />\n </div>\n </section>\n\n <p\n v-if=\"renderableBindings.length === 0\"\n class=\"mint-component-binding-renderer__empty\"\n >\n {{ emptyText }}\n </p>\n </div>\n</template>\n\n<style scoped>\n.mint-component-binding-renderer {\n display: grid;\n gap: 1rem;\n min-width: 0;\n}\n\n.mint-component-binding-renderer--grid {\n grid-template-columns: repeat(auto-fit, minmax(min(100%, 28rem), 1fr));\n}\n\n.mint-component-binding-renderer--stack {\n grid-template-columns: minmax(0, 1fr);\n}\n\n.mint-component-binding-renderer--dense {\n gap: 0.75rem;\n}\n\n.mint-component-binding-renderer__item {\n min-width: 0;\n overflow: hidden;\n border: 1px solid var(--border-color, #e5e7eb);\n border-radius: 0.5rem;\n background: var(--bg-card, #ffffff);\n box-shadow: var(--shadow-sm, 0 1px 2px rgb(15 23 42 / 0.06));\n}\n\n.mint-component-binding-renderer__header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 1rem;\n padding: 0.75rem 1rem;\n border-bottom: 1px solid var(--border-color, #e5e7eb);\n background: var(--bg-secondary, #f8fafc);\n}\n\n.mint-component-binding-renderer__title-group {\n min-width: 0;\n}\n\n.mint-component-binding-renderer__component {\n margin: 0;\n color: var(--text-primary, #0f172a);\n font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);\n font-size: 0.8125rem;\n font-weight: 600;\n}\n\n.mint-component-binding-renderer__source,\n.mint-component-binding-renderer__description,\n.mint-component-binding-renderer__empty {\n margin: 0;\n color: var(--text-secondary, #475569);\n font-size: 0.75rem;\n line-height: 1.4;\n}\n\n.mint-component-binding-renderer__description {\n max-width: 24rem;\n text-align: right;\n}\n\n.mint-component-binding-renderer__body {\n min-width: 0;\n padding: 1rem;\n}\n\n.mint-component-binding-renderer--dense .mint-component-binding-renderer__header,\n.mint-component-binding-renderer--dense .mint-component-binding-renderer__body {\n padding: 0.75rem;\n}\n\n.mint-component-binding-renderer__empty {\n padding: 1rem;\n border: 1px dashed var(--border-color, #e5e7eb);\n border-radius: 0.5rem;\n background: var(--bg-secondary, #f8fafc);\n text-align: center;\n}\n\n@media (max-width: 720px) {\n .mint-component-binding-renderer__header {\n display: block;\n }\n\n .mint-component-binding-renderer__description {\n max-width: none;\n margin-top: 0.25rem;\n text-align: left;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { RefreshCw } from 'lucide-vue-next'\n\ndefineProps<{\n visible: boolean\n}>()\n\nconst emit = defineEmits<{\n reload: []\n}>()\n</script>\n\n<template>\n <div v-if=\"visible\" class=\"mint-runtime-update\" role=\"status\">\n <RefreshCw :size=\"16\" aria-hidden=\"true\" />\n <span>A new version is ready.</span>\n <button type=\"button\" @click=\"emit('reload')\">\n Reload now\n </button>\n </div>\n</template>\n\n<style scoped>\n.mint-runtime-update {\n position: fixed;\n right: 20px;\n bottom: 20px;\n z-index: 1200;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n color: var(--text-primary);\n background: var(--bg-card);\n border: 1px solid var(--border-color);\n border-radius: 10px;\n box-shadow: 0 10px 28px rgb(15 23 42 / 16%);\n font-size: 13px;\n font-weight: 500;\n}\n\n.mint-runtime-update button {\n padding: 5px 9px;\n color: #fff;\n background: var(--color-primary);\n border: 0;\n border-radius: 6px;\n font: inherit;\n cursor: pointer;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { RefreshCw } from 'lucide-vue-next'\n\ndefineProps<{\n visible: boolean\n}>()\n\nconst emit = defineEmits<{\n reload: []\n}>()\n</script>\n\n<template>\n <div v-if=\"visible\" class=\"mint-runtime-update\" role=\"status\">\n <RefreshCw :size=\"16\" aria-hidden=\"true\" />\n <span>A new version is ready.</span>\n <button type=\"button\" @click=\"emit('reload')\">\n Reload now\n </button>\n </div>\n</template>\n\n<style scoped>\n.mint-runtime-update {\n position: fixed;\n right: 20px;\n bottom: 20px;\n z-index: 1200;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n color: var(--text-primary);\n background: var(--bg-card);\n border: 1px solid var(--border-color);\n border-radius: 10px;\n box-shadow: 0 10px 28px rgb(15 23 42 / 16%);\n font-size: 13px;\n font-weight: 500;\n}\n\n.mint-runtime-update button {\n padding: 5px 9px;\n color: #fff;\n background: var(--color-primary);\n border: 0;\n border-radius: 6px;\n font: inherit;\n cursor: pointer;\n}\n</style>\n","import {\n getCurrentScope,\n onScopeDispose,\n readonly,\n ref,\n toValue,\n watch,\n type MaybeRefOrGetter,\n type Ref,\n} from 'vue'\nimport { useApi } from './useApi'\nimport { currentPresence, subscribeRealtime, type RealtimeEvent } from './useRealtime'\n\n/**\n * What a viewer does on a topic. The platform accepts a fixed set per topic\n * kind: `experiment:{id}` takes all four labels, `project:{id}` only\n * `viewing` and `editing`. `editing` means a form with unsaved edits is open;\n * it is a hint, not a lock.\n */\nexport type PresenceActivity = 'viewing' | 'viewing_design' | 'viewing_results' | 'editing'\n\n/** One user with an open realtime stream on the topic. */\nexport interface PresenceViewer {\n user_id: string\n activity: PresenceActivity\n}\n\nexport interface UsePresenceReturn {\n /** The viewers, `editing` first, at most 20; the current user is included. Empty while the stream is closed. */\n viewers: Readonly<Ref<readonly PresenceViewer[]>>\n /** Every viewer, also those beyond the 20 in `viewers`. */\n count: Readonly<Ref<number>>\n /** True while the shared realtime stream is open. */\n connected: Readonly<Ref<boolean>>\n /** Unsubscribe; also runs when the calling component or effect scope is disposed. */\n stop: () => void\n}\n\n/**\n * Who else views an `experiment:{id}` or `project:{id}` topic (RFC #439).\n *\n * Built on `useRealtime`: the tab's open stream on the topic is its presence,\n * and `presence.changed` events update `viewers`. When `activity` is given,\n * the label is sent to `POST /api/presence/activity` when the call starts on\n * an open stream, each time the stream opens and each time the label changes;\n * `stop` (also the end of the calling scope) sets it back to `viewing`.\n * Without it, the platform shows the tab as `viewing`. Like `useRealtime`, it needs the platform's `realtime`\n * feature flag; check that flag first.\n *\n * @example\n * const { viewers } = usePresence(\n * () => `experiment:${id.value}`,\n * () => (dirty.value ? 'editing' : 'viewing'),\n * )\n */\nexport function usePresence(\n topic: MaybeRefOrGetter<string>,\n activity?: MaybeRefOrGetter<PresenceActivity>,\n): UsePresenceReturn {\n const viewers = ref<readonly PresenceViewer[]>([])\n const count = ref(0)\n const api = activity === undefined ? null : useApi({ baseUrl: '/api' })\n\n function report(label = toValue(activity)): void {\n // Presence is a hint: a failed report never reaches the view.\n api?.post('/presence/activity', { topic: toValue(topic), activity: label }).catch(() => {})\n }\n\n function show(event: RealtimeEvent | undefined): void {\n viewers.value = (event?.viewers ?? []) as PresenceViewer[]\n count.value = event?.count ?? 0\n }\n\n const realtime = subscribeRealtime(() => [toValue(topic)], (event) => {\n // ponytail: a resync after a queue overflow keeps the last viewers until\n // the next change; read the presence over REST here if that shows.\n if (event.type === 'resync') report()\n else if (event.type === 'presence.changed' && event.topic === toValue(topic)) show(event)\n }, true)\n\n // When the tab's open stream already views the topic, no open and no resync follow.\n function load(): void {\n const current = currentPresence(toValue(topic))\n show(current)\n if (current) report()\n }\n load()\n const stopTopic = watch(() => toValue(topic), load)\n // A closed stream shows nobody; the server sends the viewers again at the next open.\n const stopConnected = watch(realtime.connected, (open) => { if (!open) show(undefined) })\n // While the stream is closed the report waits for the resync of the next open.\n const stopActivity = watch(() => toValue(activity), () => {\n if (realtime.connected.value) report()\n })\n\n let stopped = false\n function stop(): void {\n if (stopped) return\n stopped = true\n stopTopic()\n stopConnected()\n stopActivity()\n // The stream can stay open on the topic for other callers: drop this caller's label.\n if (realtime.connected.value && toValue(activity) !== 'viewing') report('viewing')\n realtime.stop()\n }\n if (getCurrentScope()) onScopeDispose(stop)\n\n return { viewers: readonly(viewers), count: readonly(count), connected: realtime.connected, stop }\n}\n","import type { PresenceActivity } from '../composables/usePresence'\n\n/** One person on a presence topic, with the name to show. */\nexport interface PresencePerson {\n id: string\n name: string\n activity: PresenceActivity\n}\n\nexport interface PresenceArrangement {\n /** Every other person, `editing` first. */\n others: PresencePerson[]\n /** The people that get an avatar. */\n shown: PresencePerson[]\n /** The other people without an avatar (the `+N`). */\n overflow: number\n /** All other people, also those the platform did not list. */\n total: number\n}\n\nexport const PRESENCE_ACTIVITY_LABELS: Record<PresenceActivity, string> = {\n viewing: 'viewing',\n viewing_design: 'viewing design',\n viewing_results: 'viewing results',\n editing: 'editing',\n}\n\n/**\n * Remove the current user, sort `editing` first (the sort is stable, so the\n * platform order stays otherwise) and keep at most `max` avatars.\n * `count` is the platform's total, the current user included.\n */\nexport function arrangePresence(\n people: readonly PresencePerson[],\n options: { selfId?: string | null; count?: number; max?: number } = {},\n): PresenceArrangement {\n const max = options.max ?? 4\n const selfListed = people.some(person => person.id === options.selfId)\n const others = people\n .filter(person => person.id !== options.selfId)\n .sort((a, b) => Number(b.activity === 'editing') - Number(a.activity === 'editing'))\n // ponytail: past the platform's 20-viewer cap an unlisted current user counts as other.\n const total = Math.max(others.length, (options.count ?? people.length) - (selfListed ? 1 : 0))\n const shown = others.slice(0, max)\n return { others, shown, overflow: total - shown.length, total }\n}\n\n/** \"6 other people here: Alice Chen editing, Chen Li viewing design, and 4 more\". */\nexport function presenceSummary({ shown, overflow, total }: PresenceArrangement): string {\n const names = shown.map(person => `${person.name} ${PRESENCE_ACTIVITY_LABELS[person.activity]}`)\n if (overflow > 0) names.push(`and ${overflow} more`)\n return `${total} other ${total === 1 ? 'person' : 'people'} here: ${names.join(', ')}`\n}\n","<script setup lang=\"ts\">\n/** Who else is on a presence topic: at most `max` avatars (editing first), then `+N`; one button opens the list of each person and activity. */\nimport { computed, useId, useTemplateRef, watch, type Component } from 'vue'\nimport { ChartColumn, Eye, FlaskConical, Pencil } from 'lucide-vue-next'\nimport Avatar from './Avatar.vue'\nimport { useDropdownState } from '../composables/useDropdownState'\nimport { useEventListener } from '../composables/useEventListener'\nimport type { PresenceActivity } from '../composables/usePresence'\nimport {\n PRESENCE_ACTIVITY_LABELS,\n arrangePresence,\n presenceSummary,\n type PresencePerson,\n} from '../utils/presenceAvatars'\n\ninterface Props {\n /** The people on the topic, for example `usePresence().viewers` with names. */\n people: PresencePerson[]\n /** The current user; never shown. */\n selfId?: string | null\n /** All people on the topic (`usePresence().count`), when the list is capped. */\n count?: number\n /** Accessible name of the list. */\n label?: string\n /** Most avatars before `+N`. */\n max?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n selfId: null,\n count: undefined,\n label: 'People here',\n max: 4,\n})\n\nconst ACTIVITY_ICONS: Record<PresenceActivity, Component> = {\n viewing: Eye,\n viewing_design: FlaskConical,\n viewing_results: ChartColumn,\n editing: Pencil,\n}\n\nconst arrangement = computed(() => arrangePresence(props.people, {\n selfId: props.selfId,\n count: props.count,\n max: props.max,\n}))\nconst summary = computed(() => presenceSummary(arrangement.value))\nconst unlisted = computed(() => arrangement.value.total - arrangement.value.others.length)\n\nconst root = useTemplateRef<HTMLElement>('root')\nconst { isOpen, toggle, close } = useDropdownState({\n rootRef: root,\n triggerRef: useTemplateRef<HTMLElement>('trigger'),\n closeOnEscape: false,\n})\n// Escape closes the list from anywhere, but takes the focus back to the button only from within it.\nuseEventListener(() => document, 'keydown', (event) => {\n if (event.key === 'Escape') close(root.value?.contains(event.target as Node) ?? false)\n})\n// The root unmounts when nobody else is here; the list must not reopen on its own when someone comes back.\nwatch(() => arrangement.value.total, (total) => { if (total === 0) close() })\nconst panelId = `mint-presence-${useId()}`\n</script>\n\n<template>\n <div v-if=\"arrangement.total > 0\" ref=\"root\" class=\"mint-presence\">\n <button\n ref=\"trigger\"\n type=\"button\"\n class=\"mint-presence__trigger\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"isOpen ? panelId : undefined\"\n :aria-label=\"summary\"\n @click=\"toggle\"\n >\n <span class=\"mint-presence__stack\" aria-hidden=\"true\">\n <span\n v-for=\"person in arrangement.shown\"\n :key=\"person.id\"\n :class=\"['mint-presence__avatar', { 'mint-presence__avatar--editing': person.activity === 'editing' }]\"\n >\n <Avatar :name=\"person.name\" size=\"xs\" />\n <span v-if=\"person.activity === 'editing'\" class=\"mint-presence__badge\"><Pencil /></span>\n </span>\n <span v-if=\"arrangement.overflow > 0\" class=\"mint-presence__more\">+{{ arrangement.overflow }}</span>\n </span>\n </button>\n\n <div v-if=\"isOpen\" :id=\"panelId\" class=\"mint-popover mint-presence__panel\">\n <div class=\"mint-presence__head\">Here now <span class=\"mint-presence__count\">{{ arrangement.total }}</span></div>\n <ul class=\"mint-presence__list\" :aria-label=\"label\">\n <li v-for=\"person in arrangement.others\" :key=\"person.id\" class=\"mint-presence__row\">\n <span\n :class=\"['mint-presence__avatar', { 'mint-presence__avatar--editing': person.activity === 'editing' }]\"\n aria-hidden=\"true\"\n >\n <Avatar :name=\"person.name\" size=\"xs\" />\n <span v-if=\"person.activity === 'editing'\" class=\"mint-presence__badge\"><Pencil /></span>\n </span>\n <span class=\"mint-presence__name\">{{ person.name }}</span>\n <span :class=\"['mint-presence__activity', { 'mint-presence__activity--editing': person.activity === 'editing' }]\">\n <component :is=\"ACTIVITY_ICONS[person.activity]\" aria-hidden=\"true\" />\n {{ PRESENCE_ACTIVITY_LABELS[person.activity] }}\n </span>\n </li>\n </ul>\n <p v-if=\"unlisted > 0\" class=\"mint-presence__rest\">and {{ unlisted }} more</p>\n <p class=\"mint-presence__foot\">\n <slot name=\"footer\">Editing is a hint, not a lock. You can still edit.</slot>\n </p>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/** Who else is on a presence topic: at most `max` avatars (editing first), then `+N`; one button opens the list of each person and activity. */\nimport { computed, useId, useTemplateRef, watch, type Component } from 'vue'\nimport { ChartColumn, Eye, FlaskConical, Pencil } from 'lucide-vue-next'\nimport Avatar from './Avatar.vue'\nimport { useDropdownState } from '../composables/useDropdownState'\nimport { useEventListener } from '../composables/useEventListener'\nimport type { PresenceActivity } from '../composables/usePresence'\nimport {\n PRESENCE_ACTIVITY_LABELS,\n arrangePresence,\n presenceSummary,\n type PresencePerson,\n} from '../utils/presenceAvatars'\n\ninterface Props {\n /** The people on the topic, for example `usePresence().viewers` with names. */\n people: PresencePerson[]\n /** The current user; never shown. */\n selfId?: string | null\n /** All people on the topic (`usePresence().count`), when the list is capped. */\n count?: number\n /** Accessible name of the list. */\n label?: string\n /** Most avatars before `+N`. */\n max?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n selfId: null,\n count: undefined,\n label: 'People here',\n max: 4,\n})\n\nconst ACTIVITY_ICONS: Record<PresenceActivity, Component> = {\n viewing: Eye,\n viewing_design: FlaskConical,\n viewing_results: ChartColumn,\n editing: Pencil,\n}\n\nconst arrangement = computed(() => arrangePresence(props.people, {\n selfId: props.selfId,\n count: props.count,\n max: props.max,\n}))\nconst summary = computed(() => presenceSummary(arrangement.value))\nconst unlisted = computed(() => arrangement.value.total - arrangement.value.others.length)\n\nconst root = useTemplateRef<HTMLElement>('root')\nconst { isOpen, toggle, close } = useDropdownState({\n rootRef: root,\n triggerRef: useTemplateRef<HTMLElement>('trigger'),\n closeOnEscape: false,\n})\n// Escape closes the list from anywhere, but takes the focus back to the button only from within it.\nuseEventListener(() => document, 'keydown', (event) => {\n if (event.key === 'Escape') close(root.value?.contains(event.target as Node) ?? false)\n})\n// The root unmounts when nobody else is here; the list must not reopen on its own when someone comes back.\nwatch(() => arrangement.value.total, (total) => { if (total === 0) close() })\nconst panelId = `mint-presence-${useId()}`\n</script>\n\n<template>\n <div v-if=\"arrangement.total > 0\" ref=\"root\" class=\"mint-presence\">\n <button\n ref=\"trigger\"\n type=\"button\"\n class=\"mint-presence__trigger\"\n :aria-expanded=\"isOpen\"\n :aria-controls=\"isOpen ? panelId : undefined\"\n :aria-label=\"summary\"\n @click=\"toggle\"\n >\n <span class=\"mint-presence__stack\" aria-hidden=\"true\">\n <span\n v-for=\"person in arrangement.shown\"\n :key=\"person.id\"\n :class=\"['mint-presence__avatar', { 'mint-presence__avatar--editing': person.activity === 'editing' }]\"\n >\n <Avatar :name=\"person.name\" size=\"xs\" />\n <span v-if=\"person.activity === 'editing'\" class=\"mint-presence__badge\"><Pencil /></span>\n </span>\n <span v-if=\"arrangement.overflow > 0\" class=\"mint-presence__more\">+{{ arrangement.overflow }}</span>\n </span>\n </button>\n\n <div v-if=\"isOpen\" :id=\"panelId\" class=\"mint-popover mint-presence__panel\">\n <div class=\"mint-presence__head\">Here now <span class=\"mint-presence__count\">{{ arrangement.total }}</span></div>\n <ul class=\"mint-presence__list\" :aria-label=\"label\">\n <li v-for=\"person in arrangement.others\" :key=\"person.id\" class=\"mint-presence__row\">\n <span\n :class=\"['mint-presence__avatar', { 'mint-presence__avatar--editing': person.activity === 'editing' }]\"\n aria-hidden=\"true\"\n >\n <Avatar :name=\"person.name\" size=\"xs\" />\n <span v-if=\"person.activity === 'editing'\" class=\"mint-presence__badge\"><Pencil /></span>\n </span>\n <span class=\"mint-presence__name\">{{ person.name }}</span>\n <span :class=\"['mint-presence__activity', { 'mint-presence__activity--editing': person.activity === 'editing' }]\">\n <component :is=\"ACTIVITY_ICONS[person.activity]\" aria-hidden=\"true\" />\n {{ PRESENCE_ACTIVITY_LABELS[person.activity] }}\n </span>\n </li>\n </ul>\n <p v-if=\"unlisted > 0\" class=\"mint-presence__rest\">and {{ unlisted }} more</p>\n <p class=\"mint-presence__foot\">\n <slot name=\"footer\">Editing is a hint, not a lock. You can still edit.</slot>\n </p>\n </div>\n </div>\n</template>\n","// Generated-UI runtime components (`@morscherlab/mint-sdk/runtime`).\n\n// Layout components\nexport { default as GeneratedPluginView } from './components/GeneratedPluginView.vue'\nexport { default as GeneratedResultRenderer } from './components/GeneratedResultRenderer.vue'\nexport { default as GeneratedPlotlyResult } from './components/GeneratedPlotlyResult.vue'\nexport { default as ComponentBindingRenderer } from './components/ComponentBindingRenderer.vue'\n/** Modal picker over the read-only server mounts, recording paths rather than copying data. */\nexport { default as GeneratedPathInput } from './components/GeneratedPathInput.vue'\n\n// Feedback components\nexport { default as RuntimeUpdateNotice } from './components/RuntimeUpdateNotice.vue'\n\n// The realtime event stream (`GET /api/events`, behind the `realtime` feature flag).\nexport {\n useRealtime,\n type RealtimeEvent,\n type RealtimeHandler,\n type UseRealtimeReturn,\n} from './composables/useRealtime'\nexport {\n usePresence,\n type PresenceActivity,\n type PresenceViewer,\n type UsePresenceReturn,\n} from './composables/usePresence'\n/** Avatar stack of the other people on a presence topic, with a list of each person and activity. */\nexport { default as PresenceAvatars } from './components/PresenceAvatars.vue'\nexport type { PresencePerson } from './utils/presenceAvatars'\n\n// HTTP client and plugin endpoint helpers. Generated clients (`@/generated/mint-plugin`)\n// build on these; plugin code uses the generated `useClient`, `useSettings` and `useJobs`.\nexport {\n AuthenticationRequiredError,\n useApi,\n type ApiClientOptions,\n type UseApiReturn,\n} from './composables/useApi'\nexport {\n buildEndpointUrl,\n createClient,\n downloadEndpoint,\n pluginFormDataFromPayload,\n resolvePluginBaseUrl,\n uploadEndpoint,\n useEventStream,\n useSettingsEndpoint,\n type BuildEndpointUrlOptions,\n type CreateClientOptions,\n type DownloadEndpointOptions,\n type EventStreamMessage,\n type PluginClientRequestOptions,\n type PluginContract,\n type PluginContractSettings,\n type PluginEndpointContract,\n type PluginEndpointDefinition,\n type PluginEndpointRequestOptions,\n type PluginFormDataPayload,\n type PluginFormDataValue,\n type PluginHttpMethod,\n type PluginNavItemContract,\n type StreamOptions,\n type UseEventStreamReturn,\n type UseSettingsEndpointOptions,\n type UseSettingsEndpointReturn,\n} from './composables/createClient'\nexport {\n createGeneratedAnalysisTransport,\n useJobsEndpoint,\n type GeneratedAnalysisTransport,\n type PluginJobRequestOptions,\n type PluginJobWaitOptions,\n type UseJobsEndpointOptions,\n type UseJobsEndpointReturn,\n} from './composables/useJobsEndpoint'\nexport {\n combinePluginJobSources,\n useJobCenter,\n type CombinedPluginJobCenterSource,\n type JobsStatusTrayTab,\n type PluginJobCenterSource,\n type UseJobCenterOptions,\n type UseJobCenterReturn,\n} from './composables/useJobCenter'\nexport { controlsTo, type ControlsTarget } from './composables/controlSchemaAdapters'\nexport { controlBindings } from './composables/controlComponentBindings'\n\n// Forms, control schemas, job helpers and platform context helpers\nexport {\n useForm,\n type ValidationRule,\n type FieldRules,\n type FieldState,\n type UseFormReturn,\n} from './composables/useForm'\nexport {\n useFormBuilder,\n evaluateCondition,\n} from './composables/useFormBuilder'\nexport {\n getFieldRegistryEntry,\n getTypeDefault,\n type RegistryEntry,\n} from './composables/formBuilderRegistry'\nexport {\n defineControlComponentBindings,\n defineControls,\n getDefaultControlView,\n getControlDefaults,\n useControlSchema,\n useControlWorkspace,\n type ControlFormSchema,\n type ControlFormBinding,\n type ControlSettingsBinding,\n type ControlSidebarBinding,\n type ControlTopBarSettingsBinding,\n type ControlValues,\n type UseControlSchemaReturn,\n type ControlWorkspaceAppTopBarPillBinding,\n type ControlWorkspaceComponentBindings,\n type ControlWorkspaceFormBinding,\n type ControlWorkspacePillNavBinding,\n type ControlWorkspaceSidebarBinding,\n type ControlWorkspaceTopBarBinding,\n type ControlWorkspaceTopBarSettingsBinding,\n type UseControlWorkspaceReturn,\n} from './composables/useControlSchema'\nexport {\n resolveCurrentPluginId,\n} from './composables/platformContextHelpers'\nexport {\n resolveJobCapabilities,\n normalizeJobPercent,\n normalizeJobState,\n isActiveJobStatus,\n isTerminalJobStatus,\n jobStatusLabel,\n type JobCapabilityInput,\n type JobCapabilities,\n} from './jobs'\nexport {\n generatedJobFormSchema,\n generatedJobDefaults,\n normalizeGeneratedJobInput,\n} from './generated/schema'\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"useExperimentSamples-CxcnxZ8h.js","names":[],"sources":["../src/composables/experimentDesignData.ts","../src/composables/useExperimentData.ts","../src/composables/useFileImport.ts","../src/composables/useExperimentSamples.ts"],"sourcesContent":["import type { SelectOption } from '../types'\nimport { isRecord } from '../utils/records'\n\nexport interface ExperimentDesignDataResponse {\n experiment_id?: number\n plugin_id?: string\n data?: Record<string, unknown>\n schema_version?: string\n updated_at?: string | null\n}\n\nexport interface ExtractExperimentSamplesOptions {\n includeControls?: boolean\n}\n\n\nfunction isPlatformDesignDataResponse(value: Record<string, unknown>): boolean {\n return (\n 'data' in value\n && (\n 'experiment_id' in value\n || 'plugin_id' in value\n || 'schema_version' in value\n || 'updated_at' in value\n )\n )\n}\n\n/** Return the plugin-defined design_data payload from common platform and plugin response shapes. */\nexport function unwrapExperimentDesignData(\n rawData: Record<string, unknown> | null | undefined,\n): Record<string, unknown> | null {\n if (!rawData) return null\n\n if (isRecord(rawData.data) && isPlatformDesignDataResponse(rawData)) {\n return rawData.data\n }\n\n if (isRecord(rawData.design_data)) {\n return rawData.design_data\n }\n\n if (isRecord(rawData.designData)) {\n return rawData.designData\n }\n\n return rawData\n}\n\nfunction shouldIncludeSample(record: Record<string, unknown>, options: ExtractExperimentSamplesOptions): boolean {\n if (options.includeControls) return true\n const rawType = record.sample_type ?? record.sampleType ?? record.type ?? record.well_type ?? record.wellType\n const type = typeof rawType === 'string' ? rawType.toLowerCase() : ''\n return !['blank', 'qc'].includes(type)\n}\n\nfunction readSampleValue(record: Record<string, unknown>): string | null {\n const candidates = [\n record.sample_name,\n record.sampleName,\n record.sample_id,\n record.sampleId,\n record.name,\n record.id,\n record.label,\n ]\n\n for (const candidate of candidates) {\n if (typeof candidate === 'string' && candidate.trim()) {\n return candidate\n }\n if (typeof candidate === 'number' && Number.isFinite(candidate)) {\n return String(candidate)\n }\n }\n\n return null\n}\n\nfunction readSampleLabel(record: Record<string, unknown>, fallback: string): string {\n const label = record.name ?? record.label ?? record.sample_name ?? record.sampleName\n return typeof label === 'string' && label.trim() ? label : fallback\n}\n\nfunction readSampleDescription(record: Record<string, unknown>): string | undefined {\n const parts = [\n record.group,\n record.batch,\n record.batch_id,\n record.batchId,\n record.plate_id,\n record.plateId,\n record.well_id,\n record.wellId,\n ].filter((value): value is string | number =>\n (typeof value === 'string' && value.trim().length > 0)\n || typeof value === 'number',\n )\n\n return parts.length > 0 ? parts.map(String).join(' / ') : undefined\n}\n\nfunction addSampleRecord(\n options: SelectOption<string>[],\n seen: Set<string>,\n value: unknown,\n extractOptions: ExtractExperimentSamplesOptions,\n): void {\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed)\n options.push({ value: trimmed, label: trimmed })\n }\n return\n }\n\n if (!isRecord(value) || !shouldIncludeSample(value, extractOptions)) return\n\n const sampleValue = readSampleValue(value)\n if (!sampleValue || seen.has(sampleValue)) return\n\n seen.add(sampleValue)\n options.push({\n value: sampleValue,\n label: readSampleLabel(value, sampleValue),\n description: readSampleDescription(value),\n })\n}\n\nfunction addSampleArray(\n options: SelectOption<string>[],\n seen: Set<string>,\n value: unknown,\n extractOptions: ExtractExperimentSamplesOptions,\n): void {\n if (!Array.isArray(value)) return\n for (const sample of value) {\n addSampleRecord(options, seen, sample, extractOptions)\n }\n}\n\n/** Extract selectable sample options from raw or wrapped experiment design_data. */\nexport function extractSampleOptionsFromDesignData(\n rawData: Record<string, unknown> | null | undefined,\n options: ExtractExperimentSamplesOptions = {},\n): SelectOption<string>[] {\n const designData = unwrapExperimentDesignData(rawData)\n if (!designData) return []\n\n const sampleOptions: SelectOption<string>[] = []\n const seen = new Set<string>()\n\n addSampleArray(sampleOptions, seen, designData.samples, options)\n\n if (isRecord(designData.templates)) {\n for (const template of Object.values(designData.templates)) {\n if (!isRecord(template)) continue\n const templateData = isRecord(template.data) ? template.data : template\n addSampleArray(sampleOptions, seen, templateData.samples, options)\n }\n }\n\n if (Array.isArray(designData.plates)) {\n for (const plate of designData.plates) {\n if (!isRecord(plate)) continue\n addSampleArray(sampleOptions, seen, plate.samples, options)\n }\n }\n\n return sampleOptions\n}\n\n/** Extract SampleSelector-compatible string values from raw or wrapped experiment design_data. */\nexport function extractSampleNamesFromDesignData(\n rawData: Record<string, unknown> | null | undefined,\n options: ExtractExperimentSamplesOptions = {},\n): string[] {\n return extractSampleOptionsFromDesignData(rawData, options).map(sample => sample.value)\n}\n","import { shallowRef, computed, type Ref, type ComputedRef } from 'vue'\nimport { useApi, type UseApiReturn } from './useApi'\nimport { useRequest } from './useRequest'\nimport {\n extractSampleNamesFromDesignData,\n extractSampleOptionsFromDesignData,\n unwrapExperimentDesignData,\n} from './experimentDesignData'\nimport type { TreeNode, SummaryData, SelectOption } from '../types'\n\nexport interface UseExperimentDataOptions {\n apiBaseUrl?: string\n immediate?: boolean\n}\n\nexport interface UseExperimentDataReturn {\n /** Raw experiment data response from `/experiments/{id}/data`, or null. */\n data: Ref<Record<string, unknown> | null>\n /** Plugin-defined design_data payload unwrapped from platform response shapes, or null. */\n designData: ComputedRef<Record<string, unknown> | null>\n /** Sample values extracted from design_data for SampleSelector-style components. */\n sampleNames: ComputedRef<string[]>\n /** Sample options extracted from design_data for select/dropdown components. */\n sampleOptions: ComputedRef<SelectOption<string>[]>\n /** Hierarchy tree rows normalised from `tree_data` or `treeData`. */\n treeData: ComputedRef<TreeNode[]>\n /** Table rows normalised from `table_data` or `tableData`. */\n tableData: ComputedRef<Record<string, unknown>[]>\n /** Summary payload normalised from `summary_data` or `summaryData`, or null. */\n summaryData: ComputedRef<SummaryData | null>\n /** Whether experiment data is currently loading. */\n isLoading: Ref<boolean>\n /** Error message from the last failed fetch, or null. */\n error: Ref<string | null>\n /** Timestamp of the last successful experiment data fetch, or null. */\n lastLoadedAt: Ref<Date | null>\n /** Fetch experiment data for an experiment id. */\n fetch: (experimentId: number) => Promise<Record<string, unknown> | null>\n /** Refetch the most recently fetched experiment id. */\n refresh: () => Promise<void>\n /** Clear local experiment data and current fetch target. */\n clear: () => void\n}\n\n/** Fetches and normalises experiment output data (tree, table, summary) from the platform API. */\nexport function useExperimentData(\n options: UseExperimentDataOptions = {},\n): UseExperimentDataReturn {\n const data = shallowRef<Record<string, unknown> | null>(null)\n const request = useRequest('Failed to fetch experiment data')\n const isLoading = request.isLoading\n const error = request.error\n const lastLoadedAt = request.lastLoadedAt\n let lastExperimentId: number | null = null\n let api: UseApiReturn | null = null\n\n function getApi(): UseApiReturn {\n api ??= useApi({ baseUrl: options.apiBaseUrl })\n return api\n }\n\n const designData = computed<Record<string, unknown> | null>(() =>\n unwrapExperimentDesignData(data.value),\n )\n\n const sampleNames = computed<string[]>(() =>\n extractSampleNamesFromDesignData(designData.value),\n )\n\n const sampleOptions = computed<SelectOption<string>[]>(() =>\n extractSampleOptionsFromDesignData(designData.value),\n )\n\n const treeData = computed<TreeNode[]>(() => {\n if (!designData.value) return []\n const tree = designData.value.tree_data ?? designData.value.treeData\n return Array.isArray(tree) ? tree as TreeNode[] : []\n })\n\n const tableData = computed<Record<string, unknown>[]>(() => {\n if (!designData.value) return []\n const table = designData.value.table_data ?? designData.value.tableData\n return Array.isArray(table) ? table as Record<string, unknown>[] : []\n })\n\n const summaryData = computed<SummaryData | null>(() => {\n if (!designData.value) return null\n const summary = designData.value.summary_data ?? designData.value.summaryData\n if (summary && typeof summary === 'object' && 'metadata' in (summary as Record<string, unknown>)) {\n return summary as SummaryData\n }\n return null\n })\n\n async function fetchData(experimentId: number): Promise<Record<string, unknown> | null> {\n lastExperimentId = experimentId\n try {\n data.value = await request.run(\n () => getApi().get<Record<string, unknown>>(`/experiments/${experimentId}/data`),\n { kind: 'load', errorMessage: 'Failed to fetch experiment data' },\n )\n return data.value\n } catch {\n data.value = null\n return null\n }\n }\n\n async function refresh(): Promise<void> {\n if (lastExperimentId !== null) {\n await fetchData(lastExperimentId)\n }\n }\n\n function clear(): void {\n data.value = null\n lastExperimentId = null\n request.clearError()\n }\n\n return {\n data,\n designData,\n sampleNames,\n sampleOptions,\n treeData,\n tableData,\n summaryData,\n isLoading,\n error,\n lastLoadedAt,\n fetch: fetchData,\n refresh,\n clear,\n }\n}\n","import { ref, shallowRef, type Ref, type ShallowRef } from 'vue'\nimport { readErrorMessage } from '../utils/errors'\n\nexport interface DelimitedTable {\n columns: string[]\n rows: Record<string, string>[]\n rawRows: string[][]\n delimiter: string\n}\n\nexport interface ParseDelimitedTextOptions {\n delimiter?: string\n headers?: readonly string[]\n hasHeaderRow?: boolean\n trim?: boolean\n}\n\nexport interface FileImportValidationOptions {\n accept?: string | readonly string[]\n maxSizeBytes?: number\n}\n\nexport interface FileImportOptions<TResult = string> extends FileImportValidationOptions {\n encoding?: string\n parse?: (text: string, file: File) => TResult | Promise<TResult>\n}\n\nexport interface UseFileImportReturn<TResult> {\n loading: ShallowRef<boolean>\n error: Ref<string | null>\n fileName: Ref<string>\n result: Ref<TResult | null>\n importFile: (file: File) => Promise<TResult>\n clear: () => void\n}\n\n/** Stateful file reader for plugin import flows with shared validation and error handling. */\nexport function useFileImport<TResult = string>(\n options: FileImportOptions<TResult> = {},\n): UseFileImportReturn<TResult> {\n const loading = shallowRef(false)\n const error = ref<string | null>(null)\n const fileName = ref('')\n const result = ref<TResult | null>(null) as Ref<TResult | null>\n\n function clear(): void {\n loading.value = false\n error.value = null\n fileName.value = ''\n result.value = null\n }\n\n async function importFile(file: File): Promise<TResult> {\n loading.value = true\n error.value = null\n fileName.value = file.name\n\n try {\n validateImportFile(file, options)\n const text = await readFileAsText(file, options.encoding)\n const parsed = options.parse\n ? await options.parse(text, file)\n : text as TResult\n result.value = parsed\n return parsed\n } catch (err) {\n const message = readErrorMessage(err, 'Failed to import file.')\n error.value = message\n throw err\n } finally {\n loading.value = false\n }\n }\n\n return {\n loading,\n error,\n fileName,\n result,\n importFile,\n clear,\n }\n}\n\nexport function validateImportFile(file: File, options: FileImportValidationOptions = {}): void {\n if (options.maxSizeBytes !== undefined && file.size > options.maxSizeBytes) {\n throw new Error(`File is too large. Maximum size is ${formatBytes(options.maxSizeBytes)}.`)\n }\n\n const accept = normalizeAccept(options.accept)\n if (accept.length === 0) return\n\n const name = file.name.toLowerCase()\n const type = file.type.toLowerCase()\n const matches = accept.some((entry) => {\n if (entry.startsWith('.')) return name.endsWith(entry)\n if (entry.endsWith('/*')) return type.startsWith(entry.slice(0, -1))\n return type === entry\n })\n\n if (!matches) {\n throw new Error(`Unsupported file type. Expected ${accept.join(', ')}.`)\n }\n}\n\nexport function readFileAsText(file: File, encoding?: string): Promise<string> {\n if (typeof FileReader === 'undefined' && typeof file.text === 'function') {\n return file.text()\n }\n\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => resolve(String(reader.result ?? ''))\n reader.onerror = () => reject(reader.error ?? new Error('Failed to read file.'))\n reader.readAsText(file, encoding)\n })\n}\n\nexport function parseDelimitedText(\n text: string,\n options: ParseDelimitedTextOptions = {},\n): DelimitedTable {\n const trim = options.trim ?? true\n const delimiter = options.delimiter ?? detectDelimiter(text)\n const rawRows = parseDelimitedRows(text, delimiter)\n .filter(row => row.some(cell => cell.trim().length > 0))\n .map(row => trim ? row.map(cell => cell.trim()) : row)\n\n const hasHeaderRow = options.hasHeaderRow ?? !options.headers\n const columns = options.headers\n ? [...options.headers]\n : hasHeaderRow\n ? rawRows[0] ?? []\n : createColumnNames(maxRowLength(rawRows))\n\n const dataRows = hasHeaderRow && !options.headers ? rawRows.slice(1) : rawRows\n const rows = dataRows.map(row => Object.fromEntries(\n columns.map((column, index) => [column, row[index] ?? '']),\n ))\n\n return {\n columns,\n rows,\n rawRows,\n delimiter,\n }\n}\n\nexport function detectDelimiter(text: string): string {\n const firstLine = text.split(/\\r?\\n/, 1)[0] ?? ''\n const commaCount = countChar(firstLine, ',')\n const tabCount = countChar(firstLine, '\\t')\n const semicolonCount = countChar(firstLine, ';')\n if (tabCount > commaCount && tabCount >= semicolonCount) return '\\t'\n if (semicolonCount > commaCount) return ';'\n return ','\n}\n\nfunction parseDelimitedRows(text: string, delimiter: string): string[][] {\n const rows: string[][] = []\n let row: string[] = []\n let field = ''\n let quoted = false\n\n for (let index = 0; index < text.length; index++) {\n const char = text[index]\n const next = text[index + 1]\n\n if (char === '\"') {\n if (quoted && next === '\"') {\n field += '\"'\n index++\n } else {\n quoted = !quoted\n }\n continue\n }\n\n if (!quoted && char === delimiter) {\n row.push(field)\n field = ''\n continue\n }\n\n if (!quoted && (char === '\\n' || char === '\\r')) {\n if (char === '\\r' && next === '\\n') index++\n row.push(field)\n rows.push(row)\n row = []\n field = ''\n continue\n }\n\n field += char\n }\n\n row.push(field)\n rows.push(row)\n return rows\n}\n\nfunction normalizeAccept(accept: string | readonly string[] | undefined): string[] {\n if (!accept) return []\n const entries = typeof accept === 'string' ? accept.split(',') : [...accept]\n return entries\n .map((entry: string) => entry.trim().toLowerCase())\n .filter(Boolean)\n}\n\nfunction createColumnNames(count: number): string[] {\n return Array.from({ length: count }, (_, index) => `column_${index + 1}`)\n}\n\nfunction maxRowLength(rows: readonly string[][]): number {\n return rows.reduce((max, row) => Math.max(max, row.length), 0)\n}\n\nfunction countChar(value: string, char: string): number {\n return [...value].filter(candidate => candidate === char).length\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`\n return `${Math.round(bytes / (1024 * 1024))} MB`\n}\n","import {\n computed,\n inject,\n toValue,\n watch,\n type ComputedRef,\n type MaybeRefOrGetter,\n type Ref,\n} from 'vue'\nimport type { SelectOption } from '../types'\nimport { APP_EXPERIMENT_KEY } from './useAppExperiment'\nimport {\n extractSampleNamesFromDesignData,\n extractSampleOptionsFromDesignData,\n unwrapExperimentDesignData,\n type ExtractExperimentSamplesOptions,\n} from './experimentDesignData'\nimport { parseExperimentId } from './platformContextHelpers'\nimport { useExperimentData } from './useExperimentData'\n\nexport type ExperimentIdSource = MaybeRefOrGetter<number | string | null | undefined>\nexport type ExperimentDesignDataSource = MaybeRefOrGetter<Record<string, unknown> | null | undefined>\n\nexport interface UseExperimentSamplesOptions extends ExtractExperimentSamplesOptions {\n /** Experiment id to load from `/experiments/{id}/data`; defaults to provided AppExperiment context. */\n experimentId?: ExperimentIdSource\n /** Pre-fetched design_data or full platform design-data response. */\n designData?: ExperimentDesignDataSource\n /** API base URL override for platform calls. */\n apiBaseUrl?: string\n /** Auto-load when an experiment id becomes available. Defaults to true. */\n immediate?: boolean\n /** Enable or disable automatic loading while keeping derived samples reactive. Defaults to true. */\n enabled?: MaybeRefOrGetter<boolean>\n /** Use `useAppExperiment` provided state when `experimentId` is not set. Defaults to true. */\n syncAppExperiment?: boolean\n}\n\nexport interface UseExperimentSamplesReturn {\n /** Experiment id currently used for automatic sample loading. */\n experimentId: ComputedRef<number | undefined>\n /** Raw `/experiments/{id}/data` response when loaded through the platform API. */\n data: Ref<Record<string, unknown> | null>\n /** Plugin-defined design_data payload from props or platform response. */\n designData: ComputedRef<Record<string, unknown> | null>\n /** SampleSelector-compatible string values extracted from design_data. */\n samples: ComputedRef<string[]>\n /** Select/dropdown-friendly sample options extracted from design_data. */\n sampleOptions: ComputedRef<SelectOption<string>[]>\n isLoading: Ref<boolean>\n error: Ref<string | null>\n lastLoadedAt: Ref<Date | null>\n /** Fetch samples for a specific experiment id, defaulting to the resolved id. */\n fetch: (experimentId?: number | string | null) => Promise<Record<string, unknown> | null>\n /** Refetch the current experiment id. */\n refresh: () => Promise<void>\n /** Clear fetched platform data. */\n clear: () => void\n}\n\n/** Loads experiment design_data and derives samples for SampleSelector-style UIs. */\nexport function useExperimentSamples(\n options: UseExperimentSamplesOptions = {},\n): UseExperimentSamplesReturn {\n const appExperiment = options.syncAppExperiment === false\n ? undefined\n : inject(APP_EXPERIMENT_KEY, undefined)\n const experimentData = useExperimentData({ apiBaseUrl: options.apiBaseUrl })\n\n const experimentId = computed<number | undefined>(() => {\n const explicitId = parseExperimentId(toValue(options.experimentId))\n return explicitId ?? parseExperimentId(appExperiment?.experimentId.value)\n })\n\n const explicitDesignData = computed<Record<string, unknown> | null>(() =>\n unwrapExperimentDesignData(toValue(options.designData) ?? null),\n )\n\n const designData = computed<Record<string, unknown> | null>(() =>\n explicitDesignData.value ?? experimentData.designData.value,\n )\n\n const extractOptions = computed<ExtractExperimentSamplesOptions>(() => ({\n includeControls: options.includeControls,\n }))\n\n const samples = computed<string[]>(() =>\n extractSampleNamesFromDesignData(designData.value, extractOptions.value),\n )\n\n const sampleOptions = computed<SelectOption<string>[]>(() =>\n extractSampleOptionsFromDesignData(designData.value, extractOptions.value),\n )\n\n const enabled = computed(() => toValue(options.enabled) ?? true)\n\n async function fetchSamples(\n id: number | string | null | undefined = experimentId.value,\n ): Promise<Record<string, unknown> | null> {\n const parsedId = parseExperimentId(id)\n if (parsedId === undefined) {\n experimentData.clear()\n return null\n }\n return experimentData.fetch(parsedId)\n }\n\n watch(\n () => ({\n designData: explicitDesignData.value,\n enabled: enabled.value,\n experimentId: experimentId.value,\n }),\n ({ designData: currentDesignData, enabled: isEnabled, experimentId: currentExperimentId }) => {\n if (options.immediate === false || !isEnabled) return\n if (currentDesignData) {\n experimentData.clear()\n return\n }\n if (currentExperimentId === undefined) {\n experimentData.clear()\n return\n }\n void experimentData.fetch(currentExperimentId)\n },\n { immediate: options.immediate !== false },\n )\n\n return {\n experimentId,\n data: experimentData.data,\n designData,\n samples,\n sampleOptions,\n isLoading: experimentData.isLoading,\n error: experimentData.error,\n lastLoadedAt: experimentData.lastLoadedAt,\n fetch: fetchSamples,\n refresh: experimentData.refresh,\n clear: experimentData.clear,\n }\n}\n"],"mappings":"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"}