@morscherlab/mint-sdk 1.2.0-beta.2 → 1.2.0-beta.20

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 (493) hide show
  1. package/README.md +65 -5
  2. package/dist/{ExperimentPopover-tLwJ7XF4.js → ExperimentPopover-CJdNlCZb.js} +24 -15
  3. package/dist/ExperimentPopover-CJdNlCZb.js.map +1 -0
  4. package/dist/{ExperimentSelectorModal-DyPAUCLw.js → ExperimentSelectorModal-DCXmwKNS.js} +5 -5
  5. package/dist/ExperimentSelectorModal-DCXmwKNS.js.map +1 -0
  6. package/dist/{SettingsModal-BgKY93zh.js → SettingsModal-BYR20I4c.js} +5 -8
  7. package/dist/SettingsModal-BYR20I4c.js.map +1 -0
  8. package/dist/{EmptyState-p90quq8Z.js → Skeleton-BAF3CKY7.js} +111 -93
  9. package/dist/Skeleton-BAF3CKY7.js.map +1 -0
  10. package/dist/__tests__/components/DataStates.test.d.ts +1 -0
  11. package/dist/__tests__/components/ExperimentTimeline.test.d.ts +1 -0
  12. package/dist/__tests__/components/FileBrowserModal.test.d.ts +1 -0
  13. package/dist/__tests__/components/FilePicker.state.test.d.ts +1 -0
  14. package/dist/__tests__/components/FilePicker.test.d.ts +1 -0
  15. package/dist/__tests__/components/PlotlyChart.test.d.ts +1 -0
  16. package/dist/__tests__/components/PluginWorkspaceView.internal.test.d.ts +1 -0
  17. package/dist/__tests__/components/SecretInput.test.d.ts +1 -0
  18. package/dist/__tests__/components/WellEditPopupInternal.test.d.ts +1 -0
  19. package/dist/__tests__/components/iconButtonIconSizing.test.d.ts +1 -0
  20. package/dist/__tests__/composables/useFileBrowser.test.d.ts +1 -0
  21. package/dist/__tests__/composables/useListReorder.test.d.ts +1 -0
  22. package/dist/__tests__/composables/usePlatformFilePickerAdapter.test.d.ts +1 -0
  23. package/dist/__tests__/composables/usePluginConfig.test.d.ts +15 -0
  24. package/dist/__tests__/styles/cssTokens.test.d.ts +1 -0
  25. package/dist/apiErrors.d.ts +26 -0
  26. package/dist/components/ActionMenu.vue.d.ts +1 -1
  27. package/dist/components/AppAvatarMenu.vue.d.ts +4 -0
  28. package/dist/components/AppPluginSwitcher.vue.d.ts +2 -0
  29. package/dist/components/AppSidebar.vue.d.ts +1 -1
  30. package/dist/components/AuditTrail.vue.d.ts +13 -0
  31. package/dist/components/AutoGroupModal.vue.d.ts +1 -1
  32. package/dist/components/BaseInput.vue.d.ts +1 -1
  33. package/dist/components/BaseSelect.vue.d.ts +1 -1
  34. package/dist/components/BaseTextarea.vue.d.ts +1 -1
  35. package/dist/components/BatchProgressList.vue.d.ts +17 -0
  36. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +4 -4
  37. package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +2 -2
  38. package/dist/components/ConcentrationInput.vue.d.ts +1 -1
  39. package/dist/components/DataFrame.vue.d.ts +14 -2
  40. package/dist/components/DatePicker.vue.d.ts +2 -2
  41. package/dist/components/DateTimePicker.vue.d.ts +3 -1
  42. package/dist/components/DropdownButton.vue.d.ts +2 -0
  43. package/dist/components/ExperimentDataViewer.vue.d.ts +26 -1
  44. package/dist/components/ExperimentPopover.vue.d.ts +1 -0
  45. package/dist/components/ExperimentTimeline.vue.d.ts +29 -1
  46. package/dist/components/FileBrowserModal.vue.d.ts +99 -0
  47. package/dist/components/FilePicker.vue.d.ts +32 -0
  48. package/dist/components/FileUploader.vue.d.ts +5 -2
  49. package/dist/components/FitPanel.vue.d.ts +1 -1
  50. package/dist/components/FormulaInput.vue.d.ts +1 -1
  51. package/dist/components/GeneratedPlotlyResult.vue.d.ts +1 -3
  52. package/dist/components/JobsStatusTray.vue.d.ts +9 -2
  53. package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
  54. package/dist/components/MobileSupportGate.vue.d.ts +1 -1
  55. package/dist/components/MoleculeInput.vue.d.ts +1 -1
  56. package/dist/components/NumberInput.vue.d.ts +1 -1
  57. package/dist/components/PlotlyChart.vue.d.ts +59 -0
  58. package/dist/components/PluginWorkspaceView.props.d.ts +29 -1
  59. package/dist/components/PluginWorkspaceView.vue.d.ts +5 -5
  60. package/dist/components/ProgressBar.vue.d.ts +1 -1
  61. package/dist/components/ProtocolStepEditor.vue.d.ts +1 -0
  62. package/dist/components/ReagentList.vue.d.ts +29 -1
  63. package/dist/components/ResourceCard.vue.d.ts +1 -1
  64. package/dist/components/SampleHierarchyTree.vue.d.ts +29 -1
  65. package/dist/components/SampleLegend.vue.d.ts +1 -1
  66. package/dist/components/SampleSelector.drag.d.ts +13 -0
  67. package/dist/components/SampleSelector.tree.d.ts +2 -0
  68. package/dist/components/SampleSelector.vue.d.ts +35 -2
  69. package/dist/components/ScheduleCalendar.vue.d.ts +20 -0
  70. package/dist/components/SecretInput.vue.d.ts +28 -0
  71. package/dist/components/SequenceInput.vue.d.ts +1 -1
  72. package/dist/components/SettingsModal.vue.d.ts +1 -1
  73. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +2 -1
  74. package/dist/components/StatusIndicator.vue.d.ts +1 -1
  75. package/dist/components/TagsInput.vue.d.ts +1 -1
  76. package/dist/components/TimePicker.vue.d.ts +2 -1
  77. package/dist/components/TimeRangeInput.vue.d.ts +1 -1
  78. package/dist/components/UnitInput.vue.d.ts +1 -1
  79. package/dist/components/WellPlate.geometry.d.ts +15 -0
  80. package/dist/components/WellPlate.interaction.d.ts +13 -0
  81. package/dist/components/WellPlate.vue.d.ts +30 -1
  82. package/dist/components/fileBrowserPresentation.d.ts +10 -0
  83. package/dist/components/index.d.ts +13 -0
  84. package/dist/components/index.js +8 -8
  85. package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -0
  86. package/dist/components/internal/DataStateInternal.vue.d.ts +43 -0
  87. package/dist/components/internal/FileBrowserDialogInternal.vue.d.ts +34 -0
  88. package/dist/components/internal/FileBrowserListingInternal.vue.d.ts +25 -0
  89. package/dist/components/internal/FileBrowserToolbarInternal.vue.d.ts +26 -0
  90. package/dist/components/internal/FilePickerPreviewInternal.vue.d.ts +18 -0
  91. package/dist/components/internal/FilePickerTreeInternal.vue.d.ts +31 -0
  92. package/dist/components/internal/WellEditPopupInternal.vue.d.ts +3 -1
  93. package/dist/components/internal/WorkspaceControlsInternal.vue.d.ts +23 -0
  94. package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +70 -0
  95. package/dist/components/internal/WorkspaceSidebarInternal.vue.d.ts +43 -0
  96. package/dist/{components-DkHddRMl.js → components-DIum5hkx.js} +5882 -3200
  97. package/dist/components-DIum5hkx.js.map +1 -0
  98. package/dist/composables/controlSchemaTypes.d.ts +34 -0
  99. package/dist/composables/filePicker/localFiles.d.ts +3 -0
  100. package/dist/composables/filePicker/usePickerNavigation.d.ts +96 -0
  101. package/dist/composables/filePicker/usePickerSelection.d.ts +31 -0
  102. package/dist/composables/filePicker/validation.d.ts +5 -0
  103. package/dist/composables/flattenWorkspaceBindings.d.ts +61 -0
  104. package/dist/composables/index.d.ts +11 -2
  105. package/dist/composables/index.js +10 -10
  106. package/dist/composables/pluginWorkspaceModel.d.ts +164 -0
  107. package/dist/composables/useApi.d.ts +14 -7
  108. package/dist/composables/useAsync.d.ts +5 -1
  109. package/dist/composables/useBioTemplateWorkspace.d.ts +4 -20
  110. package/dist/composables/useCommandHistory.d.ts +5 -1
  111. package/dist/composables/useDropdownState.d.ts +18 -2
  112. package/dist/composables/useEventStream.d.ts +9 -0
  113. package/dist/composables/useFileBrowser.d.ts +55 -0
  114. package/dist/composables/useFilePicker.d.ts +189 -0
  115. package/dist/composables/useFocusTrap.d.ts +21 -0
  116. package/dist/composables/useGeneratedAnalysis.d.ts +3 -1
  117. package/dist/composables/useJobsStatusTray.d.ts +25 -1
  118. package/dist/composables/useListReorder.d.ts +90 -0
  119. package/dist/composables/useMenuKeyboard.d.ts +29 -0
  120. package/dist/composables/useOptimisticMutation.d.ts +5 -1
  121. package/dist/composables/usePlatformFilePickerAdapter.d.ts +11 -0
  122. package/dist/composables/usePluginClient.d.ts +2 -0
  123. package/dist/composables/usePluginConfig.d.ts +27 -0
  124. package/dist/composables/usePluginWorkspace.d.ts +51 -0
  125. package/dist/composables/useRequestSyncState.d.ts +42 -2
  126. package/dist/composables/useResourceCrud.d.ts +5 -1
  127. package/dist/composables/useRovingFocus.d.ts +24 -0
  128. package/dist/composables/useScheduleDrag.d.ts +1 -0
  129. package/dist/composables/useWellPainting.d.ts +5 -1
  130. package/dist/composables/useWellPlateAdapter.d.ts +5 -1
  131. package/dist/composables/useWellPlateValidation.d.ts +5 -1
  132. package/dist/composables/workspaceRecipes.d.ts +188 -0
  133. package/dist/{composables-C_i90sGS.js → composables-mFXsTA4g.js} +502 -86
  134. package/dist/composables-mFXsTA4g.js.map +1 -0
  135. package/dist/{useApi-J6zFkHmn.js → errors-BLuqMee5.js} +179 -16
  136. package/dist/errors-BLuqMee5.js.map +1 -0
  137. package/dist/{experiment-Cq145oEW.js → experiment-CVDRAnqp.js} +3 -8
  138. package/dist/experiment-CVDRAnqp.js.map +1 -0
  139. package/dist/{experiment-utils-CLnzPPq5.js → experiment-utils-CV2Wza3z.js} +70 -51
  140. package/dist/experiment-utils-CV2Wza3z.js.map +1 -0
  141. package/dist/index.d.ts +2 -0
  142. package/dist/index.js +15 -15
  143. package/dist/install.js +2 -7
  144. package/dist/install.js.map +1 -1
  145. package/dist/permissions.d.ts +42 -1
  146. package/dist/permissions.js +20 -10
  147. package/dist/permissions.js.map +1 -1
  148. package/dist/stores/auth.d.ts +6 -0
  149. package/dist/stores/index.d.ts +1 -1
  150. package/dist/stores/index.js +3 -3
  151. package/dist/stores/settings.d.ts +31 -1
  152. package/dist/styles.css +15135 -32397
  153. package/dist/templates/builderReadUtils.d.ts +1 -1
  154. package/dist/templates/index.js +2 -4
  155. package/dist/{templates-DsP51i-S.js → templates-CmGfmBRA.js} +303 -106
  156. package/dist/templates-CmGfmBRA.js.map +1 -0
  157. package/dist/types/auth.d.ts +1 -0
  158. package/dist/types/fileBrowserTypes.d.ts +77 -0
  159. package/dist/types/filePicker.d.ts +77 -0
  160. package/dist/types/form-builder.d.ts +1 -1
  161. package/dist/types/index.d.ts +2 -0
  162. package/dist/{useControlSchema-BDx2Olha.js → useControlSchema-DldpxNOP.js} +499 -1162
  163. package/dist/useControlSchema-DldpxNOP.js.map +1 -0
  164. package/dist/{useDropdownState-DSb3BC3N.js → useDropdownState-C7hRiVQf.js} +22 -6
  165. package/dist/useDropdownState-C7hRiVQf.js.map +1 -0
  166. package/dist/{useExperimentSelector-CV4iNfMS.js → useExperimentSelector-CEcIaueJ.js} +4 -4
  167. package/dist/{useExperimentSelector-CV4iNfMS.js.map → useExperimentSelector-CEcIaueJ.js.map} +1 -1
  168. package/dist/{useFormBuilder-BLxG3BOX.js → useFormBuilder-z5L_dUIy.js} +2 -2
  169. package/dist/{useFormBuilder-BLxG3BOX.js.map → useFormBuilder-z5L_dUIy.js.map} +1 -1
  170. package/dist/utils/color.d.ts +13 -0
  171. package/dist/utils/errors.d.ts +9 -0
  172. package/dist/utils/pluginSecrets.d.ts +53 -0
  173. package/dist/utils/records.d.ts +4 -0
  174. package/dist/{useProtocolTemplates-CS_SQl6U.js → validation-uwoJGEb6.js} +811 -212
  175. package/dist/validation-uwoJGEb6.js.map +1 -0
  176. package/package.json +1 -1
  177. package/src/__tests__/apiErrors.test.ts +81 -0
  178. package/src/__tests__/components/ActionMenu.test.ts +94 -0
  179. package/src/__tests__/components/AppAvatarMenu.test.ts +123 -0
  180. package/src/__tests__/components/BaseTabs.test.ts +67 -0
  181. package/src/__tests__/components/DataFrame.test.ts +183 -11
  182. package/src/__tests__/components/DataStates.test.ts +176 -0
  183. package/src/__tests__/components/DatePicker.test.ts +76 -0
  184. package/src/__tests__/components/DateTimePicker.test.ts +36 -0
  185. package/src/__tests__/components/DropdownButton.test.ts +134 -0
  186. package/src/__tests__/components/ExperimentPopover.test.ts +30 -0
  187. package/src/__tests__/components/ExperimentTimeline.test.ts +63 -0
  188. package/src/__tests__/components/FileBrowserModal.test.ts +460 -0
  189. package/src/__tests__/components/FilePicker.state.test.ts +287 -0
  190. package/src/__tests__/components/FilePicker.test.ts +487 -0
  191. package/src/__tests__/components/GeneratedPlotlyResult.test.ts +52 -5
  192. package/src/__tests__/components/GroupAssigner.test.ts +53 -0
  193. package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
  194. package/src/__tests__/components/PlotlyChart.test.ts +305 -0
  195. package/src/__tests__/components/PluginWorkspaceView.internal.test.ts +230 -0
  196. package/src/__tests__/components/RackEditor.test.ts +35 -0
  197. package/src/__tests__/components/ReagentList.test.ts +64 -2
  198. package/src/__tests__/components/RetiredStyles.test.ts +31 -0
  199. package/src/__tests__/components/SampleSelector.drag.test.ts +51 -1
  200. package/src/__tests__/components/ScheduleCalendar.test.ts +63 -0
  201. package/src/__tests__/components/SecretInput.test.ts +87 -0
  202. package/src/__tests__/components/SegmentedControl.test.ts +107 -0
  203. package/src/__tests__/components/TimePicker.test.ts +61 -0
  204. package/src/__tests__/components/WellEditPopupInternal.test.ts +108 -0
  205. package/src/__tests__/components/WellPlate.interaction.test.ts +59 -0
  206. package/src/__tests__/components/iconButtonIconSizing.test.ts +18 -0
  207. package/src/__tests__/composables/useApi.test.ts +92 -9
  208. package/src/__tests__/composables/useAuth.test.ts +2 -0
  209. package/src/__tests__/composables/useDropdownState.test.ts +58 -1
  210. package/src/__tests__/composables/useFileBrowser.test.ts +305 -0
  211. package/src/__tests__/composables/useGeneratedAnalysis.test.ts +7 -2
  212. package/src/__tests__/composables/useListReorder.test.ts +145 -0
  213. package/src/__tests__/composables/usePlatformFilePickerAdapter.test.ts +67 -0
  214. package/src/__tests__/composables/usePluginClient.test.ts +143 -0
  215. package/src/__tests__/composables/usePluginConfig.test.ts +497 -0
  216. package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
  217. package/src/__tests__/docs/frontendDocsCatalog.test.ts +39 -7
  218. package/src/__tests__/stores/settings.test.ts +71 -1
  219. package/src/__tests__/styles/cssTokens.test.ts +131 -0
  220. package/src/__tests__/utils/permissions.test.ts +68 -0
  221. package/src/apiErrors.ts +85 -0
  222. package/src/components/ActionMenu.vue +45 -88
  223. package/src/components/AlertBox.vue +0 -4
  224. package/src/components/AppAvatarMenu.vue +26 -7
  225. package/src/components/AppLayout.vue +0 -4
  226. package/src/components/AppPluginSwitcher.story.vue +87 -0
  227. package/src/components/AppPluginSwitcher.vue +2 -5
  228. package/src/components/AppSidebar.vue +0 -4
  229. package/src/components/AppToastContainer.vue +6 -8
  230. package/src/components/AppTopBar.vue +0 -4
  231. package/src/components/ArtifactSaveDialog.vue +0 -4
  232. package/src/components/ArtifactSelectorModal.vue +0 -4
  233. package/src/components/AuditTrail.story.vue +18 -0
  234. package/src/components/AuditTrail.vue +27 -7
  235. package/src/components/AutoGroupModal.vue +0 -4
  236. package/src/components/Avatar.vue +0 -4
  237. package/src/components/BaseButton.vue +0 -4
  238. package/src/components/BaseCheckbox.vue +0 -4
  239. package/src/components/BaseInput.vue +0 -4
  240. package/src/components/BaseModal.vue +8 -60
  241. package/src/components/BasePill.vue +0 -4
  242. package/src/components/BaseRadioGroup.vue +0 -4
  243. package/src/components/BaseSelect.vue +0 -4
  244. package/src/components/BaseSlider.vue +0 -4
  245. package/src/components/BaseTabs.vue +26 -5
  246. package/src/components/BaseTextarea.vue +0 -4
  247. package/src/components/BaseToggle.vue +0 -4
  248. package/src/components/BatchProgressList.story.vue +18 -0
  249. package/src/components/BatchProgressList.vue +32 -4
  250. package/src/components/BioTemplateExperimentWorkspaceView.vue +10 -21
  251. package/src/components/BioTemplatePackWorkspaceView.vue +11 -15
  252. package/src/components/BioTemplatePresetWorkspaceView.vue +8 -13
  253. package/src/components/Breadcrumb.vue +0 -4
  254. package/src/components/Calendar.vue +0 -4
  255. package/src/components/ChartContainer.story.vue +1 -1
  256. package/src/components/ChartContainer.vue +0 -4
  257. package/src/components/ChemicalFormula.vue +0 -4
  258. package/src/components/CollapsibleCard.vue +0 -4
  259. package/src/components/ColorSlider.vue +0 -4
  260. package/src/components/ComponentBindingRenderer.vue +1 -3
  261. package/src/components/ConcentrationInput.vue +0 -4
  262. package/src/components/ConfirmDialog.vue +0 -4
  263. package/src/components/ControlWorkspaceView.vue +11 -22
  264. package/src/components/DataFrame.story.vue +14 -0
  265. package/src/components/DataFrame.vue +97 -23
  266. package/src/components/DatePicker.vue +73 -27
  267. package/src/components/DateTimePicker.vue +45 -17
  268. package/src/components/Divider.vue +0 -4
  269. package/src/components/DoseCalculator.vue +0 -4
  270. package/src/components/DoseDesignWorkspaceView.vue +6 -25
  271. package/src/components/DropdownButton.vue +24 -6
  272. package/src/components/EmptyState.vue +0 -4
  273. package/src/components/ExperimentCodeBadge.vue +0 -4
  274. package/src/components/ExperimentDataViewer.story.vue +3 -0
  275. package/src/components/ExperimentDataViewer.vue +33 -13
  276. package/src/components/ExperimentPopover.vue +12 -7
  277. package/src/components/ExperimentSelectorModal.vue +0 -4
  278. package/src/components/ExperimentTimeline.story.vue +18 -0
  279. package/src/components/ExperimentTimeline.vue +81 -75
  280. package/src/components/FileBrowserModal.story.vue +203 -0
  281. package/src/components/FileBrowserModal.vue +384 -0
  282. package/src/components/FilePicker.story.vue +44 -0
  283. package/src/components/FilePicker.vue +284 -0
  284. package/src/components/FileUploader.vue +32 -18
  285. package/src/components/FitPanel.vue +0 -4
  286. package/src/components/FormActions.story.vue +96 -0
  287. package/src/components/FormActions.vue +0 -4
  288. package/src/components/FormBuilder.vue +0 -4
  289. package/src/components/FormField.vue +0 -4
  290. package/src/components/FormulaInput.vue +0 -4
  291. package/src/components/GeneratedPathInput.story.vue +68 -0
  292. package/src/components/GeneratedPlotlyResult.story.vue +96 -0
  293. package/src/components/GeneratedPlotlyResult.vue +34 -69
  294. package/src/components/GeneratedPluginView.story.vue +145 -0
  295. package/src/components/GeneratedPluginView.vue +10 -10
  296. package/src/components/GeneratedResultRenderer.story.vue +117 -0
  297. package/src/components/GeneratedResultRenderer.vue +4 -9
  298. package/src/components/GroupAssigner.vue +67 -5
  299. package/src/components/IconButton.vue +0 -4
  300. package/src/components/InstrumentAlertLog.vue +0 -4
  301. package/src/components/InstrumentStateBadge.vue +0 -4
  302. package/src/components/InstrumentStatusCard.vue +0 -4
  303. package/src/components/JobsStatusTray.vue +16 -5
  304. package/src/components/LcmsSequenceTable.vue +81 -50
  305. package/src/components/LoadingSpinner.vue +0 -4
  306. package/src/components/MobileSupportGate.vue +0 -4
  307. package/src/components/MoleculeInput.vue +0 -4
  308. package/src/components/MultiSelect.vue +0 -4
  309. package/src/components/NumberInput.vue +0 -4
  310. package/src/components/PlateMapEditor.vue +3 -14
  311. package/src/components/PlotlyChart.story.vue +61 -0
  312. package/src/components/PlotlyChart.vue +233 -0
  313. package/src/components/PluginIcon.vue +0 -4
  314. package/src/components/PluginWorkspaceView.props.ts +38 -0
  315. package/src/components/PluginWorkspaceView.vue +53 -224
  316. package/src/components/ProgressBar.vue +0 -4
  317. package/src/components/ProtocolStepEditor.vue +2 -4
  318. package/src/components/RackEditor.vue +51 -70
  319. package/src/components/ReagentEditor.vue +0 -4
  320. package/src/components/ReagentList.story.vue +18 -0
  321. package/src/components/ReagentList.vue +127 -82
  322. package/src/components/ResourceCard.vue +0 -4
  323. package/src/components/RuntimeUpdateNotice.story.vue +49 -0
  324. package/src/components/RuntimeUpdateNotice.vue +4 -4
  325. package/src/components/SampleHierarchyTree.story.vue +18 -0
  326. package/src/components/SampleHierarchyTree.vue +32 -9
  327. package/src/components/SampleLegend.vue +2 -8
  328. package/src/components/SampleSelector.drag.ts +51 -0
  329. package/src/components/SampleSelector.story.vue +6 -0
  330. package/src/components/SampleSelector.tree.ts +2 -0
  331. package/src/components/SampleSelector.vue +49 -10
  332. package/src/components/SampleSelectorGroupNode.vue +19 -0
  333. package/src/components/ScheduleCalendar.story.vue +6 -0
  334. package/src/components/ScheduleCalendar.vue +82 -7
  335. package/src/components/ScientificNumber.vue +0 -4
  336. package/src/components/SecretInput.story.vue +79 -0
  337. package/src/components/SecretInput.vue +150 -0
  338. package/src/components/SectionCard.vue +0 -4
  339. package/src/components/SegmentedControl.vue +50 -7
  340. package/src/components/SequenceInput.vue +0 -4
  341. package/src/components/SequenceProgressBar.story.vue +110 -0
  342. package/src/components/SequenceProgressBar.vue +0 -4
  343. package/src/components/SettingsModal.vue +0 -4
  344. package/src/components/Skeleton.vue +0 -4
  345. package/src/components/SmartGroupFieldRecipe.vue +8 -6
  346. package/src/components/SmartGroupManual.vue +0 -4
  347. package/src/components/StatusIndicator.vue +0 -4
  348. package/src/components/StepWizard.vue +0 -4
  349. package/src/components/TagsInput.vue +4 -6
  350. package/src/components/ThemeToggle.vue +0 -4
  351. package/src/components/TimePicker.vue +36 -7
  352. package/src/components/TimeRangeInput.vue +0 -4
  353. package/src/components/Tooltip.story.vue +3 -3
  354. package/src/components/Tooltip.vue +0 -4
  355. package/src/components/UnitInput.vue +0 -4
  356. package/src/components/WellPlate.geometry.ts +60 -1
  357. package/src/components/WellPlate.interaction.ts +44 -0
  358. package/src/components/WellPlate.story.vue +8 -0
  359. package/src/components/WellPlate.vue +53 -7
  360. package/src/components/fileBrowserPresentation.ts +39 -0
  361. package/src/components/index.ts +14 -0
  362. package/src/components/internal/AppTopBarPageSelectorInternal.vue +2 -5
  363. package/src/components/internal/AppTopBarPillNavInternal.vue +0 -4
  364. package/src/components/internal/DataStateInternal.vue +74 -0
  365. package/src/components/internal/FileBrowserDialogInternal.vue +75 -0
  366. package/src/components/internal/FileBrowserListingInternal.vue +197 -0
  367. package/src/components/internal/FileBrowserToolbarInternal.vue +136 -0
  368. package/src/components/internal/FilePickerPreviewInternal.vue +100 -0
  369. package/src/components/internal/FilePickerTreeInternal.vue +238 -0
  370. package/src/components/internal/FormSectionRenderer.vue +0 -4
  371. package/src/components/internal/WellEditPopupInternal.vue +20 -5
  372. package/src/components/internal/WorkspaceControlsInternal.vue +20 -0
  373. package/src/components/internal/WorkspaceShellInternal.vue +125 -0
  374. package/src/components/internal/WorkspaceSidebarInternal.vue +82 -0
  375. package/src/composables/controlSchemaTypes.ts +34 -0
  376. package/src/composables/experimentDesignData.ts +1 -3
  377. package/src/composables/filePicker/localFiles.ts +58 -0
  378. package/src/composables/filePicker/usePickerNavigation.ts +220 -0
  379. package/src/composables/filePicker/usePickerSelection.ts +259 -0
  380. package/src/composables/filePicker/validation.ts +41 -0
  381. package/src/composables/flattenWorkspaceBindings.ts +104 -0
  382. package/src/composables/formBuilderRegistry.ts +5 -0
  383. package/src/composables/index.ts +50 -0
  384. package/src/composables/pluginWorkspaceModel.ts +182 -0
  385. package/src/composables/useApi.ts +57 -13
  386. package/src/composables/useAsync.ts +5 -1
  387. package/src/composables/useAuth.ts +3 -0
  388. package/src/composables/useBioTemplatePackWorkspace.ts +15 -9
  389. package/src/composables/useBioTemplatePresetWorkspace.ts +14 -15
  390. package/src/composables/useBioTemplateWorkspace.ts +18 -43
  391. package/src/composables/useCommandHistory.ts +5 -1
  392. package/src/composables/useDropdownState.ts +35 -5
  393. package/src/composables/useEventStream.ts +14 -2
  394. package/src/composables/useFileBrowser.ts +314 -0
  395. package/src/composables/useFileImport.ts +2 -7
  396. package/src/composables/useFilePicker.ts +366 -0
  397. package/src/composables/useFocusTrap.ts +91 -0
  398. package/src/composables/useGeneratedAnalysis.ts +32 -27
  399. package/src/composables/useJobsStatusTray.ts +184 -17
  400. package/src/composables/useListReorder.story.vue +143 -0
  401. package/src/composables/useListReorder.ts +242 -0
  402. package/src/composables/useMenuKeyboard.ts +90 -0
  403. package/src/composables/useOptimisticMutation.ts +6 -16
  404. package/src/composables/usePlatformFilePickerAdapter.ts +104 -0
  405. package/src/composables/usePluginClient.ts +50 -4
  406. package/src/composables/usePluginConfig.ts +252 -0
  407. package/src/composables/usePluginWorkspace.ts +208 -0
  408. package/src/composables/useRackEditor.ts +2 -11
  409. package/src/composables/useRequestSyncState.ts +98 -28
  410. package/src/composables/useResourceCrud.ts +6 -16
  411. package/src/composables/useRovingFocus.ts +66 -0
  412. package/src/composables/useScheduleDrag.ts +37 -0
  413. package/src/composables/useWellPainting.ts +10 -30
  414. package/src/composables/useWellPlateAdapter.ts +5 -1
  415. package/src/composables/useWellPlateEditor.ts +1 -11
  416. package/src/composables/useWellPlateValidation.ts +5 -1
  417. package/src/composables/workspaceRecipes.ts +267 -0
  418. package/src/index.ts +19 -0
  419. package/src/permissions.ts +48 -9
  420. package/src/stores/auth.ts +1 -0
  421. package/src/stores/experiment.ts +2 -7
  422. package/src/stores/index.ts +9 -1
  423. package/src/stores/settings.ts +93 -1
  424. package/src/styles/components/audit-trail.css +5 -5
  425. package/src/styles/components/batch-progress-list.css +7 -0
  426. package/src/styles/components/color-slider.css +2 -2
  427. package/src/styles/components/data-state.css +30 -0
  428. package/src/styles/components/dataframe.css +29 -35
  429. package/src/styles/components/experiment-data-viewer.css +4 -4
  430. package/src/styles/components/experiment-timeline.css +3 -30
  431. package/src/styles/components/file-browser-modal.css +489 -0
  432. package/src/styles/components/file-picker.css +502 -0
  433. package/src/styles/components/form-builder.css +5 -5
  434. package/src/styles/components/icon-button.css +9 -0
  435. package/src/styles/components/lcms-sequence-table.css +16 -1
  436. package/src/styles/components/multi-select.css +1 -1
  437. package/src/styles/components/reagent-list.css +38 -31
  438. package/src/styles/components/sample-hierarchy-tree.css +5 -19
  439. package/src/styles/components/sample-selector.css +9 -2
  440. package/src/styles/components/schedule-calendar.css +8 -0
  441. package/src/styles/components/scientific-number.css +1 -1
  442. package/src/styles/components/secret-input.css +60 -0
  443. package/src/styles/components/well-plate.css +8 -0
  444. package/src/styles/index.css +12 -0
  445. package/src/styles/variables.css +29 -0
  446. package/src/templates/builderPresetControls.ts +1 -1
  447. package/src/templates/builderReadUtils.ts +1 -3
  448. package/src/templates/componentPlateHelpers.ts +3 -1
  449. package/src/templates/componentTargetResolvers.ts +1 -3
  450. package/src/templates/controlSchemaTargets.ts +1 -3
  451. package/src/templates/doseResponseAdapters.ts +2 -13
  452. package/src/templates/elisaAssayCollectionBuilder.ts +2 -2
  453. package/src/templates/plateMapBuilder.ts +2 -2
  454. package/src/templates/qpcrPlateBuilder.ts +1 -1
  455. package/src/templates/templateValidators.ts +1 -1
  456. package/src/templates/timeCourseBuilder.ts +2 -2
  457. package/src/templates/wellPlateScreenCollectionBuilder.ts +2 -2
  458. package/src/types/auth.ts +1 -0
  459. package/src/types/fileBrowserTypes.ts +85 -0
  460. package/src/types/filePicker.ts +72 -0
  461. package/src/types/form-builder.ts +1 -0
  462. package/src/types/index.ts +14 -0
  463. package/src/utils/color.ts +51 -0
  464. package/src/utils/errors.ts +29 -0
  465. package/src/utils/formModelSync.ts +1 -3
  466. package/src/utils/pluginIcon.ts +1 -3
  467. package/src/utils/pluginSecrets.ts +102 -0
  468. package/src/utils/records.ts +9 -0
  469. package/dist/EmptyState-p90quq8Z.js.map +0 -1
  470. package/dist/ExperimentPopover-tLwJ7XF4.js.map +0 -1
  471. package/dist/ExperimentSelectorModal-DyPAUCLw.js.map +0 -1
  472. package/dist/SettingsModal-BgKY93zh.js.map +0 -1
  473. package/dist/components-DkHddRMl.js.map +0 -1
  474. package/dist/composables/autoGroupConstants.d.ts +0 -1
  475. package/dist/composables/autoGroupGrouping.d.ts +0 -3
  476. package/dist/composables/useAutoGroupInputSources.d.ts +0 -32
  477. package/dist/composables-C_i90sGS.js.map +0 -1
  478. package/dist/experiment-Cq145oEW.js.map +0 -1
  479. package/dist/experiment-utils-CLnzPPq5.js.map +0 -1
  480. package/dist/templates/builderDefaults.d.ts +0 -1
  481. package/dist/templates/plateGeometry.d.ts +0 -4
  482. package/dist/templates-DsP51i-S.js.map +0 -1
  483. package/dist/useApi-J6zFkHmn.js.map +0 -1
  484. package/dist/useControlSchema-BDx2Olha.js.map +0 -1
  485. package/dist/useDropdownState-DSb3BC3N.js.map +0 -1
  486. package/dist/useProtocolTemplates-CS_SQl6U.js.map +0 -1
  487. package/src/__tests__/composables/useAutoGroupInputSources.test.ts +0 -127
  488. package/src/composables/autoGroupConstants.ts +0 -4
  489. package/src/composables/autoGroupGrouping.ts +0 -148
  490. package/src/composables/useAutoGroupInputSources.ts +0 -147
  491. package/src/templates/builderDefaults.ts +0 -11
  492. package/src/templates/plateGeometry.ts +0 -62
  493. /package/dist/__tests__/{composables/useAutoGroupInputSources.test.d.ts → apiErrors.test.d.ts} +0 -0
@@ -1,127 +0,0 @@
1
- import { computed, ref } from 'vue'
2
- import { describe, expect, it } from 'vitest'
3
- import { useAutoGroup } from '../../composables/useAutoGroup'
4
- import { useAutoGroupInputSources } from '../../composables/useAutoGroupInputSources'
5
- import type { WizardStep } from '../../types/components'
6
-
7
- function makeSources(options: {
8
- samples?: string[]
9
- experimentId?: number
10
- designData?: Record<string, unknown>
11
- apiGet?: (url: string) => Promise<Record<string, unknown>>
12
- } = {}) {
13
- const autoGroup = useAutoGroup()
14
- const currentStep = ref(0)
15
- const dynamicSteps = ref<WizardStep[]>([
16
- { id: 'input', label: 'Input' },
17
- { id: 'fields', label: 'Fields' },
18
- { id: 'preview', label: 'Preview' },
19
- ])
20
- const sources = useAutoGroupInputSources({
21
- autoGroup,
22
- samples: computed(() => options.samples ?? []),
23
- experimentId: computed(() => options.experimentId),
24
- designData: computed(() => options.designData),
25
- currentStep,
26
- dynamicSteps,
27
- api: {
28
- get: async <T>(url: string): Promise<T> => {
29
- const value = options.apiGet
30
- ? await options.apiGet(url)
31
- : { data: undefined }
32
- return value as T
33
- },
34
- },
35
- })
36
-
37
- return { autoGroup, currentStep, dynamicSteps, sources }
38
- }
39
-
40
- describe('useAutoGroupInputSources', () => {
41
- it('initializes pasted sample input when samples are provided', async () => {
42
- const { autoGroup, currentStep, sources } = makeSources({
43
- samples: ['S1_Control', 'S2_Treated'],
44
- })
45
- currentStep.value = 2
46
-
47
- await sources.initializeInputSources()
48
-
49
- expect(currentStep.value).toBe(0)
50
- expect(autoGroup.rawText.value).toBe('S1_Control\nS2_Treated')
51
- expect(sources.csvFileName.value).toBe('')
52
- expect(sources.experimentError.value).toBeNull()
53
- })
54
-
55
- it('loads experiment design data and advances to the fields step', async () => {
56
- const { autoGroup, currentStep, sources } = makeSources({
57
- designData: {
58
- samples: [
59
- { sample_name: 'S1', sample_type: 'sample', conditions: { Treatment: 'Control' } },
60
- { sample_name: 'S2', sample_type: 'sample', conditions: { Treatment: 'Drug' } },
61
- ],
62
- },
63
- })
64
-
65
- await sources.initializeInputSources()
66
-
67
- expect(autoGroup.inputMode.value).toBe('experiment')
68
- expect(autoGroup.csvData.value?.rows).toHaveLength(2)
69
- expect(sources.experimentFieldNames.value).toEqual(['Treatment', 'sample_type'])
70
- expect(currentStep.value).toBe(1)
71
- expect(sources.experimentLoading.value).toBe(false)
72
- })
73
-
74
- it('filters loaded experiment metadata to the provided sample subset', async () => {
75
- const { autoGroup, sources } = makeSources({
76
- samples: ['S2', 'MissingFromDesign'],
77
- designData: {
78
- samples: [
79
- { sample_name: 'S1', sample_type: 'sample', conditions: { Tissue: 'Kidney', Treatment: 'Control' } },
80
- { sample_name: 'S2', sample_type: 'sample', conditions: { Tissue: 'Liver', Treatment: 'Drug' } },
81
- ],
82
- },
83
- })
84
-
85
- await sources.initializeInputSources()
86
-
87
- expect(autoGroup.samples.value).toEqual(['S2', 'MissingFromDesign'])
88
- expect(autoGroup.groups.value.map(g => g.name).sort()).toEqual([
89
- 'Liver / Drug',
90
- 'Outlier',
91
- ])
92
- })
93
-
94
- it('parses uploaded CSV files and can clear them back to paste mode', async () => {
95
- const { autoGroup, sources } = makeSources()
96
- const file = {
97
- name: 'samples.csv',
98
- text: async () => 'sample_name,Treatment\nS1,Control\nS2,Drug',
99
- } as File
100
-
101
- await sources.processFile(file)
102
-
103
- expect(autoGroup.inputMode.value).toBe('csv')
104
- expect(autoGroup.csvData.value?.rows).toHaveLength(2)
105
- expect(sources.csvFileName.value).toBe('samples.csv')
106
-
107
- sources.clearCsvFile()
108
-
109
- expect(autoGroup.inputMode.value).toBe('paste')
110
- expect(autoGroup.csvData.value).toBeNull()
111
- expect(sources.csvFileName.value).toBe('')
112
- })
113
-
114
- it('surfaces API errors when experiment metadata cannot be fetched', async () => {
115
- const { sources } = makeSources({
116
- experimentId: 42,
117
- apiGet: async () => {
118
- throw new Error('offline')
119
- },
120
- })
121
-
122
- await sources.initializeInputSources()
123
-
124
- expect(sources.experimentLoading.value).toBe(false)
125
- expect(sources.experimentError.value).toBe('offline')
126
- })
127
- })
@@ -1,4 +0,0 @@
1
- export const DEFAULT_COLORS = [
2
- '#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6',
3
- '#EC4899', '#06B6D4', '#84CC16', '#F97316', '#6366F1',
4
- ]
@@ -1,148 +0,0 @@
1
- import type {
2
- AutoGroupResult,
3
- ColumnInfo,
4
- MetadataRow,
5
- OutlierAction,
6
- ParsedCsvData,
7
- } from '../types/auto-group'
8
- import type { SampleGroup } from '../types/components'
9
- import { DEFAULT_COLORS } from './autoGroupConstants'
10
-
11
- export function computeGroups(
12
- allSamples: string[],
13
- columns: ColumnInfo[],
14
- enabledFields: Set<number>,
15
- outlierActions: Map<number, OutlierAction>,
16
- delimiter: string,
17
- minFieldCount: number,
18
- ): AutoGroupResult {
19
- const excludedSamples: string[] = []
20
- const qcSamples: string[] = []
21
- const conformingSamples: string[] = []
22
-
23
- for (let i = 0; i < allSamples.length; i++) {
24
- const action = outlierActions.get(i)
25
- if (action === 'exclude') {
26
- excludedSamples.push(allSamples[i])
27
- } else if (action === 'qc') {
28
- qcSamples.push(allSamples[i])
29
- } else {
30
- conformingSamples.push(allSamples[i])
31
- }
32
- }
33
-
34
- // Build group map
35
- const groupMap = new Map<string, string[]>()
36
- const metadata: MetadataRow[] = []
37
- const enabledIndices = [...enabledFields].sort((a, b) => a - b)
38
- const suffixCount = minFieldCount - 1
39
-
40
- for (const sample of conformingSamples) {
41
- const parts = sample.split(delimiter)
42
- const splitAt = Math.max(1, parts.length - suffixCount)
43
- const row = [
44
- parts.slice(0, splitAt).join(delimiter),
45
- ...parts.slice(splitAt),
46
- ]
47
-
48
- // Build group key from enabled columns
49
- const keyParts: string[] = []
50
- for (const idx of enabledIndices) {
51
- if (idx < row.length && idx < columns.length) {
52
- keyParts.push(row[idx])
53
- }
54
- }
55
- const groupKey = keyParts.join(' / ')
56
-
57
- const group = groupMap.get(groupKey)
58
- if (group) {
59
- group.push(sample)
60
- } else {
61
- groupMap.set(groupKey, [sample])
62
- }
63
-
64
- // Build metadata row with ALL columns
65
- const fields: Record<string, string> = {}
66
- for (const col of columns) {
67
- if (col.index < row.length) {
68
- fields[col.name] = row[col.index]
69
- }
70
- }
71
- metadata.push({ sampleName: sample, fields, group: groupKey })
72
- }
73
-
74
- // Convert to SampleGroup[]
75
- const groups: SampleGroup[] = []
76
- let colorIdx = 0
77
- for (const [name, samples] of groupMap) {
78
- groups.push({
79
- name,
80
- color: DEFAULT_COLORS[colorIdx % DEFAULT_COLORS.length],
81
- samples,
82
- })
83
- colorIdx++
84
- }
85
-
86
- // QC group
87
- if (qcSamples.length > 0) {
88
- groups.push({
89
- name: 'QC',
90
- color: '#6B7280',
91
- samples: qcSamples,
92
- })
93
- for (const sample of qcSamples) {
94
- metadata.push({ sampleName: sample, fields: {}, group: 'QC' })
95
- }
96
- }
97
-
98
- return { groups, metadata, excludedSamples }
99
- }
100
-
101
- export function computeGroupsFromCsv(
102
- csvData: ParsedCsvData,
103
- columns: ColumnInfo[],
104
- enabledFields: Set<number>,
105
- ): AutoGroupResult {
106
- const groupMap = new Map<string, string[]>()
107
- const metadata: MetadataRow[] = []
108
- const enabledCols = columns
109
- .filter(c => enabledFields.has(c.index))
110
- .sort((a, b) => a.index - b.index)
111
-
112
- for (const row of csvData.rows) {
113
- const sampleName = row[csvData.sampleColumn]
114
-
115
- // Build group key from enabled CSV column values
116
- // Use originalName for CSV row lookup (survives user renames), display name for group key
117
- const keyParts = enabledCols.map(col => row[col.originalName ?? col.name])
118
- const groupKey = keyParts.join(' / ')
119
-
120
- const group = groupMap.get(groupKey)
121
- if (group) {
122
- group.push(sampleName)
123
- } else {
124
- groupMap.set(groupKey, [sampleName])
125
- }
126
-
127
- // Build metadata row with ALL columns - use display name as key, original for lookup
128
- const fields: Record<string, string> = {}
129
- for (const col of columns) {
130
- fields[col.name] = row[col.originalName ?? col.name]
131
- }
132
- metadata.push({ sampleName, fields, group: groupKey })
133
- }
134
-
135
- // Convert to SampleGroup[]
136
- const groups: SampleGroup[] = []
137
- let colorIdx = 0
138
- for (const [name, samples] of groupMap) {
139
- groups.push({
140
- name,
141
- color: DEFAULT_COLORS[colorIdx % DEFAULT_COLORS.length],
142
- samples,
143
- })
144
- colorIdx++
145
- }
146
-
147
- return { groups, metadata, excludedSamples: [] }
148
- }
@@ -1,147 +0,0 @@
1
- import { computed, nextTick, ref, type Ref } from 'vue'
2
- import { parseCSV, type useAutoGroup } from './useAutoGroup'
3
- import { useApi, type UseApiReturn } from './useApi'
4
- import type { WizardStep } from '../types/components'
5
-
6
- type AutoGroupController = ReturnType<typeof useAutoGroup>
7
- type ReadableRef<T> = Readonly<Ref<T>>
8
- type AutoGroupApi = Pick<UseApiReturn, 'get'>
9
-
10
- export interface UseAutoGroupInputSourcesOptions {
11
- autoGroup: AutoGroupController
12
- samples: ReadableRef<readonly string[]>
13
- experimentId: ReadableRef<number | undefined>
14
- designData: ReadableRef<Record<string, unknown> | undefined>
15
- currentStep: Ref<number>
16
- dynamicSteps: ReadableRef<readonly WizardStep[]>
17
- api?: AutoGroupApi
18
- }
19
-
20
- /** Manages AutoGroupModal input sources: pasted samples, CSV/TSV files, and experiment metadata. */
21
- export function useAutoGroupInputSources(options: UseAutoGroupInputSourcesOptions) {
22
- const api = options.api ?? useApi()
23
- const isDragOver = ref(false)
24
- const csvFileName = ref('')
25
- const experimentLoading = ref(false)
26
- const experimentError = ref<string | null>(null)
27
- const csvError = ref<string | null>(null)
28
-
29
- const experimentFieldNames = computed(() =>
30
- options.autoGroup.csvData.value?.columns.filter(c => c !== 'sample_name') ?? [],
31
- )
32
-
33
- async function initializeInputSources() {
34
- options.autoGroup.reset()
35
- options.currentStep.value = 0
36
- resetInputSourceState()
37
-
38
- if (options.experimentId.value || options.designData.value) {
39
- await fetchExperimentData()
40
- } else if (options.samples.value.length > 0) {
41
- options.autoGroup.rawText.value = options.samples.value.join('\n')
42
- }
43
- }
44
-
45
- function resetInputSourceState() {
46
- csvFileName.value = ''
47
- experimentError.value = null
48
- csvError.value = null
49
- isDragOver.value = false
50
- }
51
-
52
- async function fetchExperimentData() {
53
- if (!options.experimentId.value && !options.designData.value) return
54
-
55
- options.autoGroup.inputMode.value = 'experiment'
56
- experimentLoading.value = true
57
- experimentError.value = null
58
-
59
- try {
60
- const pluginData = await loadExperimentPluginData()
61
-
62
- if (!pluginData || typeof pluginData !== 'object') {
63
- experimentError.value = 'No design data found for this experiment'
64
- return
65
- }
66
-
67
- const success = options.autoGroup.loadExperimentData(pluginData, { samples: options.samples.value })
68
- if (!success) {
69
- experimentError.value = 'No sample metadata found in this experiment'
70
- return
71
- }
72
-
73
- await nextTick()
74
- const fieldsIdx = options.dynamicSteps.value.findIndex(s => s.id === 'fields')
75
- if (fieldsIdx >= 0) {
76
- options.currentStep.value = fieldsIdx
77
- }
78
- } catch (e) {
79
- experimentError.value = e instanceof Error ? e.message : 'Failed to fetch experiment data'
80
- } finally {
81
- experimentLoading.value = false
82
- }
83
- }
84
-
85
- async function loadExperimentPluginData(): Promise<Record<string, unknown> | undefined> {
86
- if (options.designData.value) {
87
- return options.designData.value
88
- }
89
-
90
- const result = await api.get<Record<string, unknown>>(
91
- `/experiments/${options.experimentId.value}/data`,
92
- )
93
- return result.data as Record<string, unknown> | undefined
94
- }
95
-
96
- function handleFileDrop(event: DragEvent) {
97
- event.preventDefault()
98
- isDragOver.value = false
99
- const files = event.dataTransfer?.files
100
- if (files && files.length > 0) {
101
- void processFile(files[0])
102
- }
103
- }
104
-
105
- function handleFileInput(event: Event) {
106
- const target = event.target as HTMLInputElement
107
- if (target.files && target.files.length > 0) {
108
- void processFile(target.files[0])
109
- }
110
- }
111
-
112
- async function processFile(file: File) {
113
- if (!file.name.endsWith('.csv') && !file.name.endsWith('.tsv')) return
114
-
115
- csvError.value = null
116
- try {
117
- const text = await file.text()
118
- const parsed = parseCSV(text)
119
- options.autoGroup.inputMode.value = 'csv'
120
- options.autoGroup.csvData.value = parsed
121
- csvFileName.value = file.name
122
- } catch (e) {
123
- csvError.value = e instanceof Error ? e.message : 'Failed to parse file'
124
- }
125
- }
126
-
127
- function clearCsvFile() {
128
- options.autoGroup.csvData.value = null
129
- options.autoGroup.inputMode.value = 'paste'
130
- csvFileName.value = ''
131
- }
132
-
133
- return {
134
- isDragOver,
135
- csvFileName,
136
- experimentLoading,
137
- experimentError,
138
- csvError,
139
- experimentFieldNames,
140
- initializeInputSources,
141
- fetchExperimentData,
142
- handleFileDrop,
143
- handleFileInput,
144
- processFile,
145
- clearCsvFile,
146
- }
147
- }
@@ -1,11 +0,0 @@
1
- export const DEFAULT_SAMPLE_COLORS = [
2
- '#3B82F6',
3
- '#10B981',
4
- '#EF4444',
5
- '#F59E0B',
6
- '#8B5CF6',
7
- '#F97316',
8
- '#06B6D4',
9
- '#14B8A6',
10
- '#6B7280',
11
- ]
@@ -1,62 +0,0 @@
1
- import type { WellPlateFormat } from '../types'
2
-
3
- const PLATE_DIMENSIONS: Record<number, readonly [number, number]> = {
4
- 6: [2, 3],
5
- 12: [3, 4],
6
- 24: [4, 6],
7
- 48: [6, 8],
8
- 54: [6, 9],
9
- 96: [8, 12],
10
- 384: [16, 24],
11
- }
12
-
13
- export function wellIdsForFormat(format: number): string[] {
14
- const dimensions = PLATE_DIMENSIONS[format]
15
- if (!dimensions) {
16
- throw new Error(`Unsupported plate format '${format}'.`)
17
- }
18
- const [rows, cols] = dimensions
19
- return Array.from({ length: rows }, (_, row) =>
20
- Array.from({ length: cols }, (_col, col) => `${rowLabel(row)}${col + 1}`)
21
- ).flat()
22
- }
23
-
24
- export function assertWellInFormat(wellId: string, format: number): void {
25
- const dimensions = PLATE_DIMENSIONS[format]
26
- if (!dimensions) {
27
- throw new Error(`Unsupported plate format '${format}'.`)
28
- }
29
- const match = /^([A-Z]+)([1-9][0-9]*)$/.exec(wellId.toUpperCase())
30
- if (!match) {
31
- throw new Error(`Invalid well id '${wellId}'.`)
32
- }
33
- const row = rowIndex(match[1])
34
- const col = Number(match[2]) - 1
35
- const [rows, cols] = dimensions
36
- if (row < 0 || col < 0 || row >= rows || col >= cols) {
37
- throw new Error(`Well '${wellId}' is outside a ${format}-well plate.`)
38
- }
39
- }
40
-
41
- export function readPlateFormat(value: unknown, fallback: WellPlateFormat): WellPlateFormat {
42
- const parsed = typeof value === 'number'
43
- ? value
44
- : typeof value === 'string'
45
- ? Number(value)
46
- : Number.NaN
47
- return parsed in PLATE_DIMENSIONS ? (parsed as WellPlateFormat) : fallback
48
- }
49
-
50
- function rowLabel(index: number): string {
51
- let label = ''
52
- let current = index
53
- while (true) {
54
- label = String.fromCharCode(65 + (current % 26)) + label
55
- current = Math.floor(current / 26) - 1
56
- if (current < 0) return label
57
- }
58
- }
59
-
60
- function rowIndex(label: string): number {
61
- return [...label].reduce((value, char) => value * 26 + char.charCodeAt(0) - 64, 0) - 1
62
- }