@morscherlab/mint-sdk 1.1.25 → 1.2.0-beta.10

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 (403) hide show
  1. package/README.md +44 -12
  2. package/dist/{ExperimentPopover-tLwJ7XF4.js → ExperimentPopover-oL0fg_A0.js} +6 -4
  3. package/dist/ExperimentPopover-oL0fg_A0.js.map +1 -0
  4. package/dist/{ExperimentSelectorModal-B6P2msT4.js → ExperimentSelectorModal-BeEOomw_.js} +5 -5
  5. package/dist/ExperimentSelectorModal-BeEOomw_.js.map +1 -0
  6. package/dist/{SettingsModal-BW3Ar-uy.js → SettingsModal-Dphh3RrI.js} +5 -8
  7. package/dist/SettingsModal-Dphh3RrI.js.map +1 -0
  8. package/dist/{EmptyState-p90quq8Z.js → Skeleton-DxtwJ5gt.js} +111 -93
  9. package/dist/Skeleton-DxtwJ5gt.js.map +1 -0
  10. package/dist/__tests__/components/ExperimentTimeline.test.d.ts +1 -0
  11. package/dist/__tests__/components/PluginWorkspaceView.internal.test.d.ts +1 -0
  12. package/dist/__tests__/components/SecretInput.test.d.ts +1 -0
  13. package/dist/__tests__/components/WellEditPopupInternal.test.d.ts +1 -0
  14. package/dist/__tests__/composables/useEventStream.test.d.ts +1 -0
  15. package/dist/__tests__/composables/useListReorder.test.d.ts +1 -0
  16. package/dist/__tests__/styles/cssTokens.test.d.ts +1 -0
  17. package/dist/components/ActionMenu.vue.d.ts +1 -1
  18. package/dist/components/AppAvatarMenu.vue.d.ts +4 -0
  19. package/dist/components/AppPluginSwitcher.vue.d.ts +2 -0
  20. package/dist/components/AppSidebar.vue.d.ts +1 -1
  21. package/dist/components/AuditTrail.vue.d.ts +13 -0
  22. package/dist/components/BatchProgressList.vue.d.ts +17 -0
  23. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +1 -1
  24. package/dist/components/DataFrame.vue.d.ts +14 -2
  25. package/dist/components/DatePicker.vue.d.ts +1 -1
  26. package/dist/components/DateTimePicker.vue.d.ts +2 -0
  27. package/dist/components/DropdownButton.vue.d.ts +2 -0
  28. package/dist/components/ExperimentDataViewer.vue.d.ts +26 -1
  29. package/dist/components/ExperimentPopover.vue.d.ts +1 -0
  30. package/dist/components/ExperimentTimeline.vue.d.ts +29 -1
  31. package/dist/components/FitPanel.vue.d.ts +1 -1
  32. package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
  33. package/dist/components/PluginWorkspaceView.props.d.ts +29 -1
  34. package/dist/components/PluginWorkspaceView.vue.d.ts +5 -5
  35. package/dist/components/ProgressBar.vue.d.ts +1 -1
  36. package/dist/components/ProtocolStepEditor.vue.d.ts +1 -0
  37. package/dist/components/ReagentList.vue.d.ts +29 -1
  38. package/dist/components/SampleHierarchyTree.vue.d.ts +29 -1
  39. package/dist/components/SampleSelector.drag.d.ts +13 -0
  40. package/dist/components/SampleSelector.tree.d.ts +2 -0
  41. package/dist/components/SampleSelector.vue.d.ts +34 -1
  42. package/dist/components/ScheduleCalendar.vue.d.ts +20 -0
  43. package/dist/components/SecretInput.vue.d.ts +28 -0
  44. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +2 -1
  45. package/dist/components/TimePicker.vue.d.ts +1 -0
  46. package/dist/components/WellPlate.geometry.d.ts +15 -0
  47. package/dist/components/WellPlate.interaction.d.ts +13 -0
  48. package/dist/components/WellPlate.vue.d.ts +29 -0
  49. package/dist/components/index.d.ts +9 -0
  50. package/dist/components/index.js +8 -8
  51. package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -0
  52. package/dist/components/internal/DataStateInternal.vue.d.ts +43 -0
  53. package/dist/components/internal/WellEditPopupInternal.vue.d.ts +3 -1
  54. package/dist/components/internal/WorkspaceControlsInternal.vue.d.ts +23 -0
  55. package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +70 -0
  56. package/dist/components/internal/WorkspaceSidebarInternal.vue.d.ts +43 -0
  57. package/dist/{components-DQt0tcpY.js → components-CgAUzF8F.js} +2491 -2235
  58. package/dist/components-CgAUzF8F.js.map +1 -0
  59. package/dist/composables/controlSchemaTypes.d.ts +34 -0
  60. package/dist/composables/flattenWorkspaceBindings.d.ts +61 -0
  61. package/dist/composables/index.d.ts +8 -2
  62. package/dist/composables/index.js +10 -10
  63. package/dist/composables/pluginWorkspaceModel.d.ts +164 -0
  64. package/dist/composables/useAsync.d.ts +5 -1
  65. package/dist/composables/useBioTemplateWorkspace.d.ts +4 -20
  66. package/dist/composables/useCommandHistory.d.ts +5 -1
  67. package/dist/composables/useDropdownState.d.ts +18 -2
  68. package/dist/composables/useEventStream.d.ts +52 -0
  69. package/dist/composables/useFocusTrap.d.ts +21 -0
  70. package/dist/composables/useJobsStatusTray.d.ts +1 -1
  71. package/dist/composables/useListReorder.d.ts +90 -0
  72. package/dist/composables/useMenuKeyboard.d.ts +29 -0
  73. package/dist/composables/useOptimisticMutation.d.ts +5 -1
  74. package/dist/composables/usePluginClient.d.ts +4 -17
  75. package/dist/composables/usePluginConfig.d.ts +3 -1
  76. package/dist/composables/usePluginWorkspace.d.ts +51 -0
  77. package/dist/composables/useRequestSyncState.d.ts +42 -2
  78. package/dist/composables/useResourceCrud.d.ts +5 -1
  79. package/dist/composables/useRovingFocus.d.ts +24 -0
  80. package/dist/composables/useScheduleDrag.d.ts +1 -0
  81. package/dist/composables/useWellPainting.d.ts +5 -1
  82. package/dist/composables/useWellPlateAdapter.d.ts +5 -1
  83. package/dist/composables/useWellPlateValidation.d.ts +5 -1
  84. package/dist/composables/workspaceRecipes.d.ts +188 -0
  85. package/dist/{composables-CkXDe7nm.js → composables-B_pia3hO.js} +105 -254
  86. package/dist/composables-B_pia3hO.js.map +1 -0
  87. package/dist/{useApi-CDBq6z23.js → errors-_W0-LbA6.js} +102 -3
  88. package/dist/errors-_W0-LbA6.js.map +1 -0
  89. package/dist/{experiment-Y9Iz7KYi.js → experiment-Cwl9AYxw.js} +3 -8
  90. package/dist/experiment-Cwl9AYxw.js.map +1 -0
  91. package/dist/{experiment-utils-CLnzPPq5.js → experiment-utils-DV3DrvE_.js} +70 -51
  92. package/dist/experiment-utils-DV3DrvE_.js.map +1 -0
  93. package/dist/index.d.ts +1 -0
  94. package/dist/index.js +15 -15
  95. package/dist/install.js +2 -7
  96. package/dist/install.js.map +1 -1
  97. package/dist/permissions.d.ts +42 -1
  98. package/dist/permissions.js +20 -10
  99. package/dist/permissions.js.map +1 -1
  100. package/dist/stores/index.d.ts +1 -1
  101. package/dist/stores/index.js +3 -3
  102. package/dist/stores/settings.d.ts +31 -1
  103. package/dist/styles.css +11247 -29501
  104. package/dist/templates/builderReadUtils.d.ts +1 -1
  105. package/dist/templates/index.js +2 -4
  106. package/dist/{templates-CovvRZ-9.js → templates-Qq113pyZ.js} +303 -106
  107. package/dist/templates-Qq113pyZ.js.map +1 -0
  108. package/dist/types/form-builder.d.ts +1 -1
  109. package/dist/{useControlSchema-BhoJzWzx.js → useControlSchema-aMZlb4Sc.js} +684 -1216
  110. package/dist/useControlSchema-aMZlb4Sc.js.map +1 -0
  111. package/dist/{useDropdownState-DSb3BC3N.js → useDropdownState-DitCtrTT.js} +22 -6
  112. package/dist/useDropdownState-DitCtrTT.js.map +1 -0
  113. package/dist/{useExperimentSelector-D0pjj9WH.js → useExperimentSelector-I8HC8hUu.js} +4 -4
  114. package/dist/{useExperimentSelector-D0pjj9WH.js.map → useExperimentSelector-I8HC8hUu.js.map} +1 -1
  115. package/dist/{useFormBuilder-DiEcDis2.js → useFormBuilder-TCxNnqeb.js} +2 -2
  116. package/dist/{useFormBuilder-DiEcDis2.js.map → useFormBuilder-TCxNnqeb.js.map} +1 -1
  117. package/dist/{useProtocolTemplates-DHwSveE6.js → useProtocolTemplates-BmX_iVBR.js} +660 -197
  118. package/dist/useProtocolTemplates-BmX_iVBR.js.map +1 -0
  119. package/dist/utils/color.d.ts +13 -0
  120. package/dist/utils/errors.d.ts +9 -0
  121. package/dist/utils/pluginSecrets.d.ts +53 -0
  122. package/dist/utils/records.d.ts +4 -0
  123. package/package.json +1 -1
  124. package/src/__tests__/components/ActionMenu.test.ts +94 -0
  125. package/src/__tests__/components/AppAvatarMenu.test.ts +123 -0
  126. package/src/__tests__/components/BaseTabs.test.ts +67 -0
  127. package/src/__tests__/components/DataFrame.test.ts +183 -11
  128. package/src/__tests__/components/DataStates.test.ts +176 -0
  129. package/src/__tests__/components/DatePicker.test.ts +76 -0
  130. package/src/__tests__/components/DateTimePicker.test.ts +36 -0
  131. package/src/__tests__/components/DropdownButton.test.ts +134 -0
  132. package/src/__tests__/components/ExperimentTimeline.test.ts +63 -0
  133. package/src/__tests__/components/GeneratedPluginView.test.ts +0 -5
  134. package/src/__tests__/components/GroupAssigner.test.ts +53 -0
  135. package/src/__tests__/components/JobsStatusTray.test.ts +20 -18
  136. package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
  137. package/src/__tests__/components/PluginWorkspaceView.internal.test.ts +230 -0
  138. package/src/__tests__/components/RackEditor.test.ts +35 -0
  139. package/src/__tests__/components/ReagentList.test.ts +64 -2
  140. package/src/__tests__/components/RetiredStyles.test.ts +31 -0
  141. package/src/__tests__/components/SampleSelector.drag.test.ts +51 -1
  142. package/src/__tests__/components/ScheduleCalendar.test.ts +63 -0
  143. package/src/__tests__/components/SecretInput.test.ts +87 -0
  144. package/src/__tests__/components/SegmentedControl.test.ts +88 -0
  145. package/src/__tests__/components/TimePicker.test.ts +61 -0
  146. package/src/__tests__/components/WellEditPopupInternal.test.ts +108 -0
  147. package/src/__tests__/components/WellPlate.interaction.test.ts +59 -0
  148. package/src/__tests__/composables/useAuth.test.ts +25 -0
  149. package/src/__tests__/composables/useDropdownState.test.ts +58 -1
  150. package/src/__tests__/composables/useEventStream.test.ts +140 -0
  151. package/src/__tests__/composables/useGeneratedAnalysis.test.ts +103 -0
  152. package/src/__tests__/composables/useJobsStatusTray.test.ts +25 -161
  153. package/src/__tests__/composables/useListReorder.test.ts +145 -0
  154. package/src/__tests__/composables/usePluginClient.test.ts +148 -13
  155. package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
  156. package/src/__tests__/docs/frontendDocsCatalog.test.ts +55 -2
  157. package/src/__tests__/stores/settings.test.ts +71 -1
  158. package/src/__tests__/styles/cssTokens.test.ts +131 -0
  159. package/src/__tests__/utils/permissions.test.ts +68 -0
  160. package/src/components/ActionMenu.vue +45 -88
  161. package/src/components/AlertBox.vue +0 -4
  162. package/src/components/AppAvatarMenu.vue +26 -7
  163. package/src/components/AppLayout.vue +0 -4
  164. package/src/components/AppPluginSwitcher.story.vue +87 -0
  165. package/src/components/AppPluginSwitcher.vue +2 -5
  166. package/src/components/AppSidebar.vue +0 -4
  167. package/src/components/AppToastContainer.vue +6 -8
  168. package/src/components/AppTopBar.vue +0 -4
  169. package/src/components/ArtifactSaveDialog.vue +0 -4
  170. package/src/components/ArtifactSelectorModal.vue +0 -4
  171. package/src/components/AuditTrail.story.vue +18 -0
  172. package/src/components/AuditTrail.vue +27 -7
  173. package/src/components/AutoGroupModal.vue +0 -4
  174. package/src/components/Avatar.vue +0 -4
  175. package/src/components/BaseButton.vue +0 -4
  176. package/src/components/BaseCheckbox.vue +0 -4
  177. package/src/components/BaseInput.vue +0 -4
  178. package/src/components/BaseModal.vue +8 -60
  179. package/src/components/BasePill.vue +0 -4
  180. package/src/components/BaseRadioGroup.vue +0 -4
  181. package/src/components/BaseSelect.vue +0 -4
  182. package/src/components/BaseSlider.vue +0 -4
  183. package/src/components/BaseTabs.vue +26 -5
  184. package/src/components/BaseTextarea.vue +0 -4
  185. package/src/components/BaseToggle.vue +0 -4
  186. package/src/components/BatchProgressList.story.vue +18 -0
  187. package/src/components/BatchProgressList.vue +32 -4
  188. package/src/components/BioTemplateExperimentWorkspaceView.vue +10 -21
  189. package/src/components/BioTemplatePackWorkspaceView.vue +11 -15
  190. package/src/components/BioTemplatePresetWorkspaceView.vue +8 -13
  191. package/src/components/Breadcrumb.vue +0 -4
  192. package/src/components/Calendar.vue +0 -4
  193. package/src/components/ChartContainer.story.vue +1 -1
  194. package/src/components/ChartContainer.vue +0 -4
  195. package/src/components/ChemicalFormula.vue +0 -4
  196. package/src/components/CollapsibleCard.vue +0 -4
  197. package/src/components/ColorSlider.vue +0 -4
  198. package/src/components/ComponentBindingRenderer.vue +1 -3
  199. package/src/components/ConcentrationInput.vue +0 -4
  200. package/src/components/ConfirmDialog.vue +0 -4
  201. package/src/components/ControlWorkspaceView.vue +11 -22
  202. package/src/components/DataFrame.story.vue +14 -0
  203. package/src/components/DataFrame.vue +97 -23
  204. package/src/components/DatePicker.vue +73 -27
  205. package/src/components/DateTimePicker.vue +45 -17
  206. package/src/components/Divider.vue +0 -4
  207. package/src/components/DoseCalculator.vue +0 -4
  208. package/src/components/DoseDesignWorkspaceView.vue +6 -25
  209. package/src/components/DropdownButton.vue +24 -6
  210. package/src/components/EmptyState.vue +0 -4
  211. package/src/components/ExperimentCodeBadge.vue +0 -4
  212. package/src/components/ExperimentDataViewer.story.vue +3 -0
  213. package/src/components/ExperimentDataViewer.vue +33 -13
  214. package/src/components/ExperimentPopover.vue +2 -5
  215. package/src/components/ExperimentSelectorModal.vue +0 -4
  216. package/src/components/ExperimentTimeline.story.vue +18 -0
  217. package/src/components/ExperimentTimeline.vue +81 -75
  218. package/src/components/FileUploader.vue +0 -4
  219. package/src/components/FitPanel.vue +0 -4
  220. package/src/components/FormActions.story.vue +96 -0
  221. package/src/components/FormActions.vue +0 -4
  222. package/src/components/FormBuilder.vue +0 -4
  223. package/src/components/FormField.vue +0 -4
  224. package/src/components/FormulaInput.vue +0 -4
  225. package/src/components/GeneratedPathInput.story.vue +68 -0
  226. package/src/components/GeneratedPlotlyResult.story.vue +96 -0
  227. package/src/components/GeneratedPlotlyResult.vue +3 -3
  228. package/src/components/GeneratedPluginView.story.vue +145 -0
  229. package/src/components/GeneratedPluginView.vue +10 -10
  230. package/src/components/GeneratedResultRenderer.story.vue +117 -0
  231. package/src/components/GeneratedResultRenderer.vue +4 -4
  232. package/src/components/GroupAssigner.vue +67 -5
  233. package/src/components/IconButton.vue +0 -4
  234. package/src/components/InstrumentAlertLog.vue +0 -4
  235. package/src/components/InstrumentStateBadge.vue +0 -4
  236. package/src/components/InstrumentStatusCard.vue +0 -4
  237. package/src/components/JobsStatusTray.story.vue +6 -10
  238. package/src/components/JobsStatusTray.vue +0 -4
  239. package/src/components/LcmsSequenceTable.vue +81 -50
  240. package/src/components/LoadingSpinner.vue +0 -4
  241. package/src/components/MobileSupportGate.vue +0 -4
  242. package/src/components/MoleculeInput.vue +0 -4
  243. package/src/components/MultiSelect.vue +0 -4
  244. package/src/components/NumberInput.vue +0 -4
  245. package/src/components/PlateMapEditor.vue +3 -14
  246. package/src/components/PluginIcon.vue +0 -4
  247. package/src/components/PluginWorkspaceView.props.ts +38 -0
  248. package/src/components/PluginWorkspaceView.vue +53 -224
  249. package/src/components/ProgressBar.vue +0 -4
  250. package/src/components/ProtocolStepEditor.vue +2 -4
  251. package/src/components/RackEditor.vue +51 -70
  252. package/src/components/ReagentEditor.vue +0 -4
  253. package/src/components/ReagentList.story.vue +18 -0
  254. package/src/components/ReagentList.vue +127 -82
  255. package/src/components/ResourceCard.vue +0 -4
  256. package/src/components/RuntimeUpdateNotice.story.vue +49 -0
  257. package/src/components/RuntimeUpdateNotice.vue +4 -4
  258. package/src/components/SampleHierarchyTree.story.vue +18 -0
  259. package/src/components/SampleHierarchyTree.vue +32 -9
  260. package/src/components/SampleLegend.vue +2 -8
  261. package/src/components/SampleSelector.drag.ts +51 -0
  262. package/src/components/SampleSelector.story.vue +6 -0
  263. package/src/components/SampleSelector.tree.ts +2 -0
  264. package/src/components/SampleSelector.vue +49 -10
  265. package/src/components/SampleSelectorGroupNode.vue +19 -0
  266. package/src/components/ScheduleCalendar.story.vue +6 -0
  267. package/src/components/ScheduleCalendar.vue +82 -7
  268. package/src/components/ScientificNumber.vue +0 -4
  269. package/src/components/SecretInput.story.vue +79 -0
  270. package/src/components/SecretInput.vue +150 -0
  271. package/src/components/SectionCard.vue +0 -4
  272. package/src/components/SegmentedControl.vue +48 -5
  273. package/src/components/SequenceInput.vue +0 -4
  274. package/src/components/SequenceProgressBar.story.vue +110 -0
  275. package/src/components/SequenceProgressBar.vue +0 -4
  276. package/src/components/SettingsModal.vue +0 -4
  277. package/src/components/Skeleton.vue +0 -4
  278. package/src/components/SmartGroupFieldRecipe.vue +8 -6
  279. package/src/components/SmartGroupManual.vue +0 -4
  280. package/src/components/StatusIndicator.vue +0 -4
  281. package/src/components/StepWizard.vue +0 -4
  282. package/src/components/TagsInput.vue +4 -6
  283. package/src/components/ThemeToggle.vue +0 -4
  284. package/src/components/TimePicker.vue +36 -7
  285. package/src/components/TimeRangeInput.vue +0 -4
  286. package/src/components/Tooltip.story.vue +3 -3
  287. package/src/components/Tooltip.vue +0 -4
  288. package/src/components/UnitInput.vue +0 -4
  289. package/src/components/WellPlate.geometry.ts +60 -1
  290. package/src/components/WellPlate.interaction.ts +44 -0
  291. package/src/components/WellPlate.story.vue +8 -0
  292. package/src/components/WellPlate.vue +53 -7
  293. package/src/components/index.ts +9 -0
  294. package/src/components/internal/AppTopBarPageSelectorInternal.vue +2 -5
  295. package/src/components/internal/AppTopBarPillNavInternal.vue +0 -4
  296. package/src/components/internal/DataStateInternal.vue +74 -0
  297. package/src/components/internal/FormSectionRenderer.vue +0 -4
  298. package/src/components/internal/WellEditPopupInternal.vue +20 -5
  299. package/src/components/internal/WorkspaceControlsInternal.vue +20 -0
  300. package/src/components/internal/WorkspaceShellInternal.vue +125 -0
  301. package/src/components/internal/WorkspaceSidebarInternal.vue +82 -0
  302. package/src/composables/controlSchemaTypes.ts +34 -0
  303. package/src/composables/experimentDesignData.ts +1 -3
  304. package/src/composables/flattenWorkspaceBindings.ts +104 -0
  305. package/src/composables/formBuilderRegistry.ts +5 -0
  306. package/src/composables/index.ts +41 -5
  307. package/src/composables/pluginWorkspaceModel.ts +182 -0
  308. package/src/composables/useAsync.ts +5 -1
  309. package/src/composables/useBioTemplatePackWorkspace.ts +15 -9
  310. package/src/composables/useBioTemplatePresetWorkspace.ts +14 -15
  311. package/src/composables/useBioTemplateWorkspace.ts +18 -43
  312. package/src/composables/useCommandHistory.ts +5 -1
  313. package/src/composables/useDropdownState.ts +35 -5
  314. package/src/composables/useEventStream.ts +326 -0
  315. package/src/composables/useFileImport.ts +2 -7
  316. package/src/composables/useFocusTrap.ts +91 -0
  317. package/src/composables/useGeneratedAnalysis.ts +46 -103
  318. package/src/composables/useJobsStatusTray.ts +1 -1
  319. package/src/composables/useListReorder.story.vue +143 -0
  320. package/src/composables/useListReorder.ts +242 -0
  321. package/src/composables/useMenuKeyboard.ts +90 -0
  322. package/src/composables/useOptimisticMutation.ts +6 -16
  323. package/src/composables/usePluginClient.ts +91 -252
  324. package/src/composables/usePluginConfig.ts +3 -1
  325. package/src/composables/usePluginWorkspace.ts +208 -0
  326. package/src/composables/useRackEditor.ts +2 -11
  327. package/src/composables/useRequestSyncState.ts +98 -28
  328. package/src/composables/useResourceCrud.ts +6 -16
  329. package/src/composables/useRovingFocus.ts +66 -0
  330. package/src/composables/useScheduleDrag.ts +37 -0
  331. package/src/composables/useWellPainting.ts +10 -30
  332. package/src/composables/useWellPlateAdapter.ts +5 -1
  333. package/src/composables/useWellPlateEditor.ts +1 -11
  334. package/src/composables/useWellPlateValidation.ts +5 -1
  335. package/src/composables/workspaceRecipes.ts +267 -0
  336. package/src/index.ts +16 -0
  337. package/src/permissions.ts +48 -9
  338. package/src/stores/experiment.ts +2 -7
  339. package/src/stores/index.ts +9 -1
  340. package/src/stores/settings.ts +93 -1
  341. package/src/styles/components/audit-trail.css +5 -5
  342. package/src/styles/components/batch-progress-list.css +7 -0
  343. package/src/styles/components/color-slider.css +2 -2
  344. package/src/styles/components/data-state.css +30 -0
  345. package/src/styles/components/dataframe.css +29 -35
  346. package/src/styles/components/experiment-data-viewer.css +4 -4
  347. package/src/styles/components/experiment-timeline.css +3 -30
  348. package/src/styles/components/form-builder.css +5 -5
  349. package/src/styles/components/lcms-sequence-table.css +16 -1
  350. package/src/styles/components/multi-select.css +1 -1
  351. package/src/styles/components/reagent-list.css +38 -31
  352. package/src/styles/components/sample-hierarchy-tree.css +5 -19
  353. package/src/styles/components/sample-selector.css +9 -2
  354. package/src/styles/components/schedule-calendar.css +8 -0
  355. package/src/styles/components/scientific-number.css +1 -1
  356. package/src/styles/components/secret-input.css +60 -0
  357. package/src/styles/components/well-plate.css +8 -0
  358. package/src/styles/index.css +9 -0
  359. package/src/styles/variables.css +29 -0
  360. package/src/templates/builderPresetControls.ts +1 -1
  361. package/src/templates/builderReadUtils.ts +1 -3
  362. package/src/templates/componentPlateHelpers.ts +3 -1
  363. package/src/templates/componentTargetResolvers.ts +1 -3
  364. package/src/templates/controlSchemaTargets.ts +1 -3
  365. package/src/templates/doseResponseAdapters.ts +2 -13
  366. package/src/templates/elisaAssayCollectionBuilder.ts +2 -2
  367. package/src/templates/plateMapBuilder.ts +2 -2
  368. package/src/templates/qpcrPlateBuilder.ts +1 -1
  369. package/src/templates/templateValidators.ts +1 -1
  370. package/src/templates/timeCourseBuilder.ts +2 -2
  371. package/src/templates/wellPlateScreenCollectionBuilder.ts +2 -2
  372. package/src/types/form-builder.ts +1 -0
  373. package/src/utils/color.ts +51 -0
  374. package/src/utils/errors.ts +29 -0
  375. package/src/utils/formModelSync.ts +1 -3
  376. package/src/utils/pluginIcon.ts +1 -3
  377. package/src/utils/pluginSecrets.ts +102 -0
  378. package/src/utils/records.ts +9 -0
  379. package/dist/EmptyState-p90quq8Z.js.map +0 -1
  380. package/dist/ExperimentPopover-tLwJ7XF4.js.map +0 -1
  381. package/dist/ExperimentSelectorModal-B6P2msT4.js.map +0 -1
  382. package/dist/SettingsModal-BW3Ar-uy.js.map +0 -1
  383. package/dist/components-DQt0tcpY.js.map +0 -1
  384. package/dist/composables/autoGroupConstants.d.ts +0 -1
  385. package/dist/composables/autoGroupGrouping.d.ts +0 -3
  386. package/dist/composables/useAutoGroupInputSources.d.ts +0 -32
  387. package/dist/composables-CkXDe7nm.js.map +0 -1
  388. package/dist/experiment-Y9Iz7KYi.js.map +0 -1
  389. package/dist/experiment-utils-CLnzPPq5.js.map +0 -1
  390. package/dist/templates/builderDefaults.d.ts +0 -1
  391. package/dist/templates/plateGeometry.d.ts +0 -4
  392. package/dist/templates-CovvRZ-9.js.map +0 -1
  393. package/dist/useApi-CDBq6z23.js.map +0 -1
  394. package/dist/useControlSchema-BhoJzWzx.js.map +0 -1
  395. package/dist/useDropdownState-DSb3BC3N.js.map +0 -1
  396. package/dist/useProtocolTemplates-DHwSveE6.js.map +0 -1
  397. package/src/__tests__/composables/useAutoGroupInputSources.test.ts +0 -127
  398. package/src/composables/autoGroupConstants.ts +0 -4
  399. package/src/composables/autoGroupGrouping.ts +0 -148
  400. package/src/composables/useAutoGroupInputSources.ts +0 -147
  401. package/src/templates/builderDefaults.ts +0 -11
  402. package/src/templates/plateGeometry.ts +0 -62
  403. /package/dist/__tests__/{composables/useAutoGroupInputSources.test.d.ts → components/DataStates.test.d.ts} +0 -0
@@ -0,0 +1,90 @@
1
+ import { nextTick } from 'vue'
2
+
3
+ export interface UseMenuKeyboardOptions {
4
+ /** Returns the currently navigable items inside the open panel, in DOM order. */
5
+ items: () => HTMLElement[]
6
+ /** True while the panel is open. */
7
+ isOpen: () => boolean
8
+ /** Opens the panel. */
9
+ open: () => void
10
+ /** Closes the panel. When `returnFocus` is true, focus should return to the trigger. */
11
+ close: (returnFocus?: boolean) => void
12
+ }
13
+
14
+ export interface UseMenuKeyboardReturn {
15
+ /**
16
+ * Bind to the trigger's `@keydown`. ArrowDown/Enter/Space open the panel (when
17
+ * closed) and focus its first item; ArrowUp opens it focused on the last item.
18
+ */
19
+ handleTriggerKeydown: (event: KeyboardEvent) => void
20
+ /**
21
+ * Bind to the open panel's `@keydown`. ArrowUp/ArrowDown cycle focus with
22
+ * wraparound, Home/End jump to the first/last item, Escape closes and returns
23
+ * focus to the trigger, and Tab closes without moving focus.
24
+ */
25
+ handlePanelKeydown: (event: KeyboardEvent) => void
26
+ }
27
+
28
+ /**
29
+ * Shared keyboard contract for menu- and listbox-style disclosure panels (the
30
+ * WAI-ARIA menu button pattern). Used by ActionMenu, AppAvatarMenu and DropdownButton,
31
+ * each pairing it with `useDropdownState` for the disclosure state itself.
32
+ */
33
+ export function useMenuKeyboard(options: UseMenuKeyboardOptions): UseMenuKeyboardReturn {
34
+ function focusItem(position: 'first' | 'last') {
35
+ void nextTick(() => {
36
+ const items = options.items()
37
+ const target = position === 'first' ? items[0] : items[items.length - 1]
38
+ target?.focus()
39
+ })
40
+ }
41
+
42
+ function handleTriggerKeydown(event: KeyboardEvent) {
43
+ if (options.isOpen()) return
44
+
45
+ if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') {
46
+ event.preventDefault()
47
+ options.open()
48
+ focusItem('first')
49
+ return
50
+ }
51
+ if (event.key === 'ArrowUp') {
52
+ event.preventDefault()
53
+ options.open()
54
+ focusItem('last')
55
+ }
56
+ }
57
+
58
+ function handlePanelKeydown(event: KeyboardEvent) {
59
+ const items = options.items()
60
+ const currentIndex = items.indexOf(document.activeElement as HTMLElement)
61
+
62
+ if (event.key === 'Escape') {
63
+ event.preventDefault()
64
+ options.close(true)
65
+ return
66
+ }
67
+ if (event.key === 'Tab') {
68
+ options.close()
69
+ return
70
+ }
71
+ if (event.key === 'Home') {
72
+ event.preventDefault()
73
+ items[0]?.focus()
74
+ return
75
+ }
76
+ if (event.key === 'End') {
77
+ event.preventDefault()
78
+ items[items.length - 1]?.focus()
79
+ return
80
+ }
81
+ if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return
82
+
83
+ event.preventDefault()
84
+ const direction = event.key === 'ArrowDown' ? 1 : -1
85
+ const nextIndex = (Math.max(currentIndex, 0) + direction + items.length) % items.length
86
+ items[nextIndex]?.focus()
87
+ }
88
+
89
+ return { handleTriggerKeydown, handlePanelKeydown }
90
+ }
@@ -1,4 +1,5 @@
1
1
  import { computed, ref, shallowRef, type ComputedRef, type Ref, type ShallowRef } from 'vue'
2
+ import { readErrorMessage } from '../utils/errors'
2
3
 
3
4
  export interface OptimisticMutationContext<TVariables, TSnapshot> {
4
5
  variables: TVariables
@@ -32,7 +33,11 @@ export interface UseOptimisticMutationReturn<TVariables, TData, TSnapshot = unkn
32
33
  reset: () => void
33
34
  }
34
35
 
35
- /** Run async mutations with optional optimistic local updates and rollback. */
36
+ /**
37
+ * Run async mutations with optional optimistic local updates and rollback.
38
+ *
39
+ * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `useRequestSyncState()` instead.
40
+ */
36
41
  export function useOptimisticMutation<TVariables, TData, TSnapshot = unknown>(
37
42
  options: UseOptimisticMutationOptions<TVariables, TData, TSnapshot>,
38
43
  ): UseOptimisticMutationReturn<TVariables, TData, TSnapshot> {
@@ -90,18 +95,3 @@ export function useOptimisticMutation<TVariables, TData, TSnapshot = unknown>(
90
95
  reset,
91
96
  }
92
97
  }
93
-
94
- function readErrorMessage(value: unknown): string {
95
- if (value instanceof Error && value.message) return value.message
96
- if (typeof value === 'string' && value.trim()) return value
97
- if (
98
- typeof value === 'object'
99
- && value !== null
100
- && 'message' in value
101
- && typeof (value as { message?: unknown }).message === 'string'
102
- && (value as { message: string }).message.trim()
103
- ) {
104
- return (value as { message: string }).message
105
- }
106
- return 'Request failed.'
107
- }
@@ -1,8 +1,6 @@
1
1
  import {
2
2
  computed,
3
- getCurrentInstance,
4
3
  onMounted,
5
- onUnmounted,
6
4
  ref,
7
5
  shallowRef,
8
6
  watch,
@@ -17,6 +15,7 @@ import {
17
15
  import { usePlatformContext } from './usePlatformContext'
18
16
  import { useRequestSyncState } from './useRequestSyncState'
19
17
  import { useAuthStore } from '../stores/auth'
18
+ import { PLUGIN_SECRET_FORMAT_KEY } from '../utils/pluginSecrets'
20
19
  import {
21
20
  currentExperimentFromContext,
22
21
  getInjectedPlatformContext,
@@ -28,6 +27,12 @@ import {
28
27
  pluginEndpointRequestParts,
29
28
  requestBodyFromPayload,
30
29
  } from './pluginEndpointBuilder'
30
+ import {
31
+ useEventStream,
32
+ type EventStreamMessage,
33
+ type EventStreamTransport,
34
+ type UseEventStreamReturn,
35
+ } from './useEventStream'
31
36
  import type {
32
37
  ExperimentSummary,
33
38
  GeneratedJobDefinition,
@@ -204,13 +209,7 @@ export interface UsePluginSettingsReturn<TSettings = Record<string, unknown>> {
204
209
  reset: () => void
205
210
  }
206
211
 
207
- export interface PluginEventStreamMessage<TData = string> {
208
- event: string
209
- data: TData
210
- id?: string
211
- retry?: number
212
- raw: string
213
- }
212
+ export type PluginEventStreamMessage<TData = string> = EventStreamMessage<TData>
214
213
 
215
214
  export interface PluginEventStreamOptions<TData = string> {
216
215
  /** Override the generated or platform-injected API base URL. */
@@ -232,15 +231,7 @@ export interface PluginEventStreamOptions<TData = string> {
232
231
  onError?: (error: unknown) => void
233
232
  }
234
233
 
235
- export interface UsePluginEventStreamReturn<TData = string> {
236
- isConnected: Ref<boolean>
237
- isConnecting: Ref<boolean>
238
- error: Ref<string | null>
239
- lastMessage: Ref<PluginEventStreamMessage<TData> | null>
240
- lastEventId: Ref<string | null>
241
- start: () => void
242
- stop: () => void
243
- }
234
+ export type UsePluginEventStreamReturn<TData = string> = UseEventStreamReturn<TData>
244
235
 
245
236
  export type PluginFormDataValue =
246
237
  | string
@@ -544,16 +535,36 @@ export async function downloadPluginEndpoint(
544
535
  return blob
545
536
  }
546
537
 
547
- /** Return a generated plugin client from setup code with a stable typed identity. */
538
+ function normalizePluginSettingsOptions(options: UsePluginSettingsOptions | string = {}): UsePluginSettingsOptions {
539
+ return typeof options === 'string' ? { pluginName: options } : options
540
+ }
541
+
542
+ /** @deprecated Use `useGeneratedPluginClient()` for generated clients. */
548
543
  export function usePluginClient<TClient>(client: TClient): TClient {
549
544
  return client
550
545
  }
551
546
 
552
- function normalizePluginSettingsOptions(options: UsePluginSettingsOptions | string = {}): UsePluginSettingsOptions {
553
- return typeof options === 'string' ? { pluginName: options } : options
547
+ const PLATFORM_OWNED_SETTINGS_KEY = 'allowed_experiment_types'
548
+
549
+ /**
550
+ * Secret settings travel as `{ "$secret": "<id>" }` references, so an untouched
551
+ * secret round-trips without ever exposing its value. Declaring the format on
552
+ * every write keeps a `null` unambiguous: it clears the stored secret instead of
553
+ * meaning "unchanged", which is what the deprecated placeholder form meant.
554
+ */
555
+ function withSecretFormat(
556
+ payload: Record<string, unknown>,
557
+ secretFormat: string | null,
558
+ ): Record<string, unknown> {
559
+ if (!secretFormat) return payload
560
+ return { ...payload, [PLUGIN_SECRET_FORMAT_KEY]: secretFormat }
554
561
  }
555
562
 
556
- const PLATFORM_OWNED_SETTINGS_KEY = 'allowed_experiment_types'
563
+ function responseSecretFormat(response: unknown): string | null {
564
+ if (!response || typeof response !== 'object') return null
565
+ const format = (response as Record<string, unknown>)[PLUGIN_SECRET_FORMAT_KEY]
566
+ return typeof format === 'string' && format ? format : null
567
+ }
557
568
 
558
569
  function cloneRecord(value: Record<string, unknown>): Record<string, unknown> {
559
570
  return JSON.parse(JSON.stringify(value)) as Record<string, unknown>
@@ -628,6 +639,7 @@ export function usePluginSettings<TSettings = Record<string, unknown>>(
628
639
  const values = ref({}) as Ref<PluginSettingsValues<TSettings>>
629
640
  const savedValues = shallowRef<Record<string, unknown>>({})
630
641
  const revision = ref<string | null>(null)
642
+ const secretFormat = ref<string | null>(null)
631
643
  const request = useRequestSyncState('Plugin settings request failed.')
632
644
  const isLoading = ref(false)
633
645
  const isSaving = ref(false)
@@ -660,11 +672,16 @@ export function usePluginSettings<TSettings = Record<string, unknown>>(
660
672
  values.value = cloneRecord(nextValues) as PluginSettingsValues<TSettings>
661
673
  }
662
674
 
663
- function applyLoaded(nextValues: Record<string, unknown>, nextRevision: string | null): void {
675
+ function applyLoaded(
676
+ nextValues: Record<string, unknown>,
677
+ nextRevision: string | null,
678
+ nextSecretFormat: string | null = secretFormat.value,
679
+ ): void {
664
680
  const cloned = cloneRecord(nextValues)
665
681
  values.value = cloned as PluginSettingsValues<TSettings>
666
682
  savedValues.value = cloneRecord(cloned)
667
683
  revision.value = nextRevision
684
+ secretFormat.value = nextSecretFormat
668
685
  }
669
686
 
670
687
  async function load(): Promise<void> {
@@ -684,6 +701,7 @@ export function usePluginSettings<TSettings = Record<string, unknown>>(
684
701
  applyLoaded(
685
702
  responseSettingsPayload(response),
686
703
  responseSettingsRevision(response),
704
+ responseSecretFormat(response),
687
705
  )
688
706
  } catch {
689
707
  // Error state is handled by request.run().
@@ -717,7 +735,12 @@ export function usePluginSettings<TSettings = Record<string, unknown>>(
717
735
  revision?: string
718
736
  }>(
719
737
  `/plugins/${encodeURIComponent(resolvedPluginName.value)}/config`,
720
- { config: topLevelSettingsPatch(payload, typedKeys) },
738
+ {
739
+ config: withSecretFormat(
740
+ topLevelSettingsPatch(payload, typedKeys),
741
+ secretFormat.value,
742
+ ),
743
+ },
721
744
  ),
722
745
  { success: 'save', errorMessage: 'Failed to save plugin settings' },
723
746
  )
@@ -740,7 +763,11 @@ export function usePluginSettings<TSettings = Record<string, unknown>>(
740
763
  }
741
764
 
742
765
  if (!response) return true
743
- applyLoaded(responseSettingsPayload(response), nextRevision)
766
+ applyLoaded(
767
+ responseSettingsPayload(response),
768
+ nextRevision,
769
+ responseSecretFormat(response) ?? secretFormat.value,
770
+ )
744
771
  return true
745
772
  } else {
746
773
  const ifMatch = revision.value
@@ -751,13 +778,14 @@ export function usePluginSettings<TSettings = Record<string, unknown>>(
751
778
  settings: Record<string, unknown>
752
779
  mode?: string
753
780
  revision?: string
754
- }>('/settings', payload, ifMatch),
781
+ }>('/settings', withSecretFormat(payload, secretFormat.value), ifMatch),
755
782
  { success: 'save', errorMessage: 'Failed to save plugin settings' },
756
783
  )
757
784
  }
758
785
  applyLoaded(
759
786
  responseSettingsPayload(response),
760
787
  responseSettingsRevision(response) ?? revision.value,
788
+ responseSecretFormat(response) ?? secretFormat.value,
761
789
  )
762
790
  return true
763
791
  } catch {
@@ -797,13 +825,13 @@ export function usePluginSettings<TSettings = Record<string, unknown>>(
797
825
  }
798
826
 
799
827
  function streamRequestAuth(
800
- options: PluginEventStreamOptions<unknown>,
828
+ requestHeaders: HeadersInit | undefined,
801
829
  policy: { requiresAuth: boolean },
802
830
  ): {
803
831
  headers: Headers
804
832
  token?: string
805
833
  } {
806
- const headers = new Headers(options.headers)
834
+ const headers = new Headers(requestHeaders)
807
835
  const authStore = useAuthStore()
808
836
  if (!authStore.isInitialized) {
809
837
  authStore.initialize()
@@ -811,7 +839,6 @@ function streamRequestAuth(
811
839
  if (policy.requiresAuth && authStore.token && !headers.has('Authorization')) {
812
840
  headers.set('Authorization', `Bearer ${authStore.token}`)
813
841
  }
814
- headers.set('Accept', 'text/event-stream')
815
842
  const token = policy.requiresAuth ? authStore.token : undefined
816
843
  return {
817
844
  headers,
@@ -819,40 +846,22 @@ function streamRequestAuth(
819
846
  }
820
847
  }
821
848
 
822
- function parseSseEvent<TData>(
823
- block: string,
824
- parseJson: boolean,
825
- ): PluginEventStreamMessage<TData> | null {
826
- let event = 'message'
827
- let id: string | undefined
828
- let retry: number | undefined
829
- const dataLines: string[] = []
830
-
831
- for (const line of block.split(/\r?\n/)) {
832
- if (!line || line.startsWith(':')) continue
833
- const separator = line.indexOf(':')
834
- const field = separator === -1 ? line : line.slice(0, separator)
835
- const value = separator === -1
836
- ? ''
837
- : line.slice(separator + 1).replace(/^ /, '')
838
-
839
- if (field === 'event') event = value || 'message'
840
- if (field === 'data') dataLines.push(value)
841
- if (field === 'id') id = value
842
- if (field === 'retry') {
843
- const parsed = Number(value)
844
- if (Number.isFinite(parsed)) retry = parsed
849
+ function pluginEventStreamTransport(
850
+ endpoint: PluginEndpointDefinition,
851
+ ): EventStreamTransport {
852
+ return async (url, init = {}) => {
853
+ if (typeof fetch !== 'function') {
854
+ throw new Error('[MINT SDK] fetch is required for plugin event streams.')
845
855
  }
846
- }
847
-
848
- if (!dataLines.length && !id && retry === undefined) return null
849
- const data = dataLines.join('\n')
850
- return {
851
- event,
852
- data: (parseJson && data ? JSON.parse(data) : data) as TData,
853
- id,
854
- retry,
855
- raw: block,
856
+ const requestAuth = streamRequestAuth(
857
+ init.headers,
858
+ { requiresAuth: endpoint.requiresAuth !== false },
859
+ )
860
+ const response = await fetch(url, { ...init, headers: requestAuth.headers })
861
+ if (response.status === 401) {
862
+ throw authenticationRequiredError(response, requestAuth.token)
863
+ }
864
+ return response
856
865
  }
857
866
  }
858
867
 
@@ -891,6 +900,9 @@ export function usePluginEventStream<TData = string>(
891
900
  payloadOrOptions?: unknown,
892
901
  maybeOptions?: PluginEventStreamOptions<TData>,
893
902
  ): UsePluginEventStreamReturn<TData> {
903
+ if (endpoint.method !== 'get') {
904
+ throw new Error(`[MINT SDK] Plugin event streams must use GET; got ${endpoint.method}`)
905
+ }
894
906
  const payload = maybeOptions === undefined && looksLikeEventStreamOptions(payloadOrOptions)
895
907
  ? undefined
896
908
  : payloadOrOptions
@@ -899,198 +911,25 @@ export function usePluginEventStream<TData = string>(
899
911
  ? payloadOrOptions
900
912
  : maybeOptions ?? {}
901
913
  ) as PluginEventStreamOptions<TData>
902
- const isConnected = ref(false)
903
- const isConnecting = ref(false)
904
- const error = ref<string | null>(null)
905
- const lastMessage = shallowRef<PluginEventStreamMessage<TData> | null>(null)
906
- const lastEventId = ref<string | null>(null)
907
914
  const responseType = endpoint.responseType?.trim()
908
915
  const parseJson = options.parseJson ?? Boolean(responseType && responseType !== 'string')
909
- let controller: AbortController | null = null
910
- let reconnectTimer: ReturnType<typeof setTimeout> | null = null
911
- let stopped = true
912
- let generation = 0
913
-
914
- function clearReconnectTimer(): void {
915
- if (reconnectTimer !== null) {
916
- clearTimeout(reconnectTimer)
917
- reconnectTimer = null
918
- }
919
- }
920
-
921
- function ownsConnection(
922
- connectionGeneration: number,
923
- connectionController: AbortController,
924
- ): boolean {
925
- return !stopped
926
- && generation === connectionGeneration
927
- && controller === connectionController
928
- }
929
-
930
- function scheduleReconnect(connectionGeneration: number): void {
931
- if (
932
- stopped
933
- || generation !== connectionGeneration
934
- || options.reconnect === false
935
- ) return
936
- clearReconnectTimer()
937
- reconnectTimer = setTimeout(() => {
938
- reconnectTimer = null
939
- if (stopped || generation !== connectionGeneration) return
940
- void connect(connectionGeneration)
941
- }, options.reconnectDelayMs ?? 2000)
942
- }
943
-
944
- async function connect(connectionGeneration: number): Promise<void> {
945
- if (stopped || generation !== connectionGeneration) return
946
- if (endpoint.method !== 'get') {
947
- throw new Error(`[MINT SDK] Plugin event streams must use GET; got ${endpoint.method}`)
948
- }
949
- if (typeof fetch !== 'function') {
950
- throw new Error('[MINT SDK] fetch is required for plugin event streams.')
951
- }
952
-
953
- controller?.abort()
954
- const connectionController = new AbortController()
955
- controller = connectionController
956
- isConnecting.value = true
957
- if (!ownsConnection(connectionGeneration, connectionController)) return
958
- error.value = null
959
- if (!ownsConnection(connectionGeneration, connectionController)) return
960
-
961
- let authenticationFailed = false
962
- try {
963
- const url = buildPluginEndpointUrl(contract, endpoint, payload, {
964
- baseUrl: options.baseUrl,
965
- })
966
- const requestAuth = streamRequestAuth(
967
- options as PluginEventStreamOptions<unknown>,
968
- { requiresAuth: endpoint.requiresAuth !== false },
969
- )
970
- const response = await fetch(url, {
971
- method: 'GET',
972
- headers: requestAuth.headers,
973
- credentials: options.credentials ?? 'same-origin',
974
- signal: connectionController.signal,
975
- })
976
-
977
- if (!ownsConnection(connectionGeneration, connectionController)) return
978
-
979
- if (!response.ok) {
980
- if (response.status === 401) {
981
- authenticationFailed = true
982
- throw authenticationRequiredError(response, requestAuth.token)
983
- }
984
- throw new Error(`Plugin event stream failed with HTTP ${response.status}`)
985
- }
986
- if (!response.body) {
987
- throw new Error('Plugin event stream response did not include a readable body.')
988
- }
989
-
990
- isConnected.value = true
991
- if (!ownsConnection(connectionGeneration, connectionController)) return
992
- options.onOpen?.()
993
- if (!ownsConnection(connectionGeneration, connectionController)) return
994
- const reader = response.body.getReader()
995
- const decoder = new TextDecoder()
996
- let buffer = ''
997
-
998
- for (;;) {
999
- const { value, done } = await reader.read()
1000
- if (!ownsConnection(connectionGeneration, connectionController)) return
1001
- if (done) break
1002
- buffer += decoder.decode(value, { stream: true })
1003
-
1004
- let boundary = buffer.search(/\r?\n\r?\n/)
1005
- while (boundary !== -1) {
1006
- const block = buffer.slice(0, boundary)
1007
- buffer = buffer.slice(buffer[boundary] === '\r' ? boundary + 4 : boundary + 2)
1008
- const message = parseSseEvent<TData>(block, parseJson)
1009
- if (message) {
1010
- lastMessage.value = message
1011
- if (!ownsConnection(connectionGeneration, connectionController)) return
1012
- if (message.id !== undefined) {
1013
- lastEventId.value = message.id
1014
- if (!ownsConnection(connectionGeneration, connectionController)) return
1015
- }
1016
- if (message.retry !== undefined) {
1017
- options.reconnectDelayMs = message.retry
1018
- }
1019
- if (!ownsConnection(connectionGeneration, connectionController)) return
1020
- options.onMessage?.(message)
1021
- if (!ownsConnection(connectionGeneration, connectionController)) return
1022
- }
1023
- boundary = buffer.search(/\r?\n\r?\n/)
1024
- }
1025
- }
1026
- } catch (err) {
1027
- if (err instanceof AuthenticationRequiredError) authenticationFailed = true
1028
- if (
1029
- ownsConnection(connectionGeneration, connectionController)
1030
- && !(err instanceof DOMException && err.name === 'AbortError')
1031
- ) {
1032
- const message = err instanceof Error ? err.message : 'Plugin event stream failed'
1033
- error.value = message
1034
- if (ownsConnection(connectionGeneration, connectionController)) {
1035
- options.onError?.(err)
1036
- }
1037
- }
1038
- } finally {
1039
- if (ownsConnection(connectionGeneration, connectionController)) {
1040
- isConnecting.value = false
1041
- if (ownsConnection(connectionGeneration, connectionController)) {
1042
- isConnected.value = false
1043
- if (ownsConnection(connectionGeneration, connectionController)) {
1044
- controller = null
1045
- if (authenticationFailed) {
1046
- stopped = true
1047
- } else {
1048
- scheduleReconnect(connectionGeneration)
1049
- }
1050
- }
1051
- }
1052
- }
1053
- }
1054
- }
1055
-
1056
- function start(): void {
1057
- if (!stopped) return
1058
- stopped = false
1059
- clearReconnectTimer()
1060
- generation += 1
1061
- void connect(generation)
1062
- }
1063
-
1064
- function stop(): void {
1065
- if (stopped) return
1066
- stopped = true
1067
- generation += 1
1068
- clearReconnectTimer()
1069
- controller?.abort()
1070
- controller = null
1071
- isConnecting.value = false
1072
- isConnected.value = false
1073
- }
1074
-
1075
- const currentInstance = getCurrentInstance()
1076
- if (currentInstance && options.immediate !== false && typeof window === 'undefined') {
1077
- onMounted(start)
1078
- }
1079
- if (currentInstance) onUnmounted(stop)
1080
-
1081
- if (options.immediate !== false && (typeof window !== 'undefined' || !currentInstance)) {
1082
- start()
1083
- }
1084
-
1085
- return {
1086
- isConnected,
1087
- isConnecting,
1088
- error,
1089
- lastMessage,
1090
- lastEventId,
1091
- start,
1092
- stop,
1093
- }
916
+ return useEventStream<TData>(
917
+ () => buildPluginEndpointUrl(contract, endpoint, payload, { baseUrl: options.baseUrl }),
918
+ {
919
+ transport: pluginEventStreamTransport(endpoint),
920
+ immediate: options.immediate,
921
+ reconnect: options.reconnect,
922
+ reconnectDelayMs: options.reconnectDelayMs,
923
+ parseJson,
924
+ credentials: options.credentials,
925
+ headers: options.headers,
926
+ shouldReconnect: cause => !(cause instanceof AuthenticationRequiredError),
927
+ onOpen: options.onOpen,
928
+ onMessage: options.onMessage,
929
+ onError: options.onError,
930
+ errorLabel: 'Plugin event stream',
931
+ },
932
+ )
1094
933
  }
1095
934
 
1096
935
  /** Read and optionally load the current platform experiment for integrated plugin views. */
@@ -75,7 +75,9 @@ export interface UsePluginConfigReturn {
75
75
  reset: () => void
76
76
  }
77
77
 
78
- /** Loads, saves, and tracks dirty state for a plugin's persistent configuration via the platform API. */
78
+ /**
79
+ * @deprecated Unused by the MINT platform and scheduled for removal in MINT 1.3; use `usePluginSettings()` for typed plugin settings.
80
+ */
79
81
  export function usePluginConfig(pluginName?: string): UsePluginConfigReturn {
80
82
  const injectedContext = getInjectedPlatformContext()
81
83
  const { plugin } = usePlatformContext()