@morscherlab/mint-sdk 1.2.0-beta.3 → 1.2.0-beta.4

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 (1017) hide show
  1. package/README.md +8 -2
  2. package/dist/EmptyState-p90quq8Z.js +2 -0
  3. package/dist/EmptyState-p90quq8Z.js.map +1 -0
  4. package/dist/{ExperimentPopover-Bn6PIGHE.js → ExperimentPopover-tLwJ7XF4.js} +10 -5
  5. package/dist/ExperimentPopover-tLwJ7XF4.js.map +1 -0
  6. package/dist/{ExperimentSelectorModal-DGhrJSSV.js → ExperimentSelectorModal-B6P2msT4.js} +11 -6
  7. package/dist/ExperimentSelectorModal-B6P2msT4.js.map +1 -0
  8. package/dist/{SettingsModal-wF2btHu6.js → SettingsModal-CkNM8qAI.js} +12 -7
  9. package/dist/SettingsModal-CkNM8qAI.js.map +1 -0
  10. package/dist/__stories__/experiment-helpers.d.ts +28 -0
  11. package/dist/__tests__/components/ActionItem.test.d.ts +1 -0
  12. package/dist/__tests__/components/ActionMenu.test.d.ts +1 -0
  13. package/dist/__tests__/components/AppAvatarMenu.test.d.ts +1 -0
  14. package/dist/__tests__/components/AppLayout.test.d.ts +1 -0
  15. package/dist/__tests__/components/AppPluginSwitcher.test.d.ts +1 -0
  16. package/dist/__tests__/components/AppSidebar.test.d.ts +1 -0
  17. package/dist/__tests__/components/AppToastContainer.test.d.ts +1 -0
  18. package/dist/__tests__/components/AppTopBar.navigation.test.d.ts +1 -0
  19. package/dist/__tests__/components/AppTopBar.test.d.ts +1 -0
  20. package/dist/__tests__/components/AppTopBarPageSelector.test.d.ts +1 -0
  21. package/dist/__tests__/components/AppTopBarPillNav.test.d.ts +1 -0
  22. package/dist/__tests__/components/AppTopBarPresence.test.d.ts +1 -0
  23. package/dist/__tests__/components/ArtifactSaveDialog.test.d.ts +1 -0
  24. package/dist/__tests__/components/ArtifactSelectorModal.test.d.ts +1 -0
  25. package/dist/__tests__/components/AutoGroupModal.adapter.test.d.ts +1 -0
  26. package/dist/__tests__/components/BaseInput.test.d.ts +1 -0
  27. package/dist/__tests__/components/BaseModal.test.d.ts +1 -0
  28. package/dist/__tests__/components/BasePill.test.d.ts +1 -0
  29. package/dist/__tests__/components/BaseRadioGroup.test.d.ts +1 -0
  30. package/dist/__tests__/components/BaseSelect.test.d.ts +1 -0
  31. package/dist/__tests__/components/BaseTabs.test.d.ts +1 -0
  32. package/dist/__tests__/components/BaseToggle.test.d.ts +1 -0
  33. package/dist/__tests__/components/BatchProgressList.test.d.ts +1 -0
  34. package/dist/__tests__/components/BioTemplateExperimentWorkspaceView.test.d.ts +1 -0
  35. package/dist/__tests__/components/BioTemplatePackWorkspaceView.test.d.ts +1 -0
  36. package/dist/__tests__/components/BioTemplatePresetWorkspaceView.test.d.ts +1 -0
  37. package/dist/__tests__/components/BioTemplateRenderer.test.d.ts +1 -0
  38. package/dist/__tests__/components/Breadcrumb.test.d.ts +1 -0
  39. package/dist/__tests__/components/Calendar.test.d.ts +1 -0
  40. package/dist/__tests__/components/CalendarGridPanel.test.d.ts +1 -0
  41. package/dist/__tests__/components/CollapsibleCard.test.d.ts +1 -0
  42. package/dist/__tests__/components/ComponentBindingRenderer.test.d.ts +1 -0
  43. package/dist/__tests__/components/ConcentrationInput.test.d.ts +1 -0
  44. package/dist/__tests__/components/ControlWorkspaceView.test.d.ts +1 -0
  45. package/dist/__tests__/components/DataFrame.test.d.ts +1 -0
  46. package/dist/__tests__/components/DatePicker.test.d.ts +1 -0
  47. package/dist/__tests__/components/DateTimePicker.test.d.ts +1 -0
  48. package/dist/__tests__/components/DoseCalculatorVolumeField.test.d.ts +1 -0
  49. package/dist/__tests__/components/DoseDesignWorkspaceView.test.d.ts +1 -0
  50. package/dist/__tests__/components/DropdownButton.test.d.ts +1 -0
  51. package/dist/__tests__/components/EmptyState.test.d.ts +1 -0
  52. package/dist/__tests__/components/ExperimentPopover.test.d.ts +1 -0
  53. package/dist/__tests__/components/ExperimentSelectorModal.test.d.ts +1 -0
  54. package/dist/__tests__/components/FormBuilder.test.d.ts +1 -0
  55. package/dist/__tests__/components/GeneratedPathInput.test.d.ts +1 -0
  56. package/dist/__tests__/components/GeneratedPlotlyResult.test.d.ts +1 -0
  57. package/dist/__tests__/components/GeneratedPluginView.test.d.ts +1 -0
  58. package/dist/__tests__/components/GeneratedResultRenderer.test.d.ts +1 -0
  59. package/dist/__tests__/components/GroupAssigner.test.d.ts +1 -0
  60. package/dist/__tests__/components/InstrumentAlertLog.test.d.ts +1 -0
  61. package/dist/__tests__/components/JobsStatusTray.test.d.ts +1 -0
  62. package/dist/__tests__/components/LcmsSequenceTable.test.d.ts +1 -0
  63. package/dist/__tests__/components/MobileSupportGate.test.d.ts +1 -0
  64. package/dist/__tests__/components/MultiSelect.test.d.ts +1 -0
  65. package/dist/__tests__/components/PlateMapEditorToolbarInternal.test.d.ts +1 -0
  66. package/dist/__tests__/components/PluginIcon.test.d.ts +1 -0
  67. package/dist/__tests__/components/PluginWorkspaceView.controls.test.d.ts +1 -0
  68. package/dist/__tests__/components/PluginWorkspaceView.navigation.test.d.ts +1 -0
  69. package/dist/__tests__/components/PluginWorkspaceView.shell.test.d.ts +1 -0
  70. package/dist/__tests__/components/PluginWorkspaceView.test.d.ts +1 -0
  71. package/dist/__tests__/components/ProgressBar.test.d.ts +1 -0
  72. package/dist/__tests__/components/ProtocolStep.presentation.test.d.ts +1 -0
  73. package/dist/__tests__/components/ProtocolStepEditor.state.test.d.ts +1 -0
  74. package/dist/__tests__/components/ProtocolStepEditor.test.d.ts +1 -0
  75. package/dist/__tests__/components/ProtocolStepParameterField.test.d.ts +1 -0
  76. package/dist/__tests__/components/RackEditor.test.d.ts +1 -0
  77. package/dist/__tests__/components/ReagentList.presentation.test.d.ts +1 -0
  78. package/dist/__tests__/components/ReagentList.test.d.ts +1 -0
  79. package/dist/__tests__/components/RetiredStyles.test.d.ts +1 -0
  80. package/dist/__tests__/components/RuntimeUpdateNotice.test.d.ts +1 -0
  81. package/dist/__tests__/components/SampleHierarchyTree.test.d.ts +1 -0
  82. package/dist/__tests__/components/SampleSelector.colors.test.d.ts +1 -0
  83. package/dist/__tests__/components/SampleSelector.drag.test.d.ts +1 -0
  84. package/dist/__tests__/components/SampleSelector.groups.test.d.ts +1 -0
  85. package/dist/__tests__/components/SampleSelector.selection.test.d.ts +1 -0
  86. package/dist/__tests__/components/SampleSelector.test.d.ts +1 -0
  87. package/dist/__tests__/components/SampleSelectorSampleRow.test.d.ts +1 -0
  88. package/dist/__tests__/components/ScheduleCalendar.test.d.ts +1 -0
  89. package/dist/__tests__/components/SectionCard.test.d.ts +1 -0
  90. package/dist/__tests__/components/SegmentedControl.test.d.ts +1 -0
  91. package/dist/__tests__/components/SequenceProgressBar.test.d.ts +1 -0
  92. package/dist/__tests__/components/SettingsModal.schema.test.d.ts +1 -0
  93. package/dist/__tests__/components/SettingsModal.test.d.ts +1 -0
  94. package/dist/__tests__/components/SmartGroupFieldRecipe.groups.test.d.ts +1 -0
  95. package/dist/__tests__/components/SmartGroupManual.cohorts.test.d.ts +1 -0
  96. package/dist/__tests__/components/TagsInput.test.d.ts +1 -0
  97. package/dist/__tests__/components/ThemeToggle.test.d.ts +1 -0
  98. package/dist/__tests__/components/TimePicker.test.d.ts +1 -0
  99. package/dist/__tests__/components/WellPlate.colors.test.d.ts +1 -0
  100. package/dist/__tests__/components/WellPlate.conditions.test.d.ts +1 -0
  101. package/dist/__tests__/components/WellPlate.geometry.test.d.ts +1 -0
  102. package/dist/__tests__/components/WellPlate.interaction.test.d.ts +1 -0
  103. package/dist/__tests__/components/WellPlate.legend.test.d.ts +1 -0
  104. package/dist/__tests__/components/WellPlate.rendering.test.d.ts +1 -0
  105. package/dist/__tests__/components/WellPlate.sampleDrop.test.d.ts +1 -0
  106. package/dist/__tests__/composables/analysisArtifactTarget.test.d.ts +1 -0
  107. package/dist/__tests__/composables/autoGroup/classKey.test.d.ts +1 -0
  108. package/dist/__tests__/composables/autoGroup/classify.test.d.ts +1 -0
  109. package/dist/__tests__/composables/autoGroup/columns.test.d.ts +1 -0
  110. package/dist/__tests__/composables/autoGroup/compose.test.d.ts +1 -0
  111. package/dist/__tests__/composables/autoGroup/cooccurrence.test.d.ts +1 -0
  112. package/dist/__tests__/composables/autoGroup/fingerprint.test.d.ts +1 -0
  113. package/dist/__tests__/composables/autoGroup/groupByOrder.test.d.ts +1 -0
  114. package/dist/__tests__/composables/autoGroup/groupTree.test.d.ts +1 -0
  115. package/dist/__tests__/composables/autoGroup/integration.test.d.ts +1 -0
  116. package/dist/__tests__/composables/autoGroup/template.test.d.ts +1 -0
  117. package/dist/__tests__/composables/autoGroup/tokenLength.test.d.ts +1 -0
  118. package/dist/__tests__/composables/autoGroup/tokenize.test.d.ts +1 -0
  119. package/dist/__tests__/composables/experiment-utils.test.d.ts +1 -0
  120. package/dist/__tests__/composables/formBuilderRegistry.test.d.ts +1 -0
  121. package/dist/__tests__/composables/resolvePluginFrontendBase.test.d.ts +1 -0
  122. package/dist/__tests__/composables/useAnalysisArtifacts.test.d.ts +1 -0
  123. package/dist/__tests__/composables/useApi.test.d.ts +1 -0
  124. package/dist/__tests__/composables/useAppExperiment.test.d.ts +1 -0
  125. package/dist/__tests__/composables/useAuth.test.d.ts +1 -0
  126. package/dist/__tests__/composables/useAutoGroup.test.d.ts +1 -0
  127. package/dist/__tests__/composables/useAutoGroupInputSources.test.d.ts +1 -0
  128. package/dist/__tests__/composables/useBioTemplatePackWorkspace.test.d.ts +1 -0
  129. package/dist/__tests__/composables/useBioTemplatePresetWorkspace.test.d.ts +1 -0
  130. package/dist/__tests__/composables/useBioTemplateWorkspace.test.d.ts +1 -0
  131. package/dist/__tests__/composables/useCalendarGrid.test.d.ts +1 -0
  132. package/dist/__tests__/composables/useCommandHistory.test.d.ts +1 -0
  133. package/dist/__tests__/composables/useControlSchema.test.d.ts +1 -0
  134. package/dist/__tests__/composables/useDebouncedWatch.test.d.ts +1 -0
  135. package/dist/__tests__/composables/useDropdownState.test.d.ts +1 -0
  136. package/dist/__tests__/composables/useEventListener.test.d.ts +1 -0
  137. package/dist/__tests__/composables/useEventStream.test.d.ts +1 -0
  138. package/dist/__tests__/composables/useExpansionSet.test.d.ts +1 -0
  139. package/dist/__tests__/composables/useExperimentData.test.d.ts +14 -0
  140. package/dist/__tests__/composables/useExperimentSamples.test.d.ts +1 -0
  141. package/dist/__tests__/composables/useExperimentSave.test.d.ts +1 -0
  142. package/dist/__tests__/composables/useExperimentSelector.test.d.ts +1 -0
  143. package/dist/__tests__/composables/useFileImport.test.d.ts +1 -0
  144. package/dist/__tests__/composables/useForm.test.d.ts +1 -0
  145. package/dist/__tests__/composables/useFormBuilder.test.d.ts +1 -0
  146. package/dist/__tests__/composables/useGeneratedAnalysis.test.d.ts +1 -0
  147. package/dist/__tests__/composables/useGroupAssignment.test.d.ts +1 -0
  148. package/dist/__tests__/composables/useJobsStatusTray.test.d.ts +1 -0
  149. package/dist/__tests__/composables/useListSelection.test.d.ts +1 -0
  150. package/dist/__tests__/composables/useMobileSupportGate.test.d.ts +1 -0
  151. package/dist/__tests__/composables/useOptimisticMutation.test.d.ts +1 -0
  152. package/dist/__tests__/composables/usePlatformContext.test.d.ts +1 -0
  153. package/dist/__tests__/composables/usePluginClient.test.d.ts +1 -0
  154. package/dist/__tests__/composables/usePluginConfig.test.d.ts +15 -0
  155. package/dist/__tests__/composables/usePresenceHeartbeat.test.d.ts +1 -0
  156. package/dist/__tests__/composables/useProtocolTemplates.test.d.ts +1 -0
  157. package/dist/__tests__/composables/useRequestSyncState.test.d.ts +1 -0
  158. package/dist/__tests__/composables/useResourceCrud.test.d.ts +1 -0
  159. package/dist/__tests__/composables/useRuntimeAlignment.test.d.ts +1 -0
  160. package/dist/__tests__/composables/useSampleGroups.test.d.ts +1 -0
  161. package/dist/__tests__/composables/useSampleGroups.tree.test.d.ts +1 -0
  162. package/dist/__tests__/composables/useScheduleCalendarLayout.test.d.ts +1 -0
  163. package/dist/__tests__/composables/useSelectionLimit.test.d.ts +1 -0
  164. package/dist/__tests__/composables/useSortedItems.test.d.ts +1 -0
  165. package/dist/__tests__/composables/useTemplateCollection.test.d.ts +1 -0
  166. package/dist/__tests__/composables/useTextSearch.test.d.ts +1 -0
  167. package/dist/__tests__/composables/useTheme.test.d.ts +1 -0
  168. package/dist/__tests__/composables/useTimeUtils.test.d.ts +1 -0
  169. package/dist/__tests__/composables/useWellPainting.test.d.ts +1 -0
  170. package/dist/__tests__/composables/useWellPlateAdapter.test.d.ts +1 -0
  171. package/dist/__tests__/composables/useWellPlateValidation.test.d.ts +1 -0
  172. package/dist/__tests__/docs/extractDocsComponents.test.d.ts +1 -0
  173. package/dist/__tests__/docs/extractDocsExports.test.d.ts +1 -0
  174. package/dist/__tests__/docs/extractDocsParsing.test.d.ts +1 -0
  175. package/dist/__tests__/docs/extractDocsTemplates.test.d.ts +1 -0
  176. package/dist/__tests__/docs/extractDocsTheme.test.d.ts +1 -0
  177. package/dist/__tests__/docs/frontendDocsCatalog.test.d.ts +1 -0
  178. package/dist/__tests__/generatedUi.test.d.ts +1 -0
  179. package/dist/__tests__/stores/experiment.test.d.ts +1 -0
  180. package/dist/__tests__/stores/settings.test.d.ts +1 -0
  181. package/dist/__tests__/templates/templates.test.d.ts +1 -0
  182. package/dist/__tests__/types/GeneratedJsonSchema.test.d.ts +1 -0
  183. package/dist/__tests__/utils/color.test.d.ts +1 -0
  184. package/dist/__tests__/utils/instrument.test.d.ts +1 -0
  185. package/dist/__tests__/utils/jobs.test.d.ts +1 -0
  186. package/dist/__tests__/utils/lcms.test.d.ts +1 -0
  187. package/dist/__tests__/utils/permissions.test.d.ts +1 -0
  188. package/dist/__tests__/utils/rack.test.d.ts +1 -0
  189. package/dist/{analysisArtifactTypes-ejqR8MX3.js → analysisArtifactTypes-DQ0MjwHZ.js} +2 -0
  190. package/dist/analysisArtifactTypes-DQ0MjwHZ.js.map +1 -0
  191. package/dist/chunk-BoAXSpZd.js +33 -0
  192. package/dist/components/AuditTrail.vue.d.ts +38 -0
  193. package/dist/components/AutoGroupModal.vue.d.ts +1 -1
  194. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +1 -1
  195. package/dist/components/ColorSlider.vue.d.ts +34 -0
  196. package/dist/components/DoseDesignWorkspaceView.vue.d.ts +149 -0
  197. package/dist/components/FitPanel.vue.d.ts +46 -0
  198. package/dist/components/GroupAssigner.vue.d.ts +25 -0
  199. package/dist/components/JobsStatusTray.vue.d.ts +11 -2
  200. package/dist/components/RackEditor.vue.d.ts +78 -0
  201. package/dist/components/ReagentEditor.vue.d.ts +30 -0
  202. package/dist/components/ResourceCard.vue.d.ts +50 -0
  203. package/dist/components/SampleLegend.vue.d.ts +1 -1
  204. package/dist/components/SampleSelector.vue.d.ts +1 -1
  205. package/dist/components/ScientificNumber.vue.d.ts +14 -0
  206. package/dist/components/SettingsModal.vue.d.ts +1 -1
  207. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +3 -3
  208. package/dist/components/SmartGroupManual.vue.d.ts +2 -2
  209. package/dist/components/WellPlate.vue.d.ts +1 -1
  210. package/dist/components/index.d.ts +9 -0
  211. package/dist/components/index.js +6 -6
  212. package/dist/{components-DpyzaeIc.js → components-MGNL6tRn.js} +3268 -1353
  213. package/dist/components-MGNL6tRn.js.map +1 -0
  214. package/dist/composables/autoGroupConstants.d.ts +1 -0
  215. package/dist/composables/autoGroupGrouping.d.ts +3 -0
  216. package/dist/composables/index.d.ts +10 -2
  217. package/dist/composables/index.js +9 -9
  218. package/dist/composables/useAnalysisArtifacts.d.ts +2 -0
  219. package/dist/composables/useAsync.d.ts +128 -0
  220. package/dist/composables/useAuth.d.ts +2 -0
  221. package/dist/composables/useAutoGroup.d.ts +30 -1
  222. package/dist/composables/useAutoGroupInputSources.d.ts +32 -0
  223. package/dist/composables/useCommandHistory.d.ts +29 -0
  224. package/dist/composables/useGeneratedAnalysis.d.ts +5 -1
  225. package/dist/composables/useGroupAssignment.d.ts +31 -0
  226. package/dist/composables/useJobsStatusTray.d.ts +41 -4
  227. package/dist/composables/usePluginClient.d.ts +4 -0
  228. package/dist/composables/usePluginConfig.d.ts +25 -0
  229. package/dist/composables/useRackEditor.d.ts +31 -0
  230. package/dist/composables/useResourceCrud.d.ts +40 -0
  231. package/dist/composables/useWellPainting.d.ts +35 -0
  232. package/dist/composables/useWellPlateAdapter.d.ts +36 -0
  233. package/dist/{composables-yz8bTkEV.js → composables-CKxOcvgh.js} +764 -59
  234. package/dist/composables-CKxOcvgh.js.map +1 -0
  235. package/dist/{experiment-D08H_TIH.js → experiment-Y9Iz7KYi.js} +3 -1
  236. package/dist/experiment-Y9Iz7KYi.js.map +1 -0
  237. package/dist/experiment-utils-CLnzPPq5.js +2 -0
  238. package/dist/experiment-utils-CLnzPPq5.js.map +1 -0
  239. package/dist/histoire.setup.d.ts +1 -0
  240. package/dist/index.js +18 -33
  241. package/dist/index.js.map +1 -0
  242. package/dist/install.js +28 -0
  243. package/dist/install.js.map +1 -0
  244. package/dist/jobs.d.ts +15 -1
  245. package/dist/permissions.d.ts +5 -0
  246. package/dist/permissions.js +4 -2
  247. package/dist/permissions.js.map +1 -0
  248. package/dist/plotly.min-c2Sez60c.js +180634 -0
  249. package/dist/plotly.min-c2Sez60c.js.map +1 -0
  250. package/dist/stores/auth.d.ts +6 -0
  251. package/dist/stores/index.js +2 -2
  252. package/dist/styles.css +2836 -270
  253. package/dist/tailwind.preset.js +2 -0
  254. package/dist/tailwind.preset.js.map +1 -0
  255. package/dist/templates/catalog.d.ts +4 -4
  256. package/dist/templates/index.js +2 -2
  257. package/dist/templates/presets.d.ts +2 -2
  258. package/dist/{templates-Pbxjdqlh.js → templates-BTJ9C9Kb.js} +22 -5
  259. package/dist/templates-BTJ9C9Kb.js.map +1 -0
  260. package/dist/types/auth.d.ts +1 -0
  261. package/dist/types/auto-group.d.ts +7 -0
  262. package/dist/types/componentWorkflowTypes.d.ts +22 -0
  263. package/dist/types/components.d.ts +1 -1
  264. package/dist/types/generated-ui.d.ts +11 -2
  265. package/dist/types/index.d.ts +4 -4
  266. package/dist/types/index.js +1 -1
  267. package/dist/types/jobs.d.ts +11 -3
  268. package/dist/{useApi-yE0re8k-.js → useApi-CDBq6z23.js} +15 -0
  269. package/dist/useApi-CDBq6z23.js.map +1 -0
  270. package/dist/{useControlSchema-Ds4VeFxt.js → useControlSchema-CXhxTul7.js} +104 -9
  271. package/dist/useControlSchema-CXhxTul7.js.map +1 -0
  272. package/dist/{useDropdownState-WIGW6Rr-.js → useDropdownState-DSb3BC3N.js} +2 -0
  273. package/dist/useDropdownState-DSb3BC3N.js.map +1 -0
  274. package/dist/{useExperimentSelector-DXqsZuSk.js → useExperimentSelector-D0pjj9WH.js} +3 -1
  275. package/dist/useExperimentSelector-D0pjj9WH.js.map +1 -0
  276. package/dist/{useFormBuilder-1so6QSQL.js → useFormBuilder-CuOFB3aP.js} +3 -1
  277. package/dist/useFormBuilder-CuOFB3aP.js.map +1 -0
  278. package/dist/{useProtocolTemplates-Cv0ca1AM.js → useProtocolTemplates-BWhQIWV5.js} +584 -47
  279. package/dist/useProtocolTemplates-BWhQIWV5.js.map +1 -0
  280. package/package.json +8 -2
  281. package/src/__stories__/experiment-helpers.ts +86 -0
  282. package/src/__tests__/components/ActionItem.test.ts +99 -0
  283. package/src/__tests__/components/ActionMenu.test.ts +120 -0
  284. package/src/__tests__/components/AppAvatarMenu.test.ts +38 -0
  285. package/src/__tests__/components/AppLayout.test.ts +207 -0
  286. package/src/__tests__/components/AppPluginSwitcher.test.ts +44 -0
  287. package/src/__tests__/components/AppSidebar.test.ts +857 -0
  288. package/src/__tests__/components/AppToastContainer.test.ts +37 -0
  289. package/src/__tests__/components/AppTopBar.navigation.test.ts +68 -0
  290. package/src/__tests__/components/AppTopBar.test.ts +1256 -0
  291. package/src/__tests__/components/AppTopBarPageSelector.test.ts +156 -0
  292. package/src/__tests__/components/AppTopBarPillNav.test.ts +125 -0
  293. package/src/__tests__/components/AppTopBarPresence.test.ts +47 -0
  294. package/src/__tests__/components/ArtifactSaveDialog.test.ts +566 -0
  295. package/src/__tests__/components/ArtifactSelectorModal.test.ts +178 -0
  296. package/src/__tests__/components/AutoGroupModal.adapter.test.ts +204 -0
  297. package/src/__tests__/components/BaseInput.test.ts +99 -0
  298. package/src/__tests__/components/BaseModal.test.ts +133 -0
  299. package/src/__tests__/components/BasePill.test.ts +291 -0
  300. package/src/__tests__/components/BaseRadioGroup.test.ts +25 -0
  301. package/src/__tests__/components/BaseSelect.test.ts +73 -0
  302. package/src/__tests__/components/BaseTabs.test.ts +40 -0
  303. package/src/__tests__/components/BaseToggle.test.ts +40 -0
  304. package/src/__tests__/components/BatchProgressList.test.ts +52 -0
  305. package/src/__tests__/components/BioTemplateExperimentWorkspaceView.test.ts +159 -0
  306. package/src/__tests__/components/BioTemplatePackWorkspaceView.test.ts +192 -0
  307. package/src/__tests__/components/BioTemplatePresetWorkspaceView.test.ts +328 -0
  308. package/src/__tests__/components/BioTemplateRenderer.test.ts +96 -0
  309. package/src/__tests__/components/Breadcrumb.test.ts +23 -0
  310. package/src/__tests__/components/Calendar.test.ts +566 -0
  311. package/src/__tests__/components/CalendarGridPanel.test.ts +36 -0
  312. package/src/__tests__/components/CollapsibleCard.test.ts +571 -0
  313. package/src/__tests__/components/ComponentBindingRenderer.test.ts +278 -0
  314. package/src/__tests__/components/ConcentrationInput.test.ts +45 -0
  315. package/src/__tests__/components/ControlWorkspaceView.test.ts +1102 -0
  316. package/src/__tests__/components/DataFrame.test.ts +915 -0
  317. package/src/__tests__/components/DatePicker.test.ts +45 -0
  318. package/src/__tests__/components/DateTimePicker.test.ts +48 -0
  319. package/src/__tests__/components/DoseCalculatorVolumeField.test.ts +53 -0
  320. package/src/__tests__/components/DoseDesignWorkspaceView.test.ts +185 -0
  321. package/src/__tests__/components/DropdownButton.test.ts +494 -0
  322. package/src/__tests__/components/EmptyState.test.ts +23 -0
  323. package/src/__tests__/components/ExperimentPopover.test.ts +143 -0
  324. package/src/__tests__/components/ExperimentSelectorModal.test.ts +143 -0
  325. package/src/__tests__/components/FormBuilder.test.ts +353 -0
  326. package/src/__tests__/components/GeneratedPathInput.test.ts +132 -0
  327. package/src/__tests__/components/GeneratedPlotlyResult.test.ts +117 -0
  328. package/src/__tests__/components/GeneratedPluginView.test.ts +235 -0
  329. package/src/__tests__/components/GeneratedResultRenderer.test.ts +93 -0
  330. package/src/__tests__/components/GroupAssigner.test.ts +48 -0
  331. package/src/__tests__/components/InstrumentAlertLog.test.ts +59 -0
  332. package/src/__tests__/components/JobsStatusTray.test.ts +165 -0
  333. package/src/__tests__/components/LcmsSequenceTable.test.ts +57 -0
  334. package/src/__tests__/components/MobileSupportGate.test.ts +120 -0
  335. package/src/__tests__/components/MultiSelect.test.ts +48 -0
  336. package/src/__tests__/components/PlateMapEditorToolbarInternal.test.ts +54 -0
  337. package/src/__tests__/components/PluginIcon.test.ts +215 -0
  338. package/src/__tests__/components/PluginWorkspaceView.controls.test.ts +156 -0
  339. package/src/__tests__/components/PluginWorkspaceView.navigation.test.ts +102 -0
  340. package/src/__tests__/components/PluginWorkspaceView.shell.test.ts +43 -0
  341. package/src/__tests__/components/PluginWorkspaceView.test.ts +719 -0
  342. package/src/__tests__/components/ProgressBar.test.ts +18 -0
  343. package/src/__tests__/components/ProtocolStep.presentation.test.ts +31 -0
  344. package/src/__tests__/components/ProtocolStepEditor.state.test.ts +165 -0
  345. package/src/__tests__/components/ProtocolStepEditor.test.ts +33 -0
  346. package/src/__tests__/components/ProtocolStepParameterField.test.ts +44 -0
  347. package/src/__tests__/components/RackEditor.test.ts +125 -0
  348. package/src/__tests__/components/ReagentList.presentation.test.ts +68 -0
  349. package/src/__tests__/components/ReagentList.test.ts +82 -0
  350. package/src/__tests__/components/RetiredStyles.test.ts +82 -0
  351. package/src/__tests__/components/RuntimeUpdateNotice.test.ts +14 -0
  352. package/src/__tests__/components/SampleHierarchyTree.test.ts +53 -0
  353. package/src/__tests__/components/SampleSelector.colors.test.ts +49 -0
  354. package/src/__tests__/components/SampleSelector.drag.test.ts +126 -0
  355. package/src/__tests__/components/SampleSelector.groups.test.ts +94 -0
  356. package/src/__tests__/components/SampleSelector.selection.test.ts +56 -0
  357. package/src/__tests__/components/SampleSelector.test.ts +466 -0
  358. package/src/__tests__/components/SampleSelectorSampleRow.test.ts +40 -0
  359. package/src/__tests__/components/ScheduleCalendar.test.ts +44 -0
  360. package/src/__tests__/components/SectionCard.test.ts +181 -0
  361. package/src/__tests__/components/SegmentedControl.test.ts +69 -0
  362. package/src/__tests__/components/SequenceProgressBar.test.ts +39 -0
  363. package/src/__tests__/components/SettingsModal.schema.test.ts +97 -0
  364. package/src/__tests__/components/SettingsModal.test.ts +407 -0
  365. package/src/__tests__/components/SmartGroupFieldRecipe.groups.test.ts +101 -0
  366. package/src/__tests__/components/SmartGroupManual.cohorts.test.ts +97 -0
  367. package/src/__tests__/components/TagsInput.test.ts +75 -0
  368. package/src/__tests__/components/ThemeToggle.test.ts +47 -0
  369. package/src/__tests__/components/TimePicker.test.ts +38 -0
  370. package/src/__tests__/components/WellPlate.colors.test.ts +28 -0
  371. package/src/__tests__/components/WellPlate.conditions.test.ts +68 -0
  372. package/src/__tests__/components/WellPlate.geometry.test.ts +54 -0
  373. package/src/__tests__/components/WellPlate.interaction.test.ts +171 -0
  374. package/src/__tests__/components/WellPlate.legend.test.ts +13 -0
  375. package/src/__tests__/components/WellPlate.rendering.test.ts +122 -0
  376. package/src/__tests__/components/WellPlate.sampleDrop.test.ts +70 -0
  377. package/src/__tests__/composables/analysisArtifactTarget.test.ts +77 -0
  378. package/src/__tests__/composables/autoGroup/classKey.test.ts +25 -0
  379. package/src/__tests__/composables/autoGroup/classify.test.ts +107 -0
  380. package/src/__tests__/composables/autoGroup/columns.test.ts +135 -0
  381. package/src/__tests__/composables/autoGroup/compose.test.ts +226 -0
  382. package/src/__tests__/composables/autoGroup/cooccurrence.test.ts +91 -0
  383. package/src/__tests__/composables/autoGroup/fingerprint.test.ts +122 -0
  384. package/src/__tests__/composables/autoGroup/groupByOrder.test.ts +278 -0
  385. package/src/__tests__/composables/autoGroup/groupTree.test.ts +99 -0
  386. package/src/__tests__/composables/autoGroup/integration.test.ts +75 -0
  387. package/src/__tests__/composables/autoGroup/template.test.ts +70 -0
  388. package/src/__tests__/composables/autoGroup/tokenLength.test.ts +85 -0
  389. package/src/__tests__/composables/autoGroup/tokenize.test.ts +33 -0
  390. package/src/__tests__/composables/experiment-utils.test.ts +63 -0
  391. package/src/__tests__/composables/formBuilderRegistry.test.ts +191 -0
  392. package/src/__tests__/composables/resolvePluginFrontendBase.test.ts +65 -0
  393. package/src/__tests__/composables/useAnalysisArtifacts.test.ts +740 -0
  394. package/src/__tests__/composables/useApi.test.ts +157 -0
  395. package/src/__tests__/composables/useAppExperiment.test.ts +899 -0
  396. package/src/__tests__/composables/useAuth.test.ts +233 -0
  397. package/src/__tests__/composables/useAutoGroup.test.ts +524 -0
  398. package/src/__tests__/composables/useAutoGroupInputSources.test.ts +127 -0
  399. package/src/__tests__/composables/useBioTemplatePackWorkspace.test.ts +125 -0
  400. package/src/__tests__/composables/useBioTemplatePresetWorkspace.test.ts +199 -0
  401. package/src/__tests__/composables/useBioTemplateWorkspace.test.ts +104 -0
  402. package/src/__tests__/composables/useCalendarGrid.test.ts +38 -0
  403. package/src/__tests__/composables/useCommandHistory.test.ts +43 -0
  404. package/src/__tests__/composables/useControlSchema.test.ts +1060 -0
  405. package/src/__tests__/composables/useDebouncedWatch.test.ts +93 -0
  406. package/src/__tests__/composables/useDropdownState.test.ts +95 -0
  407. package/src/__tests__/composables/useEventListener.test.ts +116 -0
  408. package/src/__tests__/composables/useEventStream.test.ts +140 -0
  409. package/src/__tests__/composables/useExpansionSet.test.ts +62 -0
  410. package/src/__tests__/composables/useExperimentData.test.ts +154 -0
  411. package/src/__tests__/composables/useExperimentSamples.test.ts +91 -0
  412. package/src/__tests__/composables/useExperimentSave.test.ts +542 -0
  413. package/src/__tests__/composables/useExperimentSelector.test.ts +338 -0
  414. package/src/__tests__/composables/useFileImport.test.ts +44 -0
  415. package/src/__tests__/composables/useForm.test.ts +263 -0
  416. package/src/__tests__/composables/useFormBuilder.test.ts +994 -0
  417. package/src/__tests__/composables/useGeneratedAnalysis.test.ts +1903 -0
  418. package/src/__tests__/composables/useGroupAssignment.test.ts +73 -0
  419. package/src/__tests__/composables/useJobsStatusTray.test.ts +283 -0
  420. package/src/__tests__/composables/useListSelection.test.ts +66 -0
  421. package/src/__tests__/composables/useMobileSupportGate.test.ts +74 -0
  422. package/src/__tests__/composables/useOptimisticMutation.test.ts +40 -0
  423. package/src/__tests__/composables/usePlatformContext.test.ts +148 -0
  424. package/src/__tests__/composables/usePluginClient.test.ts +1772 -0
  425. package/src/__tests__/composables/usePluginConfig.test.ts +497 -0
  426. package/src/__tests__/composables/usePresenceHeartbeat.test.ts +164 -0
  427. package/src/__tests__/composables/useProtocolTemplates.test.ts +64 -0
  428. package/src/__tests__/composables/useRequestSyncState.test.ts +92 -0
  429. package/src/__tests__/composables/useResourceCrud.test.ts +56 -0
  430. package/src/__tests__/composables/useRuntimeAlignment.test.ts +145 -0
  431. package/src/__tests__/composables/useSampleGroups.test.ts +66 -0
  432. package/src/__tests__/composables/useSampleGroups.tree.test.ts +145 -0
  433. package/src/__tests__/composables/useScheduleCalendarLayout.test.ts +89 -0
  434. package/src/__tests__/composables/useSelectionLimit.test.ts +41 -0
  435. package/src/__tests__/composables/useSortedItems.test.ts +87 -0
  436. package/src/__tests__/composables/useTemplateCollection.test.ts +147 -0
  437. package/src/__tests__/composables/useTextSearch.test.ts +55 -0
  438. package/src/__tests__/composables/useTheme.test.ts +91 -0
  439. package/src/__tests__/composables/useTimeUtils.test.ts +35 -0
  440. package/src/__tests__/composables/useWellPainting.test.ts +52 -0
  441. package/src/__tests__/composables/useWellPlateAdapter.test.ts +50 -0
  442. package/src/__tests__/composables/useWellPlateValidation.test.ts +42 -0
  443. package/src/__tests__/docs/extractDocsComponents.test.ts +156 -0
  444. package/src/__tests__/docs/extractDocsExports.test.ts +92 -0
  445. package/src/__tests__/docs/extractDocsParsing.test.ts +91 -0
  446. package/src/__tests__/docs/extractDocsTemplates.test.ts +53 -0
  447. package/src/__tests__/docs/extractDocsTheme.test.ts +89 -0
  448. package/src/__tests__/docs/frontendDocsCatalog.test.ts +436 -0
  449. package/src/__tests__/fixtures/auto-group/mixed-lc-ms-batch.txt +187 -0
  450. package/src/__tests__/fixtures/templates/dose-response.json +81 -0
  451. package/src/__tests__/fixtures/templates/plate-map.json +54 -0
  452. package/src/__tests__/fixtures/templates/qpcr-plate.json +96 -0
  453. package/src/__tests__/fixtures/templates/sample-sheet.json +71 -0
  454. package/src/__tests__/generatedUi.test.ts +119 -0
  455. package/src/__tests__/stores/experiment.test.ts +300 -0
  456. package/src/__tests__/stores/settings.test.ts +78 -0
  457. package/src/__tests__/templates/templates.test.ts +1185 -0
  458. package/src/__tests__/types/GeneratedJsonSchema.test.ts +62 -0
  459. package/src/__tests__/utils/color.test.ts +96 -0
  460. package/src/__tests__/utils/instrument.test.ts +47 -0
  461. package/src/__tests__/utils/jobs.test.ts +95 -0
  462. package/src/__tests__/utils/lcms.test.ts +73 -0
  463. package/src/__tests__/utils/permissions.test.ts +62 -0
  464. package/src/__tests__/utils/rack.test.ts +120 -0
  465. package/src/components/ActionMenu.story.vue +26 -0
  466. package/src/components/ActionMenu.vue +209 -0
  467. package/src/components/AlertBox.story.vue +204 -0
  468. package/src/components/AlertBox.vue +88 -0
  469. package/src/components/AppAvatarMenu.story.vue +155 -0
  470. package/src/components/AppAvatarMenu.vue +133 -0
  471. package/src/components/AppContainer.story.vue +104 -0
  472. package/src/components/AppContainer.vue +34 -0
  473. package/src/components/AppLayout.story.vue +331 -0
  474. package/src/components/AppLayout.vue +156 -0
  475. package/src/components/AppPluginSwitcher.vue +137 -0
  476. package/src/components/AppSidebar.story.vue +584 -0
  477. package/src/components/AppSidebar.vue +471 -0
  478. package/src/components/AppToastContainer.story.vue +157 -0
  479. package/src/components/AppToastContainer.vue +62 -0
  480. package/src/components/AppTopBar.navigation.ts +60 -0
  481. package/src/components/AppTopBar.story.vue +280 -0
  482. package/src/components/AppTopBar.vue +474 -0
  483. package/src/components/ArtifactSaveDialog.story.vue +319 -0
  484. package/src/components/ArtifactSaveDialog.vue +434 -0
  485. package/src/components/ArtifactSelectorModal.story.vue +295 -0
  486. package/src/components/ArtifactSelectorModal.vue +333 -0
  487. package/src/components/AuditTrail.story.vue +163 -0
  488. package/src/components/AuditTrail.vue +151 -0
  489. package/src/components/AutoGroupModal.adapter.ts +203 -0
  490. package/src/components/AutoGroupModal.story.vue +458 -0
  491. package/src/components/AutoGroupModal.vue +294 -0
  492. package/src/components/Avatar.story.vue +115 -0
  493. package/src/components/Avatar.vue +79 -0
  494. package/src/components/BaseButton.story.vue +96 -0
  495. package/src/components/BaseButton.vue +75 -0
  496. package/src/components/BaseCheckbox.story.vue +100 -0
  497. package/src/components/BaseCheckbox.vue +131 -0
  498. package/src/components/BaseInput.story.vue +98 -0
  499. package/src/components/BaseInput.vue +76 -0
  500. package/src/components/BaseModal.story.vue +335 -0
  501. package/src/components/BaseModal.vue +328 -0
  502. package/src/components/BasePill.story.vue +142 -0
  503. package/src/components/BasePill.vue +89 -0
  504. package/src/components/BaseRadioGroup.story.vue +145 -0
  505. package/src/components/BaseRadioGroup.vue +128 -0
  506. package/src/components/BaseSelect.story.vue +120 -0
  507. package/src/components/BaseSelect.vue +89 -0
  508. package/src/components/BaseSlider.story.vue +122 -0
  509. package/src/components/BaseSlider.vue +126 -0
  510. package/src/components/BaseTabs.story.vue +127 -0
  511. package/src/components/BaseTabs.vue +82 -0
  512. package/src/components/BaseTextarea.story.vue +91 -0
  513. package/src/components/BaseTextarea.vue +62 -0
  514. package/src/components/BaseToggle.story.vue +108 -0
  515. package/src/components/BaseToggle.vue +143 -0
  516. package/src/components/BatchProgressList.story.vue +92 -0
  517. package/src/components/BatchProgressList.vue +181 -0
  518. package/src/components/BioTemplateExperimentWorkspaceView.story.vue +123 -0
  519. package/src/components/BioTemplateExperimentWorkspaceView.vue +350 -0
  520. package/src/components/BioTemplatePackWorkspaceView.story.vue +107 -0
  521. package/src/components/BioTemplatePackWorkspaceView.vue +184 -0
  522. package/src/components/BioTemplatePresetWorkspaceView.story.vue +163 -0
  523. package/src/components/BioTemplatePresetWorkspaceView.vue +408 -0
  524. package/src/components/BioTemplateRenderer.story.vue +57 -0
  525. package/src/components/BioTemplateRenderer.vue +64 -0
  526. package/src/components/Breadcrumb.story.vue +106 -0
  527. package/src/components/Breadcrumb.vue +81 -0
  528. package/src/components/Calendar.story.vue +106 -0
  529. package/src/components/Calendar.vue +367 -0
  530. package/src/components/ChartContainer.story.vue +113 -0
  531. package/src/components/ChartContainer.vue +64 -0
  532. package/src/components/ChemicalFormula.story.vue +102 -0
  533. package/src/components/ChemicalFormula.vue +39 -0
  534. package/src/components/CollapsibleCard.story.vue +135 -0
  535. package/src/components/CollapsibleCard.vue +245 -0
  536. package/src/components/ColorSlider.story.vue +120 -0
  537. package/src/components/ColorSlider.vue +164 -0
  538. package/src/components/ComponentBindingRenderer.story.vue +87 -0
  539. package/src/components/ComponentBindingRenderer.vue +324 -0
  540. package/src/components/ConcentrationInput.story.vue +77 -0
  541. package/src/components/ConcentrationInput.vue +149 -0
  542. package/src/components/ConfirmDialog.story.vue +248 -0
  543. package/src/components/ConfirmDialog.vue +100 -0
  544. package/src/components/ControlWorkspaceView.story.vue +347 -0
  545. package/src/components/ControlWorkspaceView.vue +381 -0
  546. package/src/components/DataFrame.story.vue +148 -0
  547. package/src/components/DataFrame.vue +520 -0
  548. package/src/components/DatePicker.story.vue +119 -0
  549. package/src/components/DatePicker.vue +197 -0
  550. package/src/components/DateTimePicker.story.vue +112 -0
  551. package/src/components/DateTimePicker.vue +271 -0
  552. package/src/components/Divider.story.vue +80 -0
  553. package/src/components/Divider.vue +49 -0
  554. package/src/components/DoseCalculator.story.vue +68 -0
  555. package/src/components/DoseCalculator.vue +416 -0
  556. package/src/components/DoseCalculatorVolumeField.vue +61 -0
  557. package/src/components/DoseDesignWorkspaceView.story.vue +77 -0
  558. package/src/components/DoseDesignWorkspaceView.vue +262 -0
  559. package/src/components/DropdownButton.story.vue +102 -0
  560. package/src/components/DropdownButton.vue +163 -0
  561. package/src/components/EmptyState.story.vue +135 -0
  562. package/src/components/EmptyState.vue +71 -0
  563. package/src/components/ExperimentCodeBadge.story.vue +77 -0
  564. package/src/components/ExperimentCodeBadge.vue +64 -0
  565. package/src/components/ExperimentDataViewer.story.vue +174 -0
  566. package/src/components/ExperimentDataViewer.vue +293 -0
  567. package/src/components/ExperimentPopover.story.vue +442 -0
  568. package/src/components/ExperimentPopover.vue +312 -0
  569. package/src/components/ExperimentSelectorModal.story.vue +381 -0
  570. package/src/components/ExperimentSelectorModal.vue +432 -0
  571. package/src/components/ExperimentTimeline.story.vue +161 -0
  572. package/src/components/ExperimentTimeline.vue +357 -0
  573. package/src/components/FileUploader.story.vue +107 -0
  574. package/src/components/FileUploader.vue +424 -0
  575. package/src/components/FitPanel.story.vue +125 -0
  576. package/src/components/FitPanel.vue +120 -0
  577. package/src/components/FormActions.vue +92 -0
  578. package/src/components/FormBuilder.story.vue +203 -0
  579. package/src/components/FormBuilder.vue +311 -0
  580. package/src/components/FormField.story.vue +132 -0
  581. package/src/components/FormField.vue +59 -0
  582. package/src/components/FormulaInput.story.vue +96 -0
  583. package/src/components/FormulaInput.vue +125 -0
  584. package/src/components/GeneratedPathInput.vue +218 -0
  585. package/src/components/GeneratedPlotlyResult.vue +87 -0
  586. package/src/components/GeneratedPluginView.vue +289 -0
  587. package/src/components/GeneratedResultRenderer.vue +147 -0
  588. package/src/components/GroupAssigner.story.vue +83 -0
  589. package/src/components/GroupAssigner.vue +257 -0
  590. package/src/components/IconButton.story.vue +140 -0
  591. package/src/components/IconButton.vue +73 -0
  592. package/src/components/InstrumentAlertLog.vue +191 -0
  593. package/src/components/InstrumentStateBadge.vue +50 -0
  594. package/src/components/InstrumentStatusCard.vue +188 -0
  595. package/src/components/JobsStatusTray.story.vue +126 -0
  596. package/src/components/JobsStatusTray.vue +407 -0
  597. package/src/components/LcmsSequenceTable.vue +191 -0
  598. package/src/components/LoadingSpinner.story.vue +70 -0
  599. package/src/components/LoadingSpinner.vue +50 -0
  600. package/src/components/MobileSupportGate.story.vue +52 -0
  601. package/src/components/MobileSupportGate.vue +115 -0
  602. package/src/components/MoleculeInput.story.vue +66 -0
  603. package/src/components/MoleculeInput.vue +426 -0
  604. package/src/components/MultiSelect.story.vue +132 -0
  605. package/src/components/MultiSelect.vue +123 -0
  606. package/src/components/NumberInput.story.vue +122 -0
  607. package/src/components/NumberInput.vue +162 -0
  608. package/src/components/PlateMapEditor.story.vue +92 -0
  609. package/src/components/PlateMapEditor.vue +434 -0
  610. package/src/components/PluginIcon.story.vue +103 -0
  611. package/src/components/PluginIcon.vue +158 -0
  612. package/src/components/PluginWorkspaceView.controls.ts +182 -0
  613. package/src/components/PluginWorkspaceView.navigation.ts +106 -0
  614. package/src/components/PluginWorkspaceView.props.ts +169 -0
  615. package/src/components/PluginWorkspaceView.shell.ts +67 -0
  616. package/src/components/PluginWorkspaceView.story.vue +341 -0
  617. package/src/components/PluginWorkspaceView.vue +395 -0
  618. package/src/components/ProgressBar.story.vue +148 -0
  619. package/src/components/ProgressBar.vue +117 -0
  620. package/src/components/ProtocolStep.presentation.ts +31 -0
  621. package/src/components/ProtocolStepEditor.state.ts +104 -0
  622. package/src/components/ProtocolStepEditor.story.vue +69 -0
  623. package/src/components/ProtocolStepEditor.vue +382 -0
  624. package/src/components/ProtocolStepParameterField.vue +134 -0
  625. package/src/components/RackEditor.story.vue +100 -0
  626. package/src/components/RackEditor.vue +442 -0
  627. package/src/components/ReagentEditor.story.vue +153 -0
  628. package/src/components/ReagentEditor.vue +418 -0
  629. package/src/components/ReagentList.presentation.ts +105 -0
  630. package/src/components/ReagentList.story.vue +137 -0
  631. package/src/components/ReagentList.vue +392 -0
  632. package/src/components/ResourceCard.story.vue +150 -0
  633. package/src/components/ResourceCard.vue +161 -0
  634. package/src/components/RuntimeUpdateNotice.vue +51 -0
  635. package/src/components/SampleHierarchyTree.story.vue +161 -0
  636. package/src/components/SampleHierarchyTree.vue +246 -0
  637. package/src/components/SampleLegend.story.vue +91 -0
  638. package/src/components/SampleLegend.vue +119 -0
  639. package/src/components/SampleSelector.colors.ts +48 -0
  640. package/src/components/SampleSelector.drag.ts +164 -0
  641. package/src/components/SampleSelector.groups.ts +109 -0
  642. package/src/components/SampleSelector.selection.ts +64 -0
  643. package/src/components/SampleSelector.story.vue +192 -0
  644. package/src/components/SampleSelector.tree.ts +48 -0
  645. package/src/components/SampleSelector.vue +451 -0
  646. package/src/components/SampleSelectorGroupNode.vue +197 -0
  647. package/src/components/SampleSelectorSampleRow.vue +68 -0
  648. package/src/components/ScheduleCalendar.story.vue +195 -0
  649. package/src/components/ScheduleCalendar.vue +414 -0
  650. package/src/components/ScientificNumber.story.vue +127 -0
  651. package/src/components/ScientificNumber.vue +197 -0
  652. package/src/components/SectionCard.story.vue +163 -0
  653. package/src/components/SectionCard.vue +98 -0
  654. package/src/components/SegmentedControl.story.vue +149 -0
  655. package/src/components/SegmentedControl.vue +94 -0
  656. package/src/components/SequenceInput.story.vue +119 -0
  657. package/src/components/SequenceInput.vue +209 -0
  658. package/src/components/SequenceProgressBar.vue +71 -0
  659. package/src/components/SettingsModal.schema.ts +74 -0
  660. package/src/components/SettingsModal.story.vue +524 -0
  661. package/src/components/SettingsModal.vue +399 -0
  662. package/src/components/Skeleton.story.vue +141 -0
  663. package/src/components/Skeleton.vue +74 -0
  664. package/src/components/SmartGroup.types.ts +98 -0
  665. package/src/components/SmartGroupFieldRecipe.groups.ts +109 -0
  666. package/src/components/SmartGroupFieldRecipe.story.vue +58 -0
  667. package/src/components/SmartGroupFieldRecipe.vue +499 -0
  668. package/src/components/SmartGroupManual.cohorts.ts +112 -0
  669. package/src/components/SmartGroupManual.story.vue +55 -0
  670. package/src/components/SmartGroupManual.vue +398 -0
  671. package/src/components/SmartGroupModal.story.vue +61 -0
  672. package/src/components/SmartGroupModal.vue +61 -0
  673. package/src/components/StatusIndicator.story.vue +99 -0
  674. package/src/components/StatusIndicator.vue +40 -0
  675. package/src/components/StepWizard.story.vue +155 -0
  676. package/src/components/StepWizard.vue +223 -0
  677. package/src/components/TagsInput.story.vue +155 -0
  678. package/src/components/TagsInput.vue +280 -0
  679. package/src/components/ThemeToggle.story.vue +36 -0
  680. package/src/components/ThemeToggle.vue +56 -0
  681. package/src/components/TimePicker.story.vue +96 -0
  682. package/src/components/TimePicker.vue +251 -0
  683. package/src/components/TimeRangeInput.story.vue +104 -0
  684. package/src/components/TimeRangeInput.vue +122 -0
  685. package/src/components/Tooltip.story.vue +138 -0
  686. package/src/components/Tooltip.vue +114 -0
  687. package/src/components/UnitInput.story.vue +194 -0
  688. package/src/components/UnitInput.vue +217 -0
  689. package/src/components/WellPlate.colors.ts +56 -0
  690. package/src/components/WellPlate.conditions.ts +100 -0
  691. package/src/components/WellPlate.geometry.ts +91 -0
  692. package/src/components/WellPlate.interaction.ts +272 -0
  693. package/src/components/WellPlate.legend.ts +8 -0
  694. package/src/components/WellPlate.rendering.ts +105 -0
  695. package/src/components/WellPlate.sampleDrop.ts +73 -0
  696. package/src/components/WellPlate.story.vue +282 -0
  697. package/src/components/WellPlate.vue +497 -0
  698. package/src/components/index.ts +139 -0
  699. package/src/components/internal/ActionItemInternal.vue +82 -0
  700. package/src/components/internal/AppTopBarPageSelectorInternal.vue +127 -0
  701. package/src/components/internal/AppTopBarPillNavInternal.vue +194 -0
  702. package/src/components/internal/CalendarGridPanelInternal.vue +120 -0
  703. package/src/components/internal/FormFieldRendererInternal.vue +68 -0
  704. package/src/components/internal/FormSectionRenderer.vue +78 -0
  705. package/src/components/internal/PlateMapEditorToolbarInternal.vue +128 -0
  706. package/src/components/internal/WellEditPopupInternal.vue +230 -0
  707. package/src/composables/analysisArtifactTarget.ts +53 -0
  708. package/src/composables/autoGroup/classKey.ts +8 -0
  709. package/src/composables/autoGroup/classify.ts +205 -0
  710. package/src/composables/autoGroup/colors.ts +6 -0
  711. package/src/composables/autoGroup/columns.ts +226 -0
  712. package/src/composables/autoGroup/compose.ts +244 -0
  713. package/src/composables/autoGroup/cooccurrence.ts +46 -0
  714. package/src/composables/autoGroup/csv-shim.ts +44 -0
  715. package/src/composables/autoGroup/fingerprint.ts +63 -0
  716. package/src/composables/autoGroup/index.ts +22 -0
  717. package/src/composables/autoGroup/replicatePreGroup.ts +124 -0
  718. package/src/composables/autoGroup/template.ts +126 -0
  719. package/src/composables/autoGroup/tokenLength.ts +53 -0
  720. package/src/composables/autoGroup/tokenize.ts +41 -0
  721. package/src/composables/autoGroup/vocab.json +66 -0
  722. package/src/composables/autoGroupConstants.ts +4 -0
  723. package/src/composables/autoGroupGrouping.ts +148 -0
  724. package/src/composables/controlComponentBindings.ts +80 -0
  725. package/src/composables/controlSchemaAdapters.ts +199 -0
  726. package/src/composables/controlSchemaDoseDesign.ts +222 -0
  727. package/src/composables/controlSchemaFormFields.ts +64 -0
  728. package/src/composables/controlSchemaLayout.ts +59 -0
  729. package/src/composables/controlSchemaModel.ts +172 -0
  730. package/src/composables/controlSchemaNormalize.ts +101 -0
  731. package/src/composables/controlSchemaTypes.ts +372 -0
  732. package/src/composables/controlSchemaUtils.ts +36 -0
  733. package/src/composables/controlWorkspaceOptions.ts +21 -0
  734. package/src/composables/experiment-utils.ts +105 -0
  735. package/src/composables/experimentDesignData.ts +182 -0
  736. package/src/composables/formBuilderRegistry.ts +81 -0
  737. package/src/composables/formBuilderSchema.ts +153 -0
  738. package/src/composables/index.ts +530 -0
  739. package/src/composables/platformContextHelpers.ts +81 -0
  740. package/src/composables/pluginEndpointBuilder.ts +267 -0
  741. package/src/composables/pluginFrontendBase.ts +22 -0
  742. package/src/composables/protocolTemplateCatalog.ts +325 -0
  743. package/src/composables/useAnalysisArtifacts.ts +361 -0
  744. package/src/composables/useApi.ts +319 -0
  745. package/src/composables/useAppExperiment.ts +228 -0
  746. package/src/composables/useAsync.ts +323 -0
  747. package/src/composables/useAuth.ts +458 -0
  748. package/src/composables/useAutoGroup.ts +682 -0
  749. package/src/composables/useAutoGroupInputSources.ts +147 -0
  750. package/src/composables/useBioTemplateComponents.ts +105 -0
  751. package/src/composables/useBioTemplateControls.ts +41 -0
  752. package/src/composables/useBioTemplatePackWorkspace.ts +193 -0
  753. package/src/composables/useBioTemplatePresetWorkspace.ts +326 -0
  754. package/src/composables/useBioTemplateWorkspace.ts +141 -0
  755. package/src/composables/useCalendarGrid.ts +140 -0
  756. package/src/composables/useChemicalFormula.ts +275 -0
  757. package/src/composables/useCommandHistory.ts +113 -0
  758. package/src/composables/useConcentrationUnits.ts +246 -0
  759. package/src/composables/useControlSchema.ts +135 -0
  760. package/src/composables/useControlWorkspace.ts +209 -0
  761. package/src/composables/useDebouncedWatch.ts +119 -0
  762. package/src/composables/useDoseCalculator.ts +370 -0
  763. package/src/composables/useDropdownState.ts +83 -0
  764. package/src/composables/useEventListener.ts +111 -0
  765. package/src/composables/useEventStream.ts +314 -0
  766. package/src/composables/useExpansionSet.ts +117 -0
  767. package/src/composables/useExperimentData.ts +136 -0
  768. package/src/composables/useExperimentSamples.ts +142 -0
  769. package/src/composables/useExperimentSave.ts +344 -0
  770. package/src/composables/useExperimentSelector.ts +408 -0
  771. package/src/composables/useFileImport.ts +231 -0
  772. package/src/composables/useForm.ts +279 -0
  773. package/src/composables/useFormBuilder.ts +292 -0
  774. package/src/composables/useFormValidation.ts +154 -0
  775. package/src/composables/useGeneratedAnalysis.ts +1227 -0
  776. package/src/composables/useGroupAssignment.ts +148 -0
  777. package/src/composables/useJobsStatusTray.ts +493 -0
  778. package/src/composables/useListSelection.ts +158 -0
  779. package/src/composables/useMobileSupportGate.ts +80 -0
  780. package/src/composables/useOptimisticMutation.ts +107 -0
  781. package/src/composables/usePasskey.ts +216 -0
  782. package/src/composables/usePlatformContext.ts +299 -0
  783. package/src/composables/usePluginClient.ts +968 -0
  784. package/src/composables/usePluginConfig.ts +250 -0
  785. package/src/composables/usePresenceHeartbeat.ts +201 -0
  786. package/src/composables/useProtocolTemplates.ts +212 -0
  787. package/src/composables/useRackEditor.ts +223 -0
  788. package/src/composables/useReagentSeries.ts +91 -0
  789. package/src/composables/useRequestSyncState.ts +126 -0
  790. package/src/composables/useResourceCrud.ts +245 -0
  791. package/src/composables/useRuntimeAlignment.ts +184 -0
  792. package/src/composables/useSampleGroups.ts +211 -0
  793. package/src/composables/useScheduleCalendarLayout.ts +287 -0
  794. package/src/composables/useScheduleDrag.ts +245 -0
  795. package/src/composables/useSelectionLimit.ts +57 -0
  796. package/src/composables/useSequenceUtils.ts +105 -0
  797. package/src/composables/useSortedItems.ts +118 -0
  798. package/src/composables/useTemplateCollection.ts +229 -0
  799. package/src/composables/useTextSearch.ts +60 -0
  800. package/src/composables/useTheme.ts +32 -0
  801. package/src/composables/useTimeUtils.ts +155 -0
  802. package/src/composables/useToast.ts +40 -0
  803. package/src/composables/useWellPainting.ts +187 -0
  804. package/src/composables/useWellPlateAdapter.ts +147 -0
  805. package/src/composables/useWellPlateEditor.ts +425 -0
  806. package/src/composables/useWellPlateValidation.ts +85 -0
  807. package/src/generated/schema.ts +130 -0
  808. package/src/generated-ui/main.ts +21 -0
  809. package/src/histoire.setup.ts +17 -0
  810. package/src/index.ts +67 -0
  811. package/src/install.ts +39 -0
  812. package/src/instrument.ts +90 -0
  813. package/src/jobs.ts +80 -0
  814. package/src/lcms.ts +108 -0
  815. package/src/permissions.ts +144 -0
  816. package/src/plotly-dist.d.ts +3 -0
  817. package/src/stores/auth.ts +206 -0
  818. package/src/stores/experiment.ts +120 -0
  819. package/src/stores/index.ts +3 -0
  820. package/src/stores/settings.ts +232 -0
  821. package/src/styles/components/action-menu.css +59 -0
  822. package/src/styles/components/alert-box.css +150 -0
  823. package/src/styles/components/app-avatar-menu.css +156 -0
  824. package/src/styles/components/app-container.css +33 -0
  825. package/src/styles/components/app-layout.css +180 -0
  826. package/src/styles/components/app-page-selector.css +212 -0
  827. package/src/styles/components/app-pill-nav.css +133 -0
  828. package/src/styles/components/app-plugin-switcher.css +196 -0
  829. package/src/styles/components/app-sidebar.css +392 -0
  830. package/src/styles/components/app-top-bar.css +249 -0
  831. package/src/styles/components/artifact-save-dialog.css +17 -0
  832. package/src/styles/components/artifact-selector-modal.css +216 -0
  833. package/src/styles/components/audit-trail.css +143 -0
  834. package/src/styles/components/avatar.css +73 -0
  835. package/src/styles/components/batch-progress-list.css +196 -0
  836. package/src/styles/components/breadcrumb.css +64 -0
  837. package/src/styles/components/button.css +192 -0
  838. package/src/styles/components/calendar.css +192 -0
  839. package/src/styles/components/chart-container.css +69 -0
  840. package/src/styles/components/checkbox.css +210 -0
  841. package/src/styles/components/chemical-formula.css +46 -0
  842. package/src/styles/components/collapsible-card.css +393 -0
  843. package/src/styles/components/color-slider.css +110 -0
  844. package/src/styles/components/concentration-input.css +17 -0
  845. package/src/styles/components/confirm-dialog.css +59 -0
  846. package/src/styles/components/dataframe.css +554 -0
  847. package/src/styles/components/date-picker.css +243 -0
  848. package/src/styles/components/datetime-picker.css +229 -0
  849. package/src/styles/components/divider.css +63 -0
  850. package/src/styles/components/dose-calculator.css +297 -0
  851. package/src/styles/components/dropdown-button.css +280 -0
  852. package/src/styles/components/empty-state.css +135 -0
  853. package/src/styles/components/experiment-code-badge.css +33 -0
  854. package/src/styles/components/experiment-data-viewer.css +138 -0
  855. package/src/styles/components/experiment-popover.css +563 -0
  856. package/src/styles/components/experiment-selector-modal.css +341 -0
  857. package/src/styles/components/experiment-timeline.css +529 -0
  858. package/src/styles/components/file-uploader.css +310 -0
  859. package/src/styles/components/fit-panel.css +67 -0
  860. package/src/styles/components/form-builder.css +69 -0
  861. package/src/styles/components/form-field.css +48 -0
  862. package/src/styles/components/formula-input.css +103 -0
  863. package/src/styles/components/group-assigner.css +200 -0
  864. package/src/styles/components/icon-button.css +196 -0
  865. package/src/styles/components/input.css +65 -0
  866. package/src/styles/components/instrument-monitor.css +478 -0
  867. package/src/styles/components/jobs-status-tray.css +420 -0
  868. package/src/styles/components/lcms-sequence-table.css +189 -0
  869. package/src/styles/components/loading-spinner.css +67 -0
  870. package/src/styles/components/mobile-support-gate.css +119 -0
  871. package/src/styles/components/modal.css +646 -0
  872. package/src/styles/components/molecule-input.css +186 -0
  873. package/src/styles/components/multi-select.css +131 -0
  874. package/src/styles/components/number-input.css +199 -0
  875. package/src/styles/components/pill.css +188 -0
  876. package/src/styles/components/plate-map-editor.css +464 -0
  877. package/src/styles/components/plugin-icon.css +46 -0
  878. package/src/styles/components/progress-bar.css +133 -0
  879. package/src/styles/components/protocol-step-editor.css +443 -0
  880. package/src/styles/components/rack-editor.css +265 -0
  881. package/src/styles/components/radio-group.css +240 -0
  882. package/src/styles/components/reagent-editor.css +505 -0
  883. package/src/styles/components/reagent-list.css +407 -0
  884. package/src/styles/components/resource-card.css +360 -0
  885. package/src/styles/components/sample-hierarchy-tree.css +310 -0
  886. package/src/styles/components/sample-legend.css +201 -0
  887. package/src/styles/components/sample-selector.css +682 -0
  888. package/src/styles/components/schedule-calendar.css +472 -0
  889. package/src/styles/components/scientific-number.css +63 -0
  890. package/src/styles/components/section-card.css +161 -0
  891. package/src/styles/components/segmented-control.css +194 -0
  892. package/src/styles/components/select.css +77 -0
  893. package/src/styles/components/sequence-input.css +184 -0
  894. package/src/styles/components/sequence-progress-bar.css +63 -0
  895. package/src/styles/components/settings-modal.css +76 -0
  896. package/src/styles/components/skeleton.css +49 -0
  897. package/src/styles/components/slider.css +74 -0
  898. package/src/styles/components/smart-group.css +734 -0
  899. package/src/styles/components/status-indicator.css +66 -0
  900. package/src/styles/components/step-wizard.css +192 -0
  901. package/src/styles/components/tabs.css +103 -0
  902. package/src/styles/components/tags-input.css +195 -0
  903. package/src/styles/components/textarea.css +81 -0
  904. package/src/styles/components/theme-toggle.css +6 -0
  905. package/src/styles/components/time-picker.css +171 -0
  906. package/src/styles/components/time-range-input.css +42 -0
  907. package/src/styles/components/toast.css +91 -0
  908. package/src/styles/components/toggle.css +226 -0
  909. package/src/styles/components/tooltip.css +91 -0
  910. package/src/styles/components/unit-input.css +123 -0
  911. package/src/styles/components/well-edit-popup.css +258 -0
  912. package/src/styles/components/well-plate.css +286 -0
  913. package/src/styles/index.css +93 -0
  914. package/src/styles/variables.css +1150 -0
  915. package/src/tailwind.preset.ts +66 -0
  916. package/src/templates/adapters.ts +137 -0
  917. package/src/templates/assayLookups.ts +33 -0
  918. package/src/templates/assayMatrixAdapters.ts +78 -0
  919. package/src/templates/assayMatrixBuilder.ts +59 -0
  920. package/src/templates/assayNormalizers.ts +34 -0
  921. package/src/templates/builderDefaults.ts +11 -0
  922. package/src/templates/builderIdUtils.ts +20 -0
  923. package/src/templates/builderPresetControls.ts +165 -0
  924. package/src/templates/builderReadUtils.ts +57 -0
  925. package/src/templates/builders.ts +122 -0
  926. package/src/templates/calibrationCurveAdapters.ts +59 -0
  927. package/src/templates/calibrationCurveBuilder.ts +99 -0
  928. package/src/templates/calibrationNormalizers.ts +60 -0
  929. package/src/templates/catalog.ts +245 -0
  930. package/src/templates/componentBindingCatalog.ts +90 -0
  931. package/src/templates/componentBindingHelpers.ts +93 -0
  932. package/src/templates/componentBindings.ts +253 -0
  933. package/src/templates/componentDoseResponseProps.ts +42 -0
  934. package/src/templates/componentGenericProps.ts +77 -0
  935. package/src/templates/componentPlateHelpers.ts +29 -0
  936. package/src/templates/componentPlateMapProps.ts +32 -0
  937. package/src/templates/componentPropsFactory.ts +21 -0
  938. package/src/templates/componentQpcrPlateProps.ts +28 -0
  939. package/src/templates/componentTargetResolvers.ts +69 -0
  940. package/src/templates/componentTemplateProps.ts +78 -0
  941. package/src/templates/controlSchemaClone.ts +32 -0
  942. package/src/templates/controlSchemaConstants.ts +11 -0
  943. package/src/templates/controlSchemaMerge.ts +40 -0
  944. package/src/templates/controlSchemaTargets.ts +87 -0
  945. package/src/templates/controlSchemaTypes.ts +20 -0
  946. package/src/templates/controlSchemas.ts +104 -0
  947. package/src/templates/defaultBioTemplateBuilder.ts +124 -0
  948. package/src/templates/doseResponseAdapters.ts +45 -0
  949. package/src/templates/doseResponseBuilder.ts +44 -0
  950. package/src/templates/elisaAssayCollectionBuilder.ts +62 -0
  951. package/src/templates/flowCytometryAssayCollectionBuilder.ts +41 -0
  952. package/src/templates/flowCytometryPanelBuilder.ts +53 -0
  953. package/src/templates/flowNormalizers.ts +58 -0
  954. package/src/templates/flowPanelAdapters.ts +58 -0
  955. package/src/templates/index.ts +326 -0
  956. package/src/templates/instrumentRunAdapterHelpers.ts +94 -0
  957. package/src/templates/instrumentRunAdapters.ts +163 -0
  958. package/src/templates/instrumentRunBuilder.ts +97 -0
  959. package/src/templates/lcmsBatchCollectionBuilder.ts +38 -0
  960. package/src/templates/lookup.ts +18 -0
  961. package/src/templates/packs.ts +162 -0
  962. package/src/templates/plateGeometry.ts +62 -0
  963. package/src/templates/plateMapAdapters.ts +36 -0
  964. package/src/templates/plateMapBuilder.ts +43 -0
  965. package/src/templates/presetControlSchemas.ts +258 -0
  966. package/src/templates/presets.ts +179 -0
  967. package/src/templates/protocolAdapters.ts +69 -0
  968. package/src/templates/protocolNormalizers.ts +37 -0
  969. package/src/templates/protocolStepsBuilder.ts +36 -0
  970. package/src/templates/qpcrAdapters.ts +104 -0
  971. package/src/templates/qpcrExpressionCollectionBuilder.ts +33 -0
  972. package/src/templates/qpcrPlateBuilder.ts +96 -0
  973. package/src/templates/reagentAdapters.ts +77 -0
  974. package/src/templates/reagentListBuilder.ts +30 -0
  975. package/src/templates/runNormalizers.ts +63 -0
  976. package/src/templates/sampleNormalizers.ts +58 -0
  977. package/src/templates/samplePrepAdapters.ts +63 -0
  978. package/src/templates/samplePrepBuilder.ts +51 -0
  979. package/src/templates/sampleSheetAdapters.ts +75 -0
  980. package/src/templates/sampleSheetBuilder.ts +23 -0
  981. package/src/templates/targetedMetabolomicsCollectionBuilder.ts +79 -0
  982. package/src/templates/targetedMetabolomicsHelpers.ts +102 -0
  983. package/src/templates/templateAdapterTypes.ts +58 -0
  984. package/src/templates/templateControlSchemas.ts +320 -0
  985. package/src/templates/templateCreateOptions.ts +208 -0
  986. package/src/templates/templateEnvelopes.ts +137 -0
  987. package/src/templates/templatePackCollectionBuilder.ts +23 -0
  988. package/src/templates/templatePresetCollectionBuilder.ts +139 -0
  989. package/src/templates/templateQpcrTypes.ts +48 -0
  990. package/src/templates/templateValidators.ts +414 -0
  991. package/src/templates/timeCourseAdapters.ts +73 -0
  992. package/src/templates/timeCourseBuilder.ts +64 -0
  993. package/src/templates/types.ts +493 -0
  994. package/src/templates/wellPlateScreenCollectionBuilder.ts +36 -0
  995. package/src/templates/westernBlotAssayCollectionBuilder.ts +68 -0
  996. package/src/types/analysisArtifactTypes.ts +176 -0
  997. package/src/types/auth.ts +59 -0
  998. package/src/types/auto-group.ts +157 -0
  999. package/src/types/componentLabTypes.ts +235 -0
  1000. package/src/types/componentWorkflowTypes.ts +190 -0
  1001. package/src/types/components.ts +527 -0
  1002. package/src/types/form-builder.ts +207 -0
  1003. package/src/types/generated-ui.ts +189 -0
  1004. package/src/types/index.ts +299 -0
  1005. package/src/types/instrument.ts +62 -0
  1006. package/src/types/jobs.ts +70 -0
  1007. package/src/types/platform.ts +132 -0
  1008. package/src/utils/color.ts +96 -0
  1009. package/src/utils/formModelSync.ts +52 -0
  1010. package/src/utils/items.ts +28 -0
  1011. package/src/utils/options.ts +23 -0
  1012. package/src/utils/pluginIcon.ts +190 -0
  1013. package/src/utils/rack.ts +209 -0
  1014. package/src/utils/sampleGroupPath.ts +19 -0
  1015. package/dist/ExperimentPopover-C1e0cd94.js +0 -3
  1016. package/dist/ExperimentSelectorModal-DCWTFyos.js +0 -4
  1017. package/dist/SettingsModal-Bpybht86.js +0 -5
@@ -0,0 +1,968 @@
1
+ import {
2
+ computed,
3
+ onMounted,
4
+ ref,
5
+ shallowRef,
6
+ watch,
7
+ type ComputedRef,
8
+ type Ref,
9
+ } from 'vue'
10
+ import {
11
+ AuthenticationRequiredError,
12
+ authenticationRequiredError,
13
+ useApi,
14
+ } from './useApi'
15
+ import { usePlatformContext } from './usePlatformContext'
16
+ import { useRequestSyncState } from './useRequestSyncState'
17
+ import { useAuthStore } from '../stores/auth'
18
+ import {
19
+ currentExperimentFromContext,
20
+ getInjectedPlatformContext,
21
+ resolveCurrentExperimentId,
22
+ } from './platformContextHelpers'
23
+ import {
24
+ buildPluginEndpointUrl,
25
+ hasKeys,
26
+ pluginEndpointRequestParts,
27
+ requestBodyFromPayload,
28
+ } from './pluginEndpointBuilder'
29
+ import {
30
+ useEventStream,
31
+ type EventStreamMessage,
32
+ type EventStreamTransport,
33
+ type UseEventStreamReturn,
34
+ } from './useEventStream'
35
+ import type {
36
+ ExperimentSummary,
37
+ GeneratedJobDefinition,
38
+ PageSelectorItem,
39
+ SettingsModalSchema,
40
+ TopBarSettingsConfig,
41
+ } from '../types'
42
+
43
+ export {
44
+ buildPluginEndpointUrl,
45
+ resolvePluginBaseUrl,
46
+ } from './pluginEndpointBuilder'
47
+
48
+ export type PluginHttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete'
49
+
50
+ export interface PluginEndpointContract {
51
+ name: string
52
+ operationId?: string
53
+ method: PluginHttpMethod
54
+ path: string
55
+ requiresAuth?: boolean
56
+ pathParams?: PluginEndpointParamContract[]
57
+ queryParams?: PluginEndpointParamContract[]
58
+ requestType?: string | null
59
+ requestContentType?: string | null
60
+ responseType?: string | null
61
+ responseContentType?: string | null
62
+ eventStream?: boolean
63
+ }
64
+
65
+ export interface PluginEndpointParamContract {
66
+ name: string
67
+ fieldName: string
68
+ type?: string
69
+ required?: boolean
70
+ }
71
+
72
+ export interface PluginNavItemContract {
73
+ path: string
74
+ label: string
75
+ id?: string
76
+ icon?: string
77
+ description?: string
78
+ requiresAuth?: boolean
79
+ requiresAdmin?: boolean
80
+ requiresFeature?: string
81
+ }
82
+
83
+ export interface PluginContractSettings {
84
+ modelName: string | null
85
+ /** Pydantic JSON Schema used to generate typed settings values. */
86
+ valueSchema: Record<string, unknown> | null
87
+ /** SDK SettingsModal schema used to render the settings form. */
88
+ formSchema: SettingsModalSchema | null
89
+ }
90
+
91
+ export interface PluginContract {
92
+ schemaVersion: 2
93
+ plugin: {
94
+ name?: string
95
+ packageName?: string
96
+ version?: string
97
+ description?: string
98
+ routesPrefix: string
99
+ apiPrefix: string
100
+ type: 'analysis' | 'experiment-design' | string
101
+ analysisType?: string
102
+ icon?: string
103
+ color?: string
104
+ navItems?: PluginNavItemContract[]
105
+ analysisResultReaders?: string[]
106
+ capabilities?: Record<string, unknown>
107
+ }
108
+ settings: PluginContractSettings
109
+ endpoints: PluginEndpointContract[]
110
+ schemas?: Record<string, Record<string, unknown>>
111
+ jobs?: GeneratedJobDefinition[]
112
+ hash: string
113
+ }
114
+
115
+ export interface PluginEndpointDefinition {
116
+ method: PluginHttpMethod
117
+ path: string
118
+ requiresAuth?: boolean
119
+ pathParams?: PluginEndpointParamDefinition[]
120
+ queryParams?: PluginEndpointParamDefinition[]
121
+ hasBody?: boolean
122
+ requestContentType?: string | null
123
+ eventStream?: boolean
124
+ responseType?: string | null
125
+ responseContentType?: string | null
126
+ }
127
+
128
+ export type PluginEndpointParamDefinition = string | {
129
+ name: string
130
+ fieldName?: string
131
+ type?: string
132
+ required?: boolean
133
+ }
134
+
135
+ export interface CreatePluginClientOptions {
136
+ endpoints: Record<string, PluginEndpointDefinition>
137
+ baseUrl?: string
138
+ }
139
+
140
+ export interface BuildPluginEndpointUrlOptions {
141
+ /** Override the generated or platform-injected API base URL. */
142
+ baseUrl?: string
143
+ /** Return only the endpoint path and query string instead of base URL + path. */
144
+ includeBaseUrl?: boolean
145
+ }
146
+
147
+ export interface PluginEndpointRequestOptions {
148
+ /** Override the generated or platform-injected API base URL. */
149
+ baseUrl?: string
150
+ /** Cancel the request without changing its endpoint or authentication behavior. */
151
+ signal?: AbortSignal
152
+ }
153
+
154
+ export interface PluginClientRequestOptions {
155
+ /** Cancel the generated endpoint request. */
156
+ signal?: AbortSignal
157
+ }
158
+
159
+ export interface DownloadPluginEndpointOptions extends PluginEndpointRequestOptions {
160
+ /** Browser download filename. When omitted, the blob is returned without triggering a download. */
161
+ filename?: string
162
+ /** Delay before revoking the object URL after a browser download is triggered. */
163
+ revokeObjectUrlDelayMs?: number
164
+ }
165
+
166
+ export interface DownloadBlobOptions {
167
+ /** Delay before revoking the object URL after a browser download is triggered. */
168
+ revokeObjectUrlDelayMs?: number
169
+ }
170
+
171
+ export type PluginSettingsValues<TSettings> = Partial<TSettings> & Record<string, unknown>
172
+
173
+ export interface UsePluginSettingsOptions {
174
+ /** Plugin name for platform persistence. Defaults to the integrated platform plugin name. */
175
+ pluginName?: string
176
+ /** Plugin API base URL for standalone/local settings routes. Generated clients pass pluginApiPrefix. */
177
+ apiBaseUrl?: string
178
+ /** Platform API base URL for /plugins/{name}/config. Defaults to the injected platform API URL. */
179
+ platformApiBaseUrl?: string
180
+ /** SettingsModal schema generated from the backend plugin config model. */
181
+ schema?: SettingsModalSchema | null
182
+ /** SettingsModal title when using settingsConfig. */
183
+ title?: string
184
+ /** Whether SettingsModal should include SDK appearance controls. */
185
+ showAppearance?: boolean
186
+ /** Load persisted values on component mount. */
187
+ loadOnMount?: boolean
188
+ }
189
+
190
+ export interface UsePluginSettingsReturn<TSettings = Record<string, unknown>> {
191
+ /** Current typed settings values. */
192
+ settings: ComputedRef<PluginSettingsValues<TSettings>>
193
+ /** Editable settings values for SettingsModal. */
194
+ values: Ref<PluginSettingsValues<TSettings>>
195
+ /** Alias for values, kept for callers that think in platform config terms. */
196
+ config: Ref<PluginSettingsValues<TSettings>>
197
+ /** Ready-to-pass AppTopBar/PluginWorkspaceView settingsConfig. */
198
+ settingsConfig: ComputedRef<TopBarSettingsConfig>
199
+ isLoading: Ref<boolean>
200
+ isSaving: Ref<boolean>
201
+ error: Ref<string | null>
202
+ lastLoadedAt: Ref<Date | null>
203
+ lastSavedAt: Ref<Date | null>
204
+ isDirty: ComputedRef<boolean>
205
+ setValues: (values: Record<string, unknown>) => void
206
+ load: () => Promise<void>
207
+ save: (values?: Record<string, unknown>) => Promise<boolean>
208
+ reset: () => void
209
+ }
210
+
211
+ export type PluginEventStreamMessage<TData = string> = EventStreamMessage<TData>
212
+
213
+ export interface PluginEventStreamOptions<TData = string> {
214
+ /** Override the generated or platform-injected API base URL. */
215
+ baseUrl?: string
216
+ /** Start the stream immediately. Defaults to true. */
217
+ immediate?: boolean
218
+ /** Reconnect after errors or server closes. Defaults to true. */
219
+ reconnect?: boolean
220
+ /** Delay before reconnecting after a stream failure or close. Defaults to 2000ms. */
221
+ reconnectDelayMs?: number
222
+ /** Parse `data:` as JSON. Defaults to true for typed endpoints and false otherwise. */
223
+ parseJson?: boolean
224
+ /** Fetch credentials mode. Defaults to same-origin. */
225
+ credentials?: RequestCredentials
226
+ /** Extra request headers. Authorization is injected unless already supplied. */
227
+ headers?: Record<string, string>
228
+ onOpen?: () => void
229
+ onMessage?: (message: PluginEventStreamMessage<TData>) => void
230
+ onError?: (error: unknown) => void
231
+ }
232
+
233
+ export type UsePluginEventStreamReturn<TData = string> = UseEventStreamReturn<TData>
234
+
235
+ export type PluginFormDataValue =
236
+ | string
237
+ | number
238
+ | boolean
239
+ | Blob
240
+ | null
241
+ | undefined
242
+ | Record<string, unknown>
243
+
244
+ export type PluginFormDataPayload = Record<string, PluginFormDataValue | PluginFormDataValue[]>
245
+
246
+ export interface UseCurrentExperimentOptions {
247
+ apiBaseUrl?: string
248
+ immediate?: boolean
249
+ }
250
+
251
+ export interface UseCurrentExperimentReturn<TExperiment = ExperimentSummary> {
252
+ /** Current experiment id resolved from platform injection or URL conventions. */
253
+ experimentId: ComputedRef<number | undefined>
254
+ /** Whether a current experiment id is available. */
255
+ hasExperiment: ComputedRef<boolean>
256
+ /** Current experiment payload, if injected or successfully fetched. */
257
+ experiment: Ref<TExperiment | undefined>
258
+ /** Whether the current experiment is currently loading. */
259
+ isLoading: Ref<boolean>
260
+ /** Error message from the last failed current-experiment fetch, or null. */
261
+ error: Ref<string | null>
262
+ /** Timestamp of the last successful current-experiment fetch, or null. */
263
+ lastLoadedAt: Ref<Date | null>
264
+ /** Return the current experiment id or throw a clear SDK error when absent. */
265
+ requireExperimentId: () => number
266
+ /** Fetch a specific experiment id, defaulting to the current experiment id. */
267
+ fetch: (experimentId?: number) => Promise<TExperiment | undefined>
268
+ /** Refetch the currently resolved experiment id. */
269
+ refresh: () => Promise<TExperiment | undefined>
270
+ }
271
+
272
+ export type PluginEndpointCaller = (
273
+ payloadOrOptions?: unknown,
274
+ options?: PluginClientRequestOptions,
275
+ ) => Promise<unknown>
276
+ export type GeneratedPluginClient = Record<string, (...args: any[]) => Promise<any>>
277
+
278
+ function queryConfig(query: Record<string, unknown>) {
279
+ return hasKeys(query) ? { params: query } : undefined
280
+ }
281
+
282
+ const OCTET_STREAM = 'application/octet-stream'
283
+ const MULTIPART_FORM_DATA = 'multipart/form-data'
284
+
285
+ function endpointRequestConfig(
286
+ endpoint: PluginEndpointDefinition,
287
+ query: Record<string, unknown>,
288
+ options?: PluginClientRequestOptions,
289
+ ) {
290
+ const config: Record<string, unknown> = {}
291
+ if (hasKeys(query)) config.params = query
292
+ if (endpoint.requestContentType === OCTET_STREAM) {
293
+ config.headers = { 'Content-Type': OCTET_STREAM }
294
+ }
295
+ if (endpoint.requestContentType === MULTIPART_FORM_DATA) {
296
+ config.headers = { 'Content-Type': undefined }
297
+ }
298
+ if (endpoint.responseContentType === OCTET_STREAM) {
299
+ config.responseType = 'blob'
300
+ }
301
+ if (options?.signal) config.signal = options.signal
302
+ return hasKeys(config) ? config : undefined
303
+ }
304
+
305
+ function isFormData(value: unknown): value is FormData {
306
+ return typeof FormData !== 'undefined' && value instanceof FormData
307
+ }
308
+
309
+ function endpointRequestBody(endpoint: PluginEndpointDefinition, body: unknown): unknown {
310
+ return endpoint.requestContentType === MULTIPART_FORM_DATA
311
+ ? pluginFormDataFromPayload(body)
312
+ : body
313
+ }
314
+
315
+ function endpointHasPayload(endpoint: PluginEndpointDefinition): boolean {
316
+ return Boolean(
317
+ endpoint.hasBody
318
+ || endpoint.pathParams?.length
319
+ || endpoint.queryParams?.length,
320
+ )
321
+ }
322
+
323
+ function isBlob(value: unknown): value is Blob {
324
+ return typeof Blob !== 'undefined' && value instanceof Blob
325
+ }
326
+
327
+ function appendFormDataValue(formData: FormData, key: string, value: PluginFormDataValue | PluginFormDataValue[]): void {
328
+ if (value === undefined || value === null) return
329
+
330
+ if (Array.isArray(value)) {
331
+ for (const item of value) {
332
+ appendFormDataValue(formData, key, item)
333
+ }
334
+ return
335
+ }
336
+
337
+ if (isBlob(value)) {
338
+ formData.append(key, value)
339
+ return
340
+ }
341
+
342
+ if (typeof value === 'object') {
343
+ formData.append(key, JSON.stringify(value))
344
+ return
345
+ }
346
+
347
+ formData.append(key, String(value))
348
+ }
349
+
350
+ /** Convert plain upload payloads into FormData using the same encoding across generated plugin clients. */
351
+ export function pluginFormDataFromPayload(payload: unknown): FormData {
352
+ if (isFormData(payload)) return payload
353
+ if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
354
+ throw new Error('[MINT SDK] Plugin upload endpoints require a FormData or plain object payload.')
355
+ }
356
+
357
+ const formData = new FormData()
358
+ for (const [key, value] of Object.entries(payload as PluginFormDataPayload)) {
359
+ appendFormDataValue(formData, key, value)
360
+ }
361
+ return formData
362
+ }
363
+
364
+ /** Trigger a browser download for an already-created Blob. */
365
+ export function downloadBlob(blob: Blob, filename: string, options: DownloadBlobOptions = {}): void {
366
+ if (typeof document === 'undefined' || typeof URL === 'undefined') {
367
+ throw new Error('[MINT SDK] Cannot trigger a file download outside a browser.')
368
+ }
369
+
370
+ const blobUrl = URL.createObjectURL(blob)
371
+ const link = document.createElement('a')
372
+ link.href = blobUrl
373
+ link.download = filename
374
+ document.body.appendChild(link)
375
+ link.click()
376
+ document.body.removeChild(link)
377
+ setTimeout(() => URL.revokeObjectURL(blobUrl), options.revokeObjectUrlDelayMs ?? 100)
378
+ }
379
+
380
+ function normalizePluginNavPath(path: string): string {
381
+ const raw = path.trim() || '/'
382
+ const prefixed = raw.startsWith('/') ? raw : `/${raw}`
383
+ return prefixed.replace(/\/+$/, '') || '/'
384
+ }
385
+
386
+ function pluginPageIdFromPath(path: string, fallbackIndex: number): string {
387
+ const normalizedPath = normalizePluginNavPath(path)
388
+ if (normalizedPath === '/') return 'dashboard'
389
+ return normalizedPath.replace(/^\/+/, '').replace(/\/+/g, '-') || `page-${fallbackIndex + 1}`
390
+ }
391
+
392
+ /** Convert resolved @mint_plugin nav_items into page selectors for the topbar and homepage PluginCards. */
393
+ export function getPluginPageSelectorItems(contract: PluginContract): PageSelectorItem[] {
394
+ const pluginIcon = contract.plugin.icon ?? ''
395
+ const navItems = contract.plugin.navItems ?? []
396
+ return navItems.map((item, index) => ({
397
+ id: item.id || pluginPageIdFromPath(item.path, index),
398
+ label: item.label,
399
+ to: normalizePluginNavPath(item.path),
400
+ icon: item.icon || pluginIcon || undefined,
401
+ }))
402
+ }
403
+
404
+ /** Create a typed plugin API client from a generated MINT plugin contract. */
405
+ export function createPluginClient<TClient extends object = GeneratedPluginClient>(
406
+ contract: PluginContract,
407
+ options: CreatePluginClientOptions,
408
+ ): TClient {
409
+ const client: Record<string, PluginEndpointCaller> = {}
410
+
411
+ for (const [name, endpoint] of Object.entries(options.endpoints)) {
412
+ client[name] = async (
413
+ payloadOrOptions?: unknown,
414
+ explicitOptions?: PluginClientRequestOptions,
415
+ ) => {
416
+ const hasPayload = endpointHasPayload(endpoint)
417
+ const payload = hasPayload ? payloadOrOptions : undefined
418
+ const callOptions = hasPayload
419
+ ? explicitOptions
420
+ : (payloadOrOptions as PluginClientRequestOptions | undefined) ?? explicitOptions
421
+ const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl)
422
+ const api = useApi({
423
+ baseUrl: parts.baseUrl,
424
+ withAuth: endpoint.requiresAuth !== false,
425
+ })
426
+ const config = endpointRequestConfig(endpoint, parts.query, callOptions)
427
+
428
+ if (endpoint.method === 'get') {
429
+ return api.get(parts.path, config)
430
+ }
431
+
432
+ if (endpoint.method === 'delete') {
433
+ const rawBody = requestBodyFromPayload(payload, parts.requestPayload, endpoint)
434
+ const body = rawBody === undefined ? undefined : endpointRequestBody(endpoint, rawBody)
435
+ const config = body === undefined
436
+ ? endpointRequestConfig(endpoint, parts.query, callOptions)
437
+ : { ...endpointRequestConfig(endpoint, parts.query, callOptions), data: body }
438
+ return api.delete(parts.path, config)
439
+ }
440
+
441
+ const body = endpointRequestBody(
442
+ endpoint,
443
+ requestBodyFromPayload(payload, parts.requestPayload, endpoint),
444
+ )
445
+
446
+ if (endpoint.method === 'post') return api.post(parts.path, body, config)
447
+ if (endpoint.method === 'put') return api.put(parts.path, body, config)
448
+ if (endpoint.method === 'patch') return api.patch(parts.path, body, config)
449
+ throw new Error(`[MINT SDK] Unsupported plugin endpoint method: ${endpoint.method}`)
450
+ }
451
+ }
452
+
453
+ return client as TClient
454
+ }
455
+
456
+ /** Send multipart or raw binary data to a generated endpoint with contract URL, cancellation, and auth handling. */
457
+ export async function uploadPluginEndpoint<TResponse = unknown>(
458
+ contract: PluginContract,
459
+ endpoint: PluginEndpointDefinition,
460
+ payload?: unknown,
461
+ options: PluginEndpointRequestOptions = {},
462
+ ): Promise<TResponse> {
463
+ if (!['post', 'put', 'patch'].includes(endpoint.method)) {
464
+ throw new Error(`[MINT SDK] Plugin upload endpoints must use POST, PUT, or PATCH; got ${endpoint.method}`)
465
+ }
466
+
467
+ const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl)
468
+ const api = useApi({
469
+ baseUrl: parts.baseUrl,
470
+ withAuth: endpoint.requiresAuth !== false,
471
+ })
472
+ const body = endpoint.hasBody
473
+ ? requestBodyFromPayload(payload, parts.requestPayload, endpoint)
474
+ : payload
475
+ if (endpoint.requestContentType === OCTET_STREAM) {
476
+ const config = endpointRequestConfig(endpoint, parts.query, { signal: options.signal })
477
+ if (endpoint.method === 'post') return api.post<TResponse>(parts.path, body, config)
478
+ if (endpoint.method === 'put') return api.put<TResponse>(parts.path, body, config)
479
+ return api.patch<TResponse>(parts.path, body, config)
480
+ }
481
+ const formData = pluginFormDataFromPayload(body)
482
+ const config = {
483
+ ...(queryConfig(parts.query) ?? {}),
484
+ ...(options.signal ? { signal: options.signal } : {}),
485
+ // Let Axios/browser set multipart boundaries.
486
+ headers: { 'Content-Type': undefined },
487
+ }
488
+
489
+ if (endpoint.method === 'post') return api.post<TResponse>(parts.path, formData, config)
490
+ if (endpoint.method === 'put') return api.put<TResponse>(parts.path, formData, config)
491
+ return api.patch<TResponse>(parts.path, formData, config)
492
+ }
493
+
494
+ /** Fetch a generated plugin endpoint as a Blob and optionally trigger a browser download. */
495
+ export async function downloadPluginEndpoint(
496
+ contract: PluginContract,
497
+ endpoint: PluginEndpointDefinition,
498
+ payload?: unknown,
499
+ options: DownloadPluginEndpointOptions = {},
500
+ ): Promise<Blob> {
501
+ if (endpoint.requestContentType === MULTIPART_FORM_DATA) {
502
+ throw new Error('[MINT SDK] Plugin download endpoints do not support multipart request bodies')
503
+ }
504
+
505
+ const parts = pluginEndpointRequestParts(contract, endpoint, payload, options.baseUrl)
506
+ const api = useApi({
507
+ baseUrl: parts.baseUrl,
508
+ withAuth: endpoint.requiresAuth !== false,
509
+ })
510
+ const config = {
511
+ ...(endpointRequestConfig(endpoint, parts.query, { signal: options.signal }) ?? {}),
512
+ responseType: 'blob' as const,
513
+ }
514
+ const rawBody = requestBodyFromPayload(payload, parts.requestPayload, endpoint)
515
+ const body = rawBody === undefined ? undefined : endpointRequestBody(endpoint, rawBody)
516
+ let blob: Blob
517
+
518
+ if (endpoint.method === 'get') blob = await api.get<Blob>(parts.path, config)
519
+ else if (endpoint.method === 'post') blob = await api.post<Blob>(parts.path, body, config)
520
+ else if (endpoint.method === 'put') blob = await api.put<Blob>(parts.path, body, config)
521
+ else if (endpoint.method === 'patch') blob = await api.patch<Blob>(parts.path, body, config)
522
+ else if (endpoint.method === 'delete') {
523
+ blob = await api.delete<Blob>(parts.path, body === undefined ? config : { ...config, data: body })
524
+ } else {
525
+ throw new Error(`[MINT SDK] Unsupported plugin endpoint method: ${endpoint.method}`)
526
+ }
527
+
528
+ if (options.filename) {
529
+ downloadBlob(blob, options.filename, {
530
+ revokeObjectUrlDelayMs: options.revokeObjectUrlDelayMs,
531
+ })
532
+ }
533
+
534
+ return blob
535
+ }
536
+
537
+ function normalizePluginSettingsOptions(options: UsePluginSettingsOptions | string = {}): UsePluginSettingsOptions {
538
+ return typeof options === 'string' ? { pluginName: options } : options
539
+ }
540
+
541
+ /** @deprecated Use `useGeneratedPluginClient()` for generated clients. */
542
+ export function usePluginClient<TClient>(client: TClient): TClient {
543
+ return client
544
+ }
545
+
546
+ const PLATFORM_OWNED_SETTINGS_KEY = 'allowed_experiment_types'
547
+
548
+ function cloneRecord(value: Record<string, unknown>): Record<string, unknown> {
549
+ return JSON.parse(JSON.stringify(value)) as Record<string, unknown>
550
+ }
551
+
552
+ function hasOwnSetting(settings: Record<string, unknown>, key: string): boolean {
553
+ return Object.prototype.hasOwnProperty.call(settings, key)
554
+ }
555
+
556
+ function responseSettingsPayload(response: unknown): Record<string, unknown> {
557
+ if (!response || typeof response !== 'object') return {}
558
+ const data = response as {
559
+ config?: unknown
560
+ settings?: unknown
561
+ }
562
+ if (data.config && typeof data.config === 'object') {
563
+ return cloneRecord(data.config as Record<string, unknown>)
564
+ }
565
+ if (data.settings && typeof data.settings === 'object') {
566
+ return cloneRecord(data.settings as Record<string, unknown>)
567
+ }
568
+ return {}
569
+ }
570
+
571
+ function responseSettingsRevision(response: unknown): string | null {
572
+ if (!response || typeof response !== 'object') return null
573
+ const revision = (response as { revision?: unknown }).revision
574
+ return typeof revision === 'string' && revision ? revision : null
575
+ }
576
+
577
+ function topLevelSettingsPatch(
578
+ current: Record<string, unknown>,
579
+ keys: Iterable<string>,
580
+ ): Record<string, unknown> {
581
+ return Object.fromEntries(
582
+ [...keys].map(key => [
583
+ key,
584
+ hasOwnSetting(current, key) ? current[key] : null,
585
+ ]),
586
+ )
587
+ }
588
+
589
+ function changedTopLevelSettingKeys(
590
+ current: Record<string, unknown>,
591
+ saved: Record<string, unknown>,
592
+ ): Set<string> {
593
+ return new Set(
594
+ [...new Set([...Object.keys(current), ...Object.keys(saved)])].filter(
595
+ key => JSON.stringify(current[key]) !== JSON.stringify(saved[key]),
596
+ ),
597
+ )
598
+ }
599
+
600
+ function platformOwnedSettingsPatch(settings: Record<string, unknown>): Record<string, unknown> {
601
+ return {
602
+ [PLATFORM_OWNED_SETTINGS_KEY]: hasOwnSetting(settings, PLATFORM_OWNED_SETTINGS_KEY)
603
+ ? settings[PLATFORM_OWNED_SETTINGS_KEY]
604
+ : null,
605
+ }
606
+ }
607
+
608
+ /** Load, edit, and persist plugin settings from platform config or the plugin-local settings router. */
609
+ export function usePluginSettings<TSettings = Record<string, unknown>>(
610
+ options: UsePluginSettingsOptions | string = {},
611
+ ): UsePluginSettingsReturn<TSettings> {
612
+ const resolvedOptions = normalizePluginSettingsOptions(options)
613
+ const injectedContext = getInjectedPlatformContext()
614
+ const { plugin, isIntegrated } = usePlatformContext()
615
+ const platformApi = useApi({ baseUrl: resolvedOptions.platformApiBaseUrl ?? injectedContext?.platformApiUrl })
616
+ const pluginApi = useApi({ baseUrl: resolvedOptions.apiBaseUrl ?? injectedContext?.plugin?.api_prefix })
617
+
618
+ const values = ref({}) as Ref<PluginSettingsValues<TSettings>>
619
+ const savedValues = shallowRef<Record<string, unknown>>({})
620
+ const revision = ref<string | null>(null)
621
+ const request = useRequestSyncState('Plugin settings request failed.')
622
+ const isLoading = ref(false)
623
+ const isSaving = ref(false)
624
+
625
+ const resolvedPluginName = computed(() =>
626
+ resolvedOptions.pluginName ?? plugin.value?.name ?? injectedContext?.plugin?.name ?? '',
627
+ )
628
+ const usesPluginSettingsApi = computed(() => {
629
+ const currentPlugin = injectedContext?.plugin ?? plugin.value
630
+ return currentPlugin?.settings_api === 'plugin'
631
+ && resolvedPluginName.value === currentPlugin.name
632
+ })
633
+ const usesPlatformConfig = computed(() =>
634
+ Boolean(
635
+ (isIntegrated.value || injectedContext?.isIntegrated)
636
+ && resolvedPluginName.value
637
+ && !usesPluginSettingsApi.value,
638
+ ),
639
+ )
640
+ const settings = computed(() => values.value)
641
+ const isDirty = computed(() => JSON.stringify(values.value) !== JSON.stringify(savedValues.value))
642
+ const settingsConfig = computed<TopBarSettingsConfig>(() => ({
643
+ title: resolvedOptions.title,
644
+ schema: resolvedOptions.schema ?? undefined,
645
+ showAppearance: resolvedOptions.showAppearance,
646
+ values: values.value,
647
+ }))
648
+
649
+ function setValues(nextValues: Record<string, unknown>): void {
650
+ values.value = cloneRecord(nextValues) as PluginSettingsValues<TSettings>
651
+ }
652
+
653
+ function applyLoaded(nextValues: Record<string, unknown>, nextRevision: string | null): void {
654
+ const cloned = cloneRecord(nextValues)
655
+ values.value = cloned as PluginSettingsValues<TSettings>
656
+ savedValues.value = cloneRecord(cloned)
657
+ revision.value = nextRevision
658
+ }
659
+
660
+ async function load(): Promise<void> {
661
+ isLoading.value = true
662
+ try {
663
+ const response = usesPlatformConfig.value
664
+ ? await request.run(
665
+ () => platformApi.get<{ plugin_name: string; config: Record<string, unknown> }>(
666
+ `/plugins/${encodeURIComponent(resolvedPluginName.value)}/config`,
667
+ ),
668
+ { success: 'load', errorMessage: 'Failed to load plugin settings' },
669
+ )
670
+ : await request.run(
671
+ () => pluginApi.get<{ settings: Record<string, unknown>; mode?: string }>('/settings'),
672
+ { success: 'load', errorMessage: 'Failed to load plugin settings' },
673
+ )
674
+ applyLoaded(
675
+ responseSettingsPayload(response),
676
+ responseSettingsRevision(response),
677
+ )
678
+ } catch {
679
+ // Error state is handled by request.run().
680
+ } finally {
681
+ isLoading.value = false
682
+ }
683
+ }
684
+
685
+ async function save(nextValues?: Record<string, unknown>): Promise<boolean> {
686
+ if (nextValues) {
687
+ setValues(nextValues)
688
+ }
689
+
690
+ isSaving.value = true
691
+ try {
692
+ const payload = cloneRecord(values.value)
693
+ let response: unknown
694
+ if (usesPlatformConfig.value) {
695
+ const dirtyKeys = changedTopLevelSettingKeys(payload, savedValues.value)
696
+ const platformOwnedChanged = dirtyKeys.has(PLATFORM_OWNED_SETTINGS_KEY)
697
+ const typedKeys = [...dirtyKeys].filter(
698
+ key => key !== PLATFORM_OWNED_SETTINGS_KEY,
699
+ )
700
+ let nextRevision = revision.value
701
+
702
+ if (typedKeys.length) {
703
+ response = await request.run(
704
+ () => platformApi.patch<{
705
+ plugin_name: string
706
+ config: Record<string, unknown>
707
+ revision?: string
708
+ }>(
709
+ `/plugins/${encodeURIComponent(resolvedPluginName.value)}/config`,
710
+ { config: topLevelSettingsPatch(payload, typedKeys) },
711
+ ),
712
+ { success: 'save', errorMessage: 'Failed to save plugin settings' },
713
+ )
714
+ nextRevision = responseSettingsRevision(response) ?? nextRevision
715
+ }
716
+
717
+ if (platformOwnedChanged) {
718
+ response = await request.run(
719
+ () => platformApi.patch<{
720
+ plugin_name: string
721
+ config: Record<string, unknown>
722
+ revision?: string
723
+ }>(
724
+ `/plugins/${encodeURIComponent(resolvedPluginName.value)}/config`,
725
+ { config: platformOwnedSettingsPatch(payload) },
726
+ ),
727
+ { success: 'save', errorMessage: 'Failed to save plugin settings' },
728
+ )
729
+ nextRevision = responseSettingsRevision(response) ?? nextRevision
730
+ }
731
+
732
+ if (!response) return true
733
+ applyLoaded(responseSettingsPayload(response), nextRevision)
734
+ return true
735
+ } else {
736
+ const ifMatch = revision.value
737
+ ? { headers: { 'If-Match': `"${revision.value}"` } }
738
+ : undefined
739
+ response = await request.run(
740
+ () => pluginApi.put<{
741
+ settings: Record<string, unknown>
742
+ mode?: string
743
+ revision?: string
744
+ }>('/settings', payload, ifMatch),
745
+ { success: 'save', errorMessage: 'Failed to save plugin settings' },
746
+ )
747
+ }
748
+ applyLoaded(
749
+ responseSettingsPayload(response),
750
+ responseSettingsRevision(response) ?? revision.value,
751
+ )
752
+ return true
753
+ } catch {
754
+ return false
755
+ } finally {
756
+ isSaving.value = false
757
+ }
758
+ }
759
+
760
+ function reset(): void {
761
+ values.value = cloneRecord(savedValues.value) as PluginSettingsValues<TSettings>
762
+ request.clearError()
763
+ }
764
+
765
+ onMounted(() => {
766
+ if (resolvedOptions.loadOnMount !== false) {
767
+ void load()
768
+ }
769
+ })
770
+
771
+ return {
772
+ settings,
773
+ values,
774
+ config: values,
775
+ settingsConfig,
776
+ isLoading,
777
+ isSaving,
778
+ error: request.error,
779
+ lastLoadedAt: request.lastLoadedAt,
780
+ lastSavedAt: request.lastSavedAt,
781
+ isDirty,
782
+ setValues,
783
+ load,
784
+ save,
785
+ reset,
786
+ }
787
+ }
788
+
789
+ function streamRequestAuth(
790
+ requestHeaders: HeadersInit | undefined,
791
+ policy: { requiresAuth: boolean },
792
+ ): {
793
+ headers: Headers
794
+ token?: string
795
+ } {
796
+ const headers = new Headers(requestHeaders)
797
+ const authStore = useAuthStore()
798
+ if (!authStore.isInitialized) {
799
+ authStore.initialize()
800
+ }
801
+ if (policy.requiresAuth && authStore.token && !headers.has('Authorization')) {
802
+ headers.set('Authorization', `Bearer ${authStore.token}`)
803
+ }
804
+ const token = policy.requiresAuth ? authStore.token : undefined
805
+ return {
806
+ headers,
807
+ token: token && headers.get('Authorization') === `Bearer ${token}` ? token : undefined,
808
+ }
809
+ }
810
+
811
+ function pluginEventStreamTransport(
812
+ endpoint: PluginEndpointDefinition,
813
+ ): EventStreamTransport {
814
+ return async (url, init = {}) => {
815
+ if (typeof fetch !== 'function') {
816
+ throw new Error('[MINT SDK] fetch is required for plugin event streams.')
817
+ }
818
+ const requestAuth = streamRequestAuth(
819
+ init.headers,
820
+ { requiresAuth: endpoint.requiresAuth !== false },
821
+ )
822
+ const response = await fetch(url, { ...init, headers: requestAuth.headers })
823
+ if (response.status === 401) {
824
+ throw authenticationRequiredError(response, requestAuth.token)
825
+ }
826
+ return response
827
+ }
828
+ }
829
+
830
+ function looksLikeEventStreamOptions(value: unknown): value is PluginEventStreamOptions {
831
+ if (!value || typeof value !== 'object') return false
832
+ const candidate = value as Record<string, unknown>
833
+ return [
834
+ 'baseUrl',
835
+ 'immediate',
836
+ 'reconnect',
837
+ 'reconnectDelayMs',
838
+ 'parseJson',
839
+ 'credentials',
840
+ 'headers',
841
+ 'onOpen',
842
+ 'onMessage',
843
+ 'onError',
844
+ ].some(key => key in candidate)
845
+ }
846
+
847
+ /** Consume a generated plugin SSE endpoint with auth headers, reconnect, and teardown. */
848
+ export function usePluginEventStream<TData = string>(
849
+ contract: PluginContract,
850
+ endpoint: PluginEndpointDefinition,
851
+ options?: PluginEventStreamOptions<TData>,
852
+ ): UsePluginEventStreamReturn<TData>
853
+ export function usePluginEventStream<TData = string>(
854
+ contract: PluginContract,
855
+ endpoint: PluginEndpointDefinition,
856
+ payload?: unknown,
857
+ options?: PluginEventStreamOptions<TData>,
858
+ ): UsePluginEventStreamReturn<TData>
859
+ export function usePluginEventStream<TData = string>(
860
+ contract: PluginContract,
861
+ endpoint: PluginEndpointDefinition,
862
+ payloadOrOptions?: unknown,
863
+ maybeOptions?: PluginEventStreamOptions<TData>,
864
+ ): UsePluginEventStreamReturn<TData> {
865
+ if (endpoint.method !== 'get') {
866
+ throw new Error(`[MINT SDK] Plugin event streams must use GET; got ${endpoint.method}`)
867
+ }
868
+ const payload = maybeOptions === undefined && looksLikeEventStreamOptions(payloadOrOptions)
869
+ ? undefined
870
+ : payloadOrOptions
871
+ const options = (
872
+ maybeOptions === undefined && looksLikeEventStreamOptions(payloadOrOptions)
873
+ ? payloadOrOptions
874
+ : maybeOptions ?? {}
875
+ ) as PluginEventStreamOptions<TData>
876
+ const responseType = endpoint.responseType?.trim()
877
+ const parseJson = options.parseJson ?? Boolean(responseType && responseType !== 'string')
878
+ return useEventStream<TData>(
879
+ () => buildPluginEndpointUrl(contract, endpoint, payload, { baseUrl: options.baseUrl }),
880
+ {
881
+ transport: pluginEventStreamTransport(endpoint),
882
+ immediate: options.immediate,
883
+ reconnect: options.reconnect,
884
+ reconnectDelayMs: options.reconnectDelayMs,
885
+ parseJson,
886
+ credentials: options.credentials,
887
+ headers: options.headers,
888
+ shouldReconnect: cause => !(cause instanceof AuthenticationRequiredError),
889
+ onOpen: options.onOpen,
890
+ onMessage: options.onMessage,
891
+ onError: options.onError,
892
+ errorLabel: 'Plugin event stream',
893
+ },
894
+ )
895
+ }
896
+
897
+ /** Read and optionally load the current platform experiment for integrated plugin views. */
898
+ export function useCurrentExperiment<TExperiment = ExperimentSummary>(
899
+ options: UseCurrentExperimentOptions = {},
900
+ ): UseCurrentExperimentReturn<TExperiment> {
901
+ const api = useApi({ baseUrl: options.apiBaseUrl ?? getInjectedPlatformContext()?.platformApiUrl })
902
+ const experiment = shallowRef<TExperiment | undefined>(currentExperimentFromContext<TExperiment>())
903
+ const request = useRequestSyncState('Failed to load current experiment')
904
+ const isLoading = request.loading
905
+ const error = request.error
906
+ const lastLoadedAt = request.lastLoadedAt
907
+
908
+ const experimentId = computed<number | undefined>(() => {
909
+ return resolveCurrentExperimentId()
910
+ })
911
+ const hasExperiment = computed(() => experimentId.value !== undefined)
912
+
913
+ function requireExperimentId(): number {
914
+ const id = experimentId.value
915
+ if (id === undefined) {
916
+ throw new Error('[MINT SDK] No current experiment is selected.')
917
+ }
918
+ return id
919
+ }
920
+
921
+ async function fetchExperiment(id = experimentId.value): Promise<TExperiment | undefined> {
922
+ if (id === undefined) {
923
+ experiment.value = currentExperimentFromContext<TExperiment>()
924
+ return experiment.value
925
+ }
926
+
927
+ try {
928
+ const result = await request.run(
929
+ () => api.get<TExperiment>(`/experiments/${id}`),
930
+ { success: 'load', errorMessage: 'Failed to load current experiment' },
931
+ )
932
+ experiment.value = result
933
+ return result
934
+ } catch (e) {
935
+ experiment.value = undefined
936
+ return undefined
937
+ }
938
+ }
939
+
940
+ async function refresh(): Promise<TExperiment | undefined> {
941
+ return fetchExperiment()
942
+ }
943
+
944
+ watch(
945
+ experimentId,
946
+ (id) => {
947
+ if (options.immediate === false) return
948
+ if (id === undefined) {
949
+ experiment.value = currentExperimentFromContext<TExperiment>()
950
+ return
951
+ }
952
+ void fetchExperiment(id)
953
+ },
954
+ { immediate: options.immediate !== false },
955
+ )
956
+
957
+ return {
958
+ experimentId,
959
+ hasExperiment,
960
+ experiment,
961
+ isLoading,
962
+ error,
963
+ lastLoadedAt,
964
+ requireExperimentId,
965
+ fetch: fetchExperiment,
966
+ refresh,
967
+ }
968
+ }