@morscherlab/mint-sdk 1.2.0-beta.8 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (402) hide show
  1. package/README.md +60 -0
  2. package/dist/{ExperimentPopover-CfOdh5Rm.js → ExperimentPopover-CJdNlCZb.js} +24 -15
  3. package/dist/ExperimentPopover-CJdNlCZb.js.map +1 -0
  4. package/dist/{ExperimentSelectorModal-DvIagrxY.js → ExperimentSelectorModal-DCXmwKNS.js} +5 -5
  5. package/dist/ExperimentSelectorModal-DCXmwKNS.js.map +1 -0
  6. package/dist/{SettingsModal-W3TYfnP9.js → SettingsModal-BYR20I4c.js} +5 -5
  7. package/dist/SettingsModal-BYR20I4c.js.map +1 -0
  8. package/dist/{EmptyState-NBqf2_8z.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/iconButtonIconSizing.test.d.ts +1 -0
  17. package/dist/__tests__/composables/useFileBrowser.test.d.ts +1 -0
  18. package/dist/__tests__/composables/useListReorder.test.d.ts +1 -0
  19. package/dist/__tests__/composables/usePlatformFilePickerAdapter.test.d.ts +1 -0
  20. package/dist/__tests__/styles/cssTokens.test.d.ts +1 -0
  21. package/dist/apiErrors.d.ts +26 -0
  22. package/dist/components/ActionMenu.vue.d.ts +1 -1
  23. package/dist/components/AppPluginSwitcher.vue.d.ts +2 -0
  24. package/dist/components/AuditTrail.vue.d.ts +13 -0
  25. package/dist/components/BaseInput.vue.d.ts +1 -1
  26. package/dist/components/BaseSelect.vue.d.ts +1 -1
  27. package/dist/components/BaseTextarea.vue.d.ts +1 -1
  28. package/dist/components/BatchProgressList.vue.d.ts +17 -0
  29. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
  30. package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +2 -2
  31. package/dist/components/ConcentrationInput.vue.d.ts +1 -1
  32. package/dist/components/DataFrame.vue.d.ts +14 -2
  33. package/dist/components/DatePicker.vue.d.ts +2 -2
  34. package/dist/components/DateTimePicker.vue.d.ts +3 -1
  35. package/dist/components/ExperimentDataViewer.vue.d.ts +26 -1
  36. package/dist/components/ExperimentPopover.vue.d.ts +1 -0
  37. package/dist/components/ExperimentTimeline.vue.d.ts +29 -1
  38. package/dist/components/FileBrowserModal.vue.d.ts +99 -0
  39. package/dist/components/FilePicker.vue.d.ts +32 -0
  40. package/dist/components/FileUploader.vue.d.ts +5 -2
  41. package/dist/components/FormulaInput.vue.d.ts +1 -1
  42. package/dist/components/GeneratedPlotlyResult.vue.d.ts +1 -3
  43. package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
  44. package/dist/components/MobileSupportGate.vue.d.ts +1 -1
  45. package/dist/components/MoleculeInput.vue.d.ts +1 -1
  46. package/dist/components/NumberInput.vue.d.ts +1 -1
  47. package/dist/components/PlotlyChart.vue.d.ts +59 -0
  48. package/dist/components/ProgressBar.vue.d.ts +1 -1
  49. package/dist/components/ProtocolStepEditor.vue.d.ts +1 -0
  50. package/dist/components/ReagentList.vue.d.ts +29 -1
  51. package/dist/components/ResourceCard.vue.d.ts +1 -1
  52. package/dist/components/SampleHierarchyTree.vue.d.ts +29 -1
  53. package/dist/components/SampleSelector.drag.d.ts +13 -0
  54. package/dist/components/SampleSelector.tree.d.ts +2 -0
  55. package/dist/components/SampleSelector.vue.d.ts +34 -1
  56. package/dist/components/ScheduleCalendar.vue.d.ts +20 -0
  57. package/dist/components/SecretInput.vue.d.ts +1 -1
  58. package/dist/components/SequenceInput.vue.d.ts +1 -1
  59. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +1 -0
  60. package/dist/components/StatusIndicator.vue.d.ts +1 -1
  61. package/dist/components/TagsInput.vue.d.ts +1 -1
  62. package/dist/components/TimePicker.vue.d.ts +2 -1
  63. package/dist/components/TimeRangeInput.vue.d.ts +1 -1
  64. package/dist/components/UnitInput.vue.d.ts +1 -1
  65. package/dist/components/WellPlate.geometry.d.ts +15 -0
  66. package/dist/components/WellPlate.interaction.d.ts +13 -0
  67. package/dist/components/WellPlate.vue.d.ts +30 -1
  68. package/dist/components/fileBrowserPresentation.d.ts +10 -0
  69. package/dist/components/index.d.ts +4 -0
  70. package/dist/components/index.js +8 -8
  71. package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -0
  72. package/dist/components/internal/DataStateInternal.vue.d.ts +43 -0
  73. package/dist/components/internal/FileBrowserDialogInternal.vue.d.ts +34 -0
  74. package/dist/components/internal/FileBrowserListingInternal.vue.d.ts +25 -0
  75. package/dist/components/internal/FileBrowserToolbarInternal.vue.d.ts +26 -0
  76. package/dist/components/internal/FilePickerPreviewInternal.vue.d.ts +18 -0
  77. package/dist/components/internal/FilePickerTreeInternal.vue.d.ts +31 -0
  78. package/dist/{components-B80gV0P6.js → components-DIum5hkx.js} +5415 -2753
  79. package/dist/components-DIum5hkx.js.map +1 -0
  80. package/dist/composables/controlSchemaTypes.d.ts +34 -0
  81. package/dist/composables/filePicker/localFiles.d.ts +3 -0
  82. package/dist/composables/filePicker/usePickerNavigation.d.ts +96 -0
  83. package/dist/composables/filePicker/usePickerSelection.d.ts +31 -0
  84. package/dist/composables/filePicker/validation.d.ts +5 -0
  85. package/dist/composables/index.d.ts +3 -0
  86. package/dist/composables/index.js +10 -10
  87. package/dist/composables/useApi.d.ts +14 -7
  88. package/dist/composables/useDropdownState.d.ts +18 -2
  89. package/dist/composables/useEventStream.d.ts +9 -0
  90. package/dist/composables/useFileBrowser.d.ts +55 -0
  91. package/dist/composables/useFilePicker.d.ts +189 -0
  92. package/dist/composables/useListReorder.d.ts +90 -0
  93. package/dist/composables/useMenuKeyboard.d.ts +2 -2
  94. package/dist/composables/usePlatformFilePickerAdapter.d.ts +11 -0
  95. package/dist/composables/usePluginConfig.d.ts +3 -1
  96. package/dist/composables/useRequestSyncState.d.ts +42 -2
  97. package/dist/composables/useScheduleDrag.d.ts +1 -0
  98. package/dist/{composables-C8mmD5ta.js → composables-mFXsTA4g.js} +307 -74
  99. package/dist/composables-mFXsTA4g.js.map +1 -0
  100. package/dist/{useApi-CDBq6z23.js → errors-BLuqMee5.js} +178 -16
  101. package/dist/errors-BLuqMee5.js.map +1 -0
  102. package/dist/{experiment-Y9Iz7KYi.js → experiment-CVDRAnqp.js} +3 -8
  103. package/dist/experiment-CVDRAnqp.js.map +1 -0
  104. package/dist/{experiment-utils-DV3DrvE_.js → experiment-utils-CV2Wza3z.js} +1 -1
  105. package/dist/experiment-utils-CV2Wza3z.js.map +1 -0
  106. package/dist/index.d.ts +1 -0
  107. package/dist/index.js +15 -15
  108. package/dist/install.js +2 -7
  109. package/dist/install.js.map +1 -1
  110. package/dist/permissions.d.ts +42 -1
  111. package/dist/permissions.js +20 -10
  112. package/dist/permissions.js.map +1 -1
  113. package/dist/stores/index.d.ts +1 -1
  114. package/dist/stores/index.js +3 -3
  115. package/dist/stores/settings.d.ts +31 -1
  116. package/dist/styles.css +15162 -32475
  117. package/dist/templates/index.js +2 -4
  118. package/dist/{templates-CK72aKO1.js → templates-CmGfmBRA.js} +291 -85
  119. package/dist/templates-CmGfmBRA.js.map +1 -0
  120. package/dist/types/fileBrowserTypes.d.ts +77 -0
  121. package/dist/types/filePicker.d.ts +77 -0
  122. package/dist/types/index.d.ts +2 -0
  123. package/dist/{useControlSchema-_OVhavKq.js → useControlSchema-DldpxNOP.js} +234 -1121
  124. package/dist/useControlSchema-DldpxNOP.js.map +1 -0
  125. package/dist/{useDropdownState-D5G4UvWd.js → useDropdownState-C7hRiVQf.js} +22 -6
  126. package/dist/useDropdownState-C7hRiVQf.js.map +1 -0
  127. package/dist/{useExperimentSelector-DSEckf_g.js → useExperimentSelector-CEcIaueJ.js} +4 -4
  128. package/dist/{useExperimentSelector-DSEckf_g.js.map → useExperimentSelector-CEcIaueJ.js.map} +1 -1
  129. package/dist/{useFormBuilder-Bd714C7y.js → useFormBuilder-z5L_dUIy.js} +2 -2
  130. package/dist/{useFormBuilder-Bd714C7y.js.map → useFormBuilder-z5L_dUIy.js.map} +1 -1
  131. package/dist/utils/color.d.ts +13 -0
  132. package/dist/utils/errors.d.ts +9 -0
  133. package/dist/{useProtocolTemplates-Dq5Pzwyd.js → validation-uwoJGEb6.js} +231 -158
  134. package/dist/validation-uwoJGEb6.js.map +1 -0
  135. package/package.json +1 -1
  136. package/src/__tests__/apiErrors.test.ts +81 -0
  137. package/src/__tests__/components/ActionMenu.test.ts +94 -0
  138. package/src/__tests__/components/DataFrame.test.ts +183 -11
  139. package/src/__tests__/components/DataStates.test.ts +176 -0
  140. package/src/__tests__/components/DatePicker.test.ts +76 -0
  141. package/src/__tests__/components/DateTimePicker.test.ts +36 -0
  142. package/src/__tests__/components/ExperimentPopover.test.ts +30 -0
  143. package/src/__tests__/components/ExperimentTimeline.test.ts +63 -0
  144. package/src/__tests__/components/FileBrowserModal.test.ts +460 -0
  145. package/src/__tests__/components/FilePicker.state.test.ts +287 -0
  146. package/src/__tests__/components/FilePicker.test.ts +487 -0
  147. package/src/__tests__/components/GeneratedPlotlyResult.test.ts +52 -5
  148. package/src/__tests__/components/GroupAssigner.test.ts +53 -0
  149. package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
  150. package/src/__tests__/components/PlotlyChart.test.ts +305 -0
  151. package/src/__tests__/components/RackEditor.test.ts +35 -0
  152. package/src/__tests__/components/ReagentList.test.ts +64 -2
  153. package/src/__tests__/components/RetiredStyles.test.ts +31 -0
  154. package/src/__tests__/components/SampleSelector.drag.test.ts +51 -1
  155. package/src/__tests__/components/ScheduleCalendar.test.ts +63 -0
  156. package/src/__tests__/components/SegmentedControl.test.ts +107 -0
  157. package/src/__tests__/components/TimePicker.test.ts +61 -0
  158. package/src/__tests__/components/WellPlate.interaction.test.ts +59 -0
  159. package/src/__tests__/components/iconButtonIconSizing.test.ts +18 -0
  160. package/src/__tests__/composables/useApi.test.ts +92 -9
  161. package/src/__tests__/composables/useDropdownState.test.ts +58 -1
  162. package/src/__tests__/composables/useFileBrowser.test.ts +305 -0
  163. package/src/__tests__/composables/useGeneratedAnalysis.test.ts +7 -2
  164. package/src/__tests__/composables/useListReorder.test.ts +145 -0
  165. package/src/__tests__/composables/usePlatformFilePickerAdapter.test.ts +67 -0
  166. package/src/__tests__/composables/usePluginClient.test.ts +3 -0
  167. package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
  168. package/src/__tests__/stores/settings.test.ts +71 -1
  169. package/src/__tests__/styles/cssTokens.test.ts +131 -0
  170. package/src/__tests__/utils/permissions.test.ts +68 -0
  171. package/src/apiErrors.ts +85 -0
  172. package/src/components/ActionMenu.vue +45 -88
  173. package/src/components/AlertBox.vue +0 -4
  174. package/src/components/AppAvatarMenu.vue +2 -14
  175. package/src/components/AppLayout.vue +0 -4
  176. package/src/components/AppPluginSwitcher.story.vue +87 -0
  177. package/src/components/AppPluginSwitcher.vue +2 -5
  178. package/src/components/AppSidebar.vue +0 -4
  179. package/src/components/AppToastContainer.vue +6 -8
  180. package/src/components/AppTopBar.vue +0 -4
  181. package/src/components/ArtifactSaveDialog.vue +0 -4
  182. package/src/components/ArtifactSelectorModal.vue +0 -4
  183. package/src/components/AuditTrail.story.vue +18 -0
  184. package/src/components/AuditTrail.vue +27 -7
  185. package/src/components/AutoGroupModal.vue +0 -4
  186. package/src/components/Avatar.vue +0 -4
  187. package/src/components/BaseButton.vue +0 -4
  188. package/src/components/BaseCheckbox.vue +0 -4
  189. package/src/components/BaseInput.vue +0 -4
  190. package/src/components/BaseModal.vue +0 -4
  191. package/src/components/BasePill.vue +0 -4
  192. package/src/components/BaseRadioGroup.vue +0 -4
  193. package/src/components/BaseSelect.vue +0 -4
  194. package/src/components/BaseSlider.vue +0 -4
  195. package/src/components/BaseTabs.vue +0 -4
  196. package/src/components/BaseTextarea.vue +0 -4
  197. package/src/components/BaseToggle.vue +0 -4
  198. package/src/components/BatchProgressList.story.vue +18 -0
  199. package/src/components/BatchProgressList.vue +32 -4
  200. package/src/components/Breadcrumb.vue +0 -4
  201. package/src/components/Calendar.vue +0 -4
  202. package/src/components/ChartContainer.story.vue +1 -1
  203. package/src/components/ChartContainer.vue +0 -4
  204. package/src/components/ChemicalFormula.vue +0 -4
  205. package/src/components/CollapsibleCard.vue +0 -4
  206. package/src/components/ColorSlider.vue +0 -4
  207. package/src/components/ConcentrationInput.vue +0 -4
  208. package/src/components/ConfirmDialog.vue +0 -4
  209. package/src/components/DataFrame.story.vue +14 -0
  210. package/src/components/DataFrame.vue +97 -23
  211. package/src/components/DatePicker.vue +73 -27
  212. package/src/components/DateTimePicker.vue +45 -17
  213. package/src/components/Divider.vue +0 -4
  214. package/src/components/DoseCalculator.vue +0 -4
  215. package/src/components/DropdownButton.vue +2 -14
  216. package/src/components/EmptyState.vue +0 -4
  217. package/src/components/ExperimentCodeBadge.vue +0 -4
  218. package/src/components/ExperimentDataViewer.story.vue +3 -0
  219. package/src/components/ExperimentDataViewer.vue +33 -13
  220. package/src/components/ExperimentPopover.vue +12 -7
  221. package/src/components/ExperimentSelectorModal.vue +0 -4
  222. package/src/components/ExperimentTimeline.story.vue +18 -0
  223. package/src/components/ExperimentTimeline.vue +81 -75
  224. package/src/components/FileBrowserModal.story.vue +203 -0
  225. package/src/components/FileBrowserModal.vue +384 -0
  226. package/src/components/FilePicker.story.vue +44 -0
  227. package/src/components/FilePicker.vue +284 -0
  228. package/src/components/FileUploader.vue +32 -18
  229. package/src/components/FitPanel.vue +0 -4
  230. package/src/components/FormActions.story.vue +96 -0
  231. package/src/components/FormActions.vue +0 -4
  232. package/src/components/FormBuilder.vue +0 -4
  233. package/src/components/FormField.vue +0 -4
  234. package/src/components/FormulaInput.vue +0 -4
  235. package/src/components/GeneratedPathInput.story.vue +68 -0
  236. package/src/components/GeneratedPlotlyResult.story.vue +96 -0
  237. package/src/components/GeneratedPlotlyResult.vue +34 -69
  238. package/src/components/GeneratedPluginView.story.vue +145 -0
  239. package/src/components/GeneratedPluginView.vue +10 -10
  240. package/src/components/GeneratedResultRenderer.story.vue +117 -0
  241. package/src/components/GeneratedResultRenderer.vue +4 -9
  242. package/src/components/GroupAssigner.vue +67 -5
  243. package/src/components/IconButton.vue +0 -4
  244. package/src/components/InstrumentAlertLog.vue +0 -4
  245. package/src/components/InstrumentStateBadge.vue +0 -4
  246. package/src/components/InstrumentStatusCard.vue +0 -4
  247. package/src/components/JobsStatusTray.vue +0 -4
  248. package/src/components/LcmsSequenceTable.vue +81 -50
  249. package/src/components/LoadingSpinner.vue +0 -4
  250. package/src/components/MobileSupportGate.vue +0 -4
  251. package/src/components/MoleculeInput.vue +0 -4
  252. package/src/components/MultiSelect.vue +0 -4
  253. package/src/components/NumberInput.vue +0 -4
  254. package/src/components/PlateMapEditor.vue +3 -14
  255. package/src/components/PlotlyChart.story.vue +61 -0
  256. package/src/components/PlotlyChart.vue +233 -0
  257. package/src/components/PluginIcon.vue +0 -4
  258. package/src/components/ProgressBar.vue +0 -4
  259. package/src/components/ProtocolStepEditor.vue +2 -4
  260. package/src/components/RackEditor.vue +51 -70
  261. package/src/components/ReagentEditor.vue +0 -4
  262. package/src/components/ReagentList.story.vue +18 -0
  263. package/src/components/ReagentList.vue +127 -82
  264. package/src/components/ResourceCard.vue +0 -4
  265. package/src/components/RuntimeUpdateNotice.story.vue +49 -0
  266. package/src/components/RuntimeUpdateNotice.vue +4 -4
  267. package/src/components/SampleHierarchyTree.story.vue +18 -0
  268. package/src/components/SampleHierarchyTree.vue +32 -9
  269. package/src/components/SampleLegend.vue +2 -8
  270. package/src/components/SampleSelector.drag.ts +51 -0
  271. package/src/components/SampleSelector.story.vue +6 -0
  272. package/src/components/SampleSelector.tree.ts +2 -0
  273. package/src/components/SampleSelector.vue +49 -10
  274. package/src/components/SampleSelectorGroupNode.vue +19 -0
  275. package/src/components/ScheduleCalendar.story.vue +6 -0
  276. package/src/components/ScheduleCalendar.vue +82 -7
  277. package/src/components/ScientificNumber.vue +0 -4
  278. package/src/components/SectionCard.vue +0 -4
  279. package/src/components/SegmentedControl.vue +50 -7
  280. package/src/components/SequenceInput.vue +0 -4
  281. package/src/components/SequenceProgressBar.story.vue +110 -0
  282. package/src/components/SequenceProgressBar.vue +0 -4
  283. package/src/components/SettingsModal.vue +0 -4
  284. package/src/components/Skeleton.vue +0 -4
  285. package/src/components/SmartGroupFieldRecipe.vue +8 -6
  286. package/src/components/SmartGroupManual.vue +0 -4
  287. package/src/components/StatusIndicator.vue +0 -4
  288. package/src/components/StepWizard.vue +0 -4
  289. package/src/components/TagsInput.vue +4 -6
  290. package/src/components/ThemeToggle.vue +0 -4
  291. package/src/components/TimePicker.vue +36 -7
  292. package/src/components/TimeRangeInput.vue +0 -4
  293. package/src/components/Tooltip.story.vue +3 -3
  294. package/src/components/Tooltip.vue +0 -4
  295. package/src/components/UnitInput.vue +0 -4
  296. package/src/components/WellPlate.geometry.ts +60 -1
  297. package/src/components/WellPlate.interaction.ts +44 -0
  298. package/src/components/WellPlate.story.vue +8 -0
  299. package/src/components/WellPlate.vue +53 -7
  300. package/src/components/fileBrowserPresentation.ts +39 -0
  301. package/src/components/index.ts +5 -0
  302. package/src/components/internal/AppTopBarPageSelectorInternal.vue +2 -5
  303. package/src/components/internal/AppTopBarPillNavInternal.vue +0 -4
  304. package/src/components/internal/DataStateInternal.vue +74 -0
  305. package/src/components/internal/FileBrowserDialogInternal.vue +75 -0
  306. package/src/components/internal/FileBrowserListingInternal.vue +197 -0
  307. package/src/components/internal/FileBrowserToolbarInternal.vue +136 -0
  308. package/src/components/internal/FilePickerPreviewInternal.vue +100 -0
  309. package/src/components/internal/FilePickerTreeInternal.vue +238 -0
  310. package/src/components/internal/FormSectionRenderer.vue +0 -4
  311. package/src/components/internal/WellEditPopupInternal.vue +0 -4
  312. package/src/composables/controlSchemaTypes.ts +34 -0
  313. package/src/composables/filePicker/localFiles.ts +58 -0
  314. package/src/composables/filePicker/usePickerNavigation.ts +220 -0
  315. package/src/composables/filePicker/usePickerSelection.ts +259 -0
  316. package/src/composables/filePicker/validation.ts +41 -0
  317. package/src/composables/index.ts +17 -0
  318. package/src/composables/useApi.ts +57 -13
  319. package/src/composables/useDropdownState.ts +35 -5
  320. package/src/composables/useEventStream.ts +14 -2
  321. package/src/composables/useFileBrowser.ts +314 -0
  322. package/src/composables/useFileImport.ts +2 -7
  323. package/src/composables/useFilePicker.ts +366 -0
  324. package/src/composables/useGeneratedAnalysis.ts +18 -26
  325. package/src/composables/useListReorder.story.vue +143 -0
  326. package/src/composables/useListReorder.ts +242 -0
  327. package/src/composables/useMenuKeyboard.ts +2 -2
  328. package/src/composables/useOptimisticMutation.ts +1 -15
  329. package/src/composables/usePlatformFilePickerAdapter.ts +104 -0
  330. package/src/composables/usePluginClient.ts +3 -0
  331. package/src/composables/usePluginConfig.ts +3 -1
  332. package/src/composables/useRackEditor.ts +2 -11
  333. package/src/composables/useRequestSyncState.ts +98 -28
  334. package/src/composables/useResourceCrud.ts +1 -15
  335. package/src/composables/useScheduleDrag.ts +37 -0
  336. package/src/composables/useWellPainting.ts +5 -29
  337. package/src/composables/useWellPlateEditor.ts +1 -11
  338. package/src/index.ts +3 -0
  339. package/src/permissions.ts +48 -9
  340. package/src/stores/experiment.ts +2 -7
  341. package/src/stores/index.ts +9 -1
  342. package/src/stores/settings.ts +93 -1
  343. package/src/styles/components/audit-trail.css +5 -5
  344. package/src/styles/components/batch-progress-list.css +7 -0
  345. package/src/styles/components/color-slider.css +2 -2
  346. package/src/styles/components/data-state.css +30 -0
  347. package/src/styles/components/dataframe.css +29 -35
  348. package/src/styles/components/experiment-data-viewer.css +4 -4
  349. package/src/styles/components/experiment-timeline.css +3 -30
  350. package/src/styles/components/file-browser-modal.css +489 -0
  351. package/src/styles/components/file-picker.css +502 -0
  352. package/src/styles/components/form-builder.css +5 -5
  353. package/src/styles/components/icon-button.css +9 -0
  354. package/src/styles/components/lcms-sequence-table.css +16 -1
  355. package/src/styles/components/multi-select.css +1 -1
  356. package/src/styles/components/reagent-list.css +38 -31
  357. package/src/styles/components/sample-hierarchy-tree.css +5 -19
  358. package/src/styles/components/sample-selector.css +9 -2
  359. package/src/styles/components/schedule-calendar.css +8 -0
  360. package/src/styles/components/scientific-number.css +1 -1
  361. package/src/styles/components/well-plate.css +8 -0
  362. package/src/styles/index.css +11 -0
  363. package/src/styles/variables.css +29 -0
  364. package/src/templates/builderPresetControls.ts +1 -1
  365. package/src/templates/componentPlateHelpers.ts +3 -1
  366. package/src/templates/doseResponseAdapters.ts +2 -13
  367. package/src/templates/elisaAssayCollectionBuilder.ts +2 -2
  368. package/src/templates/plateMapBuilder.ts +2 -2
  369. package/src/templates/qpcrPlateBuilder.ts +1 -1
  370. package/src/templates/templateValidators.ts +1 -1
  371. package/src/templates/timeCourseBuilder.ts +2 -2
  372. package/src/templates/wellPlateScreenCollectionBuilder.ts +2 -2
  373. package/src/types/fileBrowserTypes.ts +85 -0
  374. package/src/types/filePicker.ts +72 -0
  375. package/src/types/index.ts +14 -0
  376. package/src/utils/color.ts +51 -0
  377. package/src/utils/errors.ts +29 -0
  378. package/dist/EmptyState-NBqf2_8z.js.map +0 -1
  379. package/dist/ExperimentPopover-CfOdh5Rm.js.map +0 -1
  380. package/dist/ExperimentSelectorModal-DvIagrxY.js.map +0 -1
  381. package/dist/SettingsModal-W3TYfnP9.js.map +0 -1
  382. package/dist/components-B80gV0P6.js.map +0 -1
  383. package/dist/composables/autoGroupConstants.d.ts +0 -1
  384. package/dist/composables/autoGroupGrouping.d.ts +0 -3
  385. package/dist/composables/useAutoGroupInputSources.d.ts +0 -32
  386. package/dist/composables-C8mmD5ta.js.map +0 -1
  387. package/dist/experiment-Y9Iz7KYi.js.map +0 -1
  388. package/dist/experiment-utils-DV3DrvE_.js.map +0 -1
  389. package/dist/templates/builderDefaults.d.ts +0 -1
  390. package/dist/templates/plateGeometry.d.ts +0 -4
  391. package/dist/templates-CK72aKO1.js.map +0 -1
  392. package/dist/useApi-CDBq6z23.js.map +0 -1
  393. package/dist/useControlSchema-_OVhavKq.js.map +0 -1
  394. package/dist/useDropdownState-D5G4UvWd.js.map +0 -1
  395. package/dist/useProtocolTemplates-Dq5Pzwyd.js.map +0 -1
  396. package/src/__tests__/composables/useAutoGroupInputSources.test.ts +0 -127
  397. package/src/composables/autoGroupConstants.ts +0 -4
  398. package/src/composables/autoGroupGrouping.ts +0 -148
  399. package/src/composables/useAutoGroupInputSources.ts +0 -147
  400. package/src/templates/builderDefaults.ts +0 -11
  401. package/src/templates/plateGeometry.ts +0 -62
  402. /package/dist/__tests__/{composables/useAutoGroupInputSources.test.d.ts → apiErrors.test.d.ts} +0 -0
@@ -0,0 +1,284 @@
1
+ <script setup lang="ts">
2
+ /** Adapter-driven file picker with Finder-style selection, disclosure and metadata preview. */
3
+ import { ref } from 'vue'
4
+ import BaseButton from './BaseButton.vue'
5
+ import BaseInput from './BaseInput.vue'
6
+ import IconButton from './IconButton.vue'
7
+ import FileUploader from './FileUploader.vue'
8
+ import FileBrowserDialogInternal from './internal/FileBrowserDialogInternal.vue'
9
+ import FilePickerTreeInternal from './internal/FilePickerTreeInternal.vue'
10
+ import FilePickerPreviewInternal from './internal/FilePickerPreviewInternal.vue'
11
+ import { formatBytes } from './fileBrowserPresentation'
12
+ import { useFilePicker } from '../composables/useFilePicker'
13
+ import { pickerReason } from '../composables/filePicker/validation'
14
+ import type {
15
+ PickerAdapter,
16
+ PickerCapabilities,
17
+ PickerNode,
18
+ PickerSelection,
19
+ PickerSelectionMode,
20
+ PickerSource,
21
+ } from '../types/filePicker'
22
+
23
+ interface Props {
24
+ open: boolean
25
+ adapter: PickerAdapter
26
+ selectionMode?: PickerSelectionMode
27
+ sources?: PickerSource[]
28
+ capabilities?: PickerCapabilities
29
+ initialPath?: string
30
+ initialSelection?: PickerSelection | null
31
+ title?: string
32
+ /** Host-owned visibility/selection filter; backend must still enforce access. */
33
+ systemFilter?: (node: PickerNode, source: PickerSource) => boolean
34
+ }
35
+ const props = withDefaults(defineProps<Props>(), {
36
+ selectionMode: 'folder+files',
37
+ sources: () => ['server'],
38
+ capabilities: () => ({}),
39
+ initialPath: '',
40
+ initialSelection: null,
41
+ title: 'Choose data',
42
+ })
43
+ const emit = defineEmits<{
44
+ 'update:open': [open: boolean]
45
+ select: [selection: PickerSelection]
46
+ cancel: []
47
+ }>()
48
+ const uploadError = ref('')
49
+ const {
50
+ previewNode,
51
+ sourceNames,
52
+ sourceIcons,
53
+ allowedSources,
54
+ source,
55
+ query,
56
+ recursive,
57
+ skipBlanks,
58
+ reviewing,
59
+ nav,
60
+ selection,
61
+ capability,
62
+ path,
63
+ trail,
64
+ loading,
65
+ error,
66
+ rows,
67
+ roots,
68
+ chosen,
69
+ focused,
70
+ resolving,
71
+ resolutionError,
72
+ searchArea,
73
+ confirmLabel,
74
+ folderCount,
75
+ canConfirm,
76
+ switchSource,
77
+ selectNode,
78
+ enter,
79
+ up,
80
+ refresh,
81
+ selectParent,
82
+ chooseLocal,
83
+ cancel,
84
+ confirm,
85
+ keyboard,
86
+ } = useFilePicker(props, emit)
87
+ </script>
88
+
89
+ <template>
90
+ <FileBrowserDialogInternal
91
+ :open="open"
92
+ :label="title"
93
+ size="full"
94
+ variant="picker"
95
+ @close="cancel"
96
+ >
97
+ <template #header>
98
+ <div v-if="source === 'server'" ref="searchArea" class="mint-picker__search">
99
+ <svg
100
+ viewBox="0 0 24 24"
101
+ fill="none"
102
+ stroke="currentColor"
103
+ stroke-width="1.8"
104
+ aria-hidden="true"
105
+ >
106
+ <circle cx="10.5" cy="10.5" r="7" />
107
+ <path d="m16 16 5 5" />
108
+ </svg>
109
+ <BaseInput
110
+ v-model="query"
111
+ aria-label="Search folders and files"
112
+ placeholder="Search folders and files…"
113
+ />
114
+ <kbd>/</kbd>
115
+ </div>
116
+ <h2 v-else class="mint-file-browser__title mint-picker__local-title">{{ title }}</h2>
117
+ <div
118
+ v-if="allowedSources.length > 1"
119
+ class="mint-picker__sources"
120
+ role="group"
121
+ aria-label="Data source"
122
+ :style="{ '--picker-source-index': allowedSources.indexOf(source) }"
123
+ >
124
+ <span class="mint-picker__source-indicator" aria-hidden="true" />
125
+ <IconButton
126
+ v-for="item in allowedSources"
127
+ :key="item"
128
+ size="sm"
129
+ variant="ghost"
130
+ :label="sourceNames[item]"
131
+ :aria-pressed="item === source"
132
+ @click="switchSource(item)"
133
+ >
134
+ <svg
135
+ viewBox="0 0 24 24"
136
+ fill="none"
137
+ stroke="currentColor"
138
+ stroke-width="1.8"
139
+ aria-hidden="true"
140
+ >
141
+ <path :d="sourceIcons[item]" />
142
+ </svg>
143
+ </IconButton>
144
+ </div>
145
+ </template>
146
+ <div :key="source" class="mint-picker mint-picker__source-panel" @keydown="keyboard">
147
+ <div v-if="source === 'server'" class="mint-picker__pathbar">
148
+ <IconButton
149
+ label="Up one level"
150
+ size="sm"
151
+ variant="secondary"
152
+ :disabled="!path"
153
+ @click="up()"
154
+ ><svg
155
+ viewBox="0 0 24 24"
156
+ fill="none"
157
+ stroke="currentColor"
158
+ stroke-width="2"
159
+ aria-hidden="true"
160
+ >
161
+ <path d="M11 17l-5-5 5-5M6 12h13" /></svg
162
+ ></IconButton>
163
+ <nav aria-label="Breadcrumb" class="mint-picker__breadcrumbs">
164
+ <BaseButton variant="ghost" size="sm" @click="up('')">{{
165
+ sourceNames[source]
166
+ }}</BaseButton>
167
+ <template v-for="crumb in trail" :key="crumb.path"
168
+ ><span>/</span
169
+ ><BaseButton variant="ghost" size="sm" @click="up(crumb.path)">{{
170
+ crumb.label
171
+ }}</BaseButton></template
172
+ >
173
+ </nav>
174
+ <BaseButton
175
+ variant="ghost"
176
+ size="sm"
177
+ class="mint-picker__scope"
178
+ :aria-pressed="recursive"
179
+ @click="recursive = !recursive"
180
+ >{{ recursive ? 'Subfolders' : 'This folder' }}</BaseButton
181
+ >
182
+ <IconButton size="sm" label="Refresh location" :disabled="loading" @click="refresh()"
183
+ ><svg
184
+ viewBox="0 0 24 24"
185
+ fill="none"
186
+ stroke="currentColor"
187
+ stroke-width="1.8"
188
+ aria-hidden="true"
189
+ >
190
+ <path d="M20 7v5h-5M4 17v-5h5M6 8a7 7 0 0 1 12-2l2 3M4 15l2 3a7 7 0 0 0 12-2" /></svg
191
+ ></IconButton>
192
+ </div>
193
+ <div v-if="!allowedSources.length" class="mint-picker__empty">
194
+ No data sources are enabled.
195
+ </div>
196
+ <template v-else>
197
+ <div v-if="source === 'localFile'" class="mint-picker__local-upload">
198
+ <FileUploader
199
+ size="lg"
200
+ :mode="selectionMode === 'folder' ? 'folder' : selectionMode === 'single-file' ? 'file' : 'file+folder'"
201
+ :multiple="selectionMode !== 'single-file'"
202
+ :show-files="false"
203
+ @upload="(...args) => { uploadError = ''; chooseLocal(...args) }"
204
+ @error="uploadError = $event"
205
+ />
206
+ <p v-if="uploadError || error || resolutionError" role="alert">
207
+ {{ uploadError || error || resolutionError }}
208
+ </p>
209
+ </div>
210
+ <div v-else class="mint-picker__workspace">
211
+ <FilePickerTreeInternal
212
+ :empty-title="
213
+ path
214
+ ? 'No readable files'
215
+ : 'No server locations configured'
216
+ "
217
+ :rows="rows"
218
+ :loading="loading"
219
+ :error="error"
220
+ :query="query"
221
+ :mode="selectionMode"
222
+ :selected="selection.selected"
223
+ :reason="(node) => pickerReason(selection.exclusion(node), node)"
224
+ :progress="selection.folderProgress"
225
+ :focus-path="selection.focusPath.value"
226
+ @select="selectNode"
227
+ @enter="enter"
228
+ @expand="nav.expand"
229
+ @up="up"
230
+ @retry="refresh"
231
+ @parent="selectParent"
232
+ />
233
+ <FilePickerPreviewInternal
234
+ :node="previewNode"
235
+ :total-count="focused?.kind === 'folder' ? focused.fileCount : undefined"
236
+ :source="source"
237
+ :exclusions="chosen.excluded"
238
+ :busy="resolving"
239
+ :error="resolutionError"
240
+ :reviewing="reviewing"
241
+ @review="reviewing = !reviewing"
242
+ @retry="selection.resolve"
243
+ />
244
+ </div>
245
+ </template>
246
+ </div>
247
+ <template #footer>
248
+ <div class="mint-picker__footer">
249
+ <div class="mint-picker__receipt" role="status">
250
+ <span v-if="folderCount" class="mint-picker__badge"
251
+ >{{ folderCount }} folder{{ folderCount === 1 ? '' : 's' }}</span
252
+ >
253
+ <span v-if="chosen.files.length" class="mint-picker__badge"
254
+ >{{ chosen.files.length }} {{ chosen.files.length === 1 ? 'file' : 'files' }}</span
255
+ >
256
+ <span v-if="roots.length">{{ resolving ? 'Checking…' : formatBytes(chosen.bytes) }}</span>
257
+ <span v-else>No selection</span>
258
+ <BaseButton
259
+ v-if="chosen.excluded.length && source === 'server'"
260
+ variant="ghost"
261
+ size="sm"
262
+ @click="reviewing = !reviewing"
263
+ >{{ chosen.excluded.length }} skipped</BaseButton
264
+ >
265
+ <span v-else-if="chosen.excluded.length">{{ chosen.excluded.length }} skipped</span>
266
+ <BaseButton
267
+ v-if="capability?.isBlank"
268
+ size="sm"
269
+ variant="ghost"
270
+ :aria-pressed="skipBlanks"
271
+ @click="skipBlanks = !skipBlanks"
272
+ >Skip blanks {{ skipBlanks ? 'on' : 'off' }}</BaseButton
273
+ >
274
+ </div>
275
+ <div class="mint-picker__actions">
276
+ <BaseButton variant="ghost" size="sm" @click="cancel">Cancel</BaseButton
277
+ ><BaseButton size="sm" :disabled="!canConfirm" @click="confirm">{{
278
+ confirmLabel
279
+ }}</BaseButton>
280
+ </div>
281
+ </div>
282
+ </template>
283
+ </FileBrowserDialogInternal>
284
+ </template>
@@ -8,7 +8,9 @@ interface Props {
8
8
  maxSize?: number
9
9
  disabled?: boolean
10
10
  size?: 'sm' | 'md' | 'lg'
11
- mode?: 'file' | 'folder'
11
+ mode?: 'file' | 'folder' | 'file+folder'
12
+ /** Hide the selection list when a parent presents the files itself. */
13
+ showFiles?: boolean
12
14
  }
13
15
 
14
16
  const props = withDefaults(defineProps<Props>(), {
@@ -16,6 +18,7 @@ const props = withDefaults(defineProps<Props>(), {
16
18
  disabled: false,
17
19
  size: 'md',
18
20
  mode: 'file',
21
+ showFiles: true,
19
22
  })
20
23
 
21
24
  const emit = defineEmits<{
@@ -30,9 +33,10 @@ const selectedFiles = ref<File[]>([])
30
33
  const folderName = ref<string | null>(null)
31
34
 
32
35
  const isFolder = computed(() => props.mode === 'folder')
36
+ const isMixed = computed(() => props.mode === 'file+folder')
33
37
 
34
38
  const acceptLabel = computed(() => {
35
- if (!props.accept) return 'any file'
39
+ if (!props.accept) return isFolder.value ? 'a folder' : 'any file'
36
40
  return props.accept.split(',').map(a => a.trim().replace('.', '').toUpperCase()).join(', ')
37
41
  })
38
42
 
@@ -154,15 +158,19 @@ function extractFolderName(files: File[]): string | null {
154
158
  return null
155
159
  }
156
160
 
157
- function handleDrop(event: DragEvent) {
161
+ async function handleDrop(event: DragEvent) {
158
162
  event.preventDefault()
159
163
  isDragOver.value = false
160
164
  if (props.disabled) return
161
165
 
162
- if (isFolder.value && event.dataTransfer?.items) {
163
- handleFolderDrop(event.dataTransfer.items)
164
- } else if (event.dataTransfer?.files) {
165
- handleFiles(event.dataTransfer.files)
166
+ try {
167
+ if (props.mode !== 'file' && event.dataTransfer?.items?.length) {
168
+ await handleFolderDrop(event.dataTransfer.items)
169
+ } else if (event.dataTransfer?.files) {
170
+ handleFiles(event.dataTransfer.files)
171
+ }
172
+ } catch (cause) {
173
+ emit('error', cause instanceof Error ? cause.message : 'Could not read the dropped folder.')
166
174
  }
167
175
  }
168
176
 
@@ -171,8 +179,12 @@ async function handleFolderDrop(items: DataTransferItemList) {
171
179
  const relativePaths: string[] = []
172
180
  let folderNameFromDrop: string | undefined
173
181
 
174
- for (const item of Array.from(items)) {
182
+ // Capture live drag data before awaiting: the browser protects it after the drop handler.
183
+ const dropped = Array.from(items, (item) => {
175
184
  const entry = item.webkitGetAsEntry?.()
185
+ return { entry, file: entry ? null : item.getAsFile?.() }
186
+ })
187
+ for (const { entry, file: droppedFile } of dropped) {
176
188
  if (entry?.isDirectory) {
177
189
  folderNameFromDrop = entry.name
178
190
  await readDirectory(
@@ -181,8 +193,10 @@ async function handleFolderDrop(items: DataTransferItemList) {
181
193
  relativePaths,
182
194
  entry.name,
183
195
  )
184
- } else if (entry?.isFile) {
185
- const file = await getFile(entry as FileSystemFileEntry)
196
+ } else {
197
+ const file = entry?.isFile
198
+ ? await getFile(entry as FileSystemFileEntry)
199
+ : droppedFile
186
200
  if (file) {
187
201
  files.push(file)
188
202
  relativePaths.push(file.name)
@@ -291,7 +305,11 @@ function formatFileSize(bytes: number): string {
291
305
  <div
292
306
  role="button"
293
307
  tabindex="0"
294
- :aria-label="disabled ? 'File upload disabled' : 'Click or drag files to upload'"
308
+ :aria-label="disabled
309
+ ? 'File upload disabled'
310
+ : isMixed
311
+ ? 'Drop files or a folder, or click to choose files'
312
+ : isFolder ? 'Click or drag a folder to upload' : 'Click or drag files to upload'"
295
313
  :aria-disabled="disabled"
296
314
  :class="[
297
315
  'mint-file-uploader__dropzone',
@@ -345,7 +363,7 @@ function formatFileSize(bytes: number): string {
345
363
  </svg>
346
364
 
347
365
  <p class="mint-file-uploader__text">
348
- Drop {{ acceptLabel }} or click
366
+ {{ isMixed ? 'Drop files or a folder, or click to choose files' : `Drop ${acceptLabel} or click` }}
349
367
  </p>
350
368
  </div>
351
369
  </div>
@@ -356,7 +374,7 @@ function formatFileSize(bytes: number): string {
356
374
  </div>
357
375
 
358
376
  <!-- Folder summary display -->
359
- <div v-if="isFolder && folderName && selectedFiles.length > 0" class="mint-file-uploader__folder-summary">
377
+ <div v-if="showFiles && isFolder && folderName && selectedFiles.length > 0" class="mint-file-uploader__folder-summary">
360
378
  <div class="mint-file-uploader__folder-info">
361
379
  <div class="mint-file-uploader__folder-icon-wrapper">
362
380
  <svg class="mint-file-uploader__folder-icon" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24">
@@ -382,7 +400,7 @@ function formatFileSize(bytes: number): string {
382
400
 
383
401
  <!-- File list display -->
384
402
  <TransitionGroup
385
- v-if="!isFolder && selectedFiles.length > 0"
403
+ v-if="showFiles && !isFolder && selectedFiles.length > 0"
386
404
  tag="ul"
387
405
  name="mint-file-uploader-item"
388
406
  class="mint-file-uploader__list"
@@ -418,7 +436,3 @@ function formatFileSize(bytes: number): string {
418
436
  </TransitionGroup>
419
437
  </div>
420
438
  </template>
421
-
422
- <style>
423
- @import '../styles/components/file-uploader.css';
424
- </style>
@@ -114,7 +114,3 @@ function variantClass(variant?: string): string {
114
114
  <slot name="footer" />
115
115
  </div>
116
116
  </template>
117
-
118
- <style>
119
- @import '../styles/components/fit-panel.css';
120
- </style>
@@ -0,0 +1,96 @@
1
+ <script setup lang="ts">
2
+ import FormActions from './FormActions.vue'
3
+
4
+ function log(event: string) {
5
+ return () => console.log(event)
6
+ }
7
+
8
+ function initState() {
9
+ return {
10
+ isWizard: false,
11
+ isFirst: true,
12
+ isLast: true,
13
+ canProceed: true,
14
+ loading: false,
15
+ disabled: false,
16
+ showCancel: true,
17
+ submitLabel: 'Submit',
18
+ cancelLabel: 'Cancel',
19
+ }
20
+ }
21
+ </script>
22
+
23
+ <template>
24
+ <Story title="Forms/FormActions">
25
+ <Variant title="Playground" :init-state="initState">
26
+ <template #default="{ state }">
27
+ <div style="padding: 2rem; max-width: 600px;">
28
+ <FormActions
29
+ :is-wizard="state.isWizard"
30
+ :is-first="state.isFirst"
31
+ :is-last="state.isLast"
32
+ :can-proceed="state.canProceed"
33
+ :loading="state.loading"
34
+ :disabled="state.disabled"
35
+ :show-cancel="state.showCancel"
36
+ :submit-label="state.submitLabel"
37
+ :cancel-label="state.cancelLabel"
38
+ @submit="log('submit')()"
39
+ @cancel="log('cancel')()"
40
+ @back="log('back')()"
41
+ @next="log('next')()"
42
+ />
43
+ </div>
44
+ </template>
45
+
46
+ <template #controls="{ state }">
47
+ <HstCheckbox v-model="state.isWizard" title="Wizard mode" />
48
+ <HstCheckbox v-model="state.isFirst" title="First step" />
49
+ <HstCheckbox v-model="state.isLast" title="Last step" />
50
+ <HstCheckbox v-model="state.canProceed" title="Can proceed" />
51
+ <HstCheckbox v-model="state.loading" title="Loading" />
52
+ <HstCheckbox v-model="state.disabled" title="Disabled" />
53
+ <HstCheckbox v-model="state.showCancel" title="Show cancel" />
54
+ <HstText v-model="state.submitLabel" title="Submit label" />
55
+ <HstText v-model="state.cancelLabel" title="Cancel label" />
56
+ </template>
57
+ </Variant>
58
+
59
+ <Variant title="Flat form">
60
+ <div style="padding: 2rem; max-width: 600px;">
61
+ <FormActions show-cancel submit-label="Save design" />
62
+ </div>
63
+ </Variant>
64
+
65
+ <Variant title="Wizard — first step">
66
+ <!-- Back is hidden on the first step; Next gates on `canProceed`. -->
67
+ <div style="padding: 2rem; max-width: 600px;">
68
+ <FormActions is-wizard :is-first="true" :is-last="false" />
69
+ </div>
70
+ </Variant>
71
+
72
+ <Variant title="Wizard — middle step">
73
+ <div style="padding: 2rem; max-width: 600px;">
74
+ <FormActions is-wizard :is-first="false" :is-last="false" />
75
+ </div>
76
+ </Variant>
77
+
78
+ <Variant title="Wizard — last step">
79
+ <div style="padding: 2rem; max-width: 600px;">
80
+ <FormActions is-wizard :is-first="false" :is-last="true" submit-label="Create experiment" />
81
+ </div>
82
+ </Variant>
83
+
84
+ <Variant title="Blocked by validation">
85
+ <div style="padding: 2rem; max-width: 600px;">
86
+ <FormActions is-wizard :is-first="false" :is-last="false" :can-proceed="false" />
87
+ </div>
88
+ </Variant>
89
+
90
+ <Variant title="Loading">
91
+ <div style="padding: 2rem; max-width: 600px;">
92
+ <FormActions show-cancel loading submit-label="Saving…" />
93
+ </div>
94
+ </Variant>
95
+ </Story>
96
+ </template>
@@ -86,7 +86,3 @@ const emit = defineEmits<{
86
86
  </BaseButton>
87
87
  </div>
88
88
  </template>
89
-
90
- <style>
91
- @import '../styles/components/form-builder.css';
92
- </style>
@@ -305,7 +305,3 @@ defineExpose({
305
305
  </template>
306
306
  </div>
307
307
  </template>
308
-
309
- <style>
310
- @import '../styles/components/form-builder.css';
311
- </style>
@@ -53,7 +53,3 @@ const describedBy = computed(() => errorId.value ?? hintId.value)
53
53
  </p>
54
54
  </div>
55
55
  </template>
56
-
57
- <style>
58
- @import '../styles/components/form-field.css';
59
- </style>
@@ -119,7 +119,3 @@ function handleInput(event: Event) {
119
119
  </div>
120
120
  </div>
121
121
  </template>
122
-
123
- <style>
124
- @import '../styles/components/formula-input.css';
125
- </style>
@@ -0,0 +1,68 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ import GeneratedPathInput from './GeneratedPathInput.vue'
4
+ import type { PluginJobPathInput } from '../types/generated-ui'
5
+
6
+ const single = ref<PluginJobPathInput | PluginJobPathInput[] | null>(null)
7
+ const multiple = ref<PluginJobPathInput | PluginJobPathInput[] | null>([])
8
+
9
+ function describe(value: PluginJobPathInput | PluginJobPathInput[] | null): string {
10
+ if (!value) return 'nothing selected'
11
+ const selections = Array.isArray(value) ? value : [value]
12
+ if (!selections.length) return 'nothing selected'
13
+ return selections
14
+ .map(selection => selection.rootName ?? selection.relativePaths.join(', '))
15
+ .join(' · ')
16
+ }
17
+
18
+ function initState() {
19
+ return {
20
+ multiple: false,
21
+ disabled: false,
22
+ }
23
+ }
24
+ </script>
25
+
26
+ <template>
27
+ <Story title="Forms/GeneratedPathInput">
28
+ <Variant title="Playground" :init-state="initState">
29
+ <template #default="{ state }">
30
+ <!-- Outside an integrated plugin the "Existing artifact" button is
31
+ hidden, so the story shows the file/folder modes only. -->
32
+ <div style="padding: 2rem; max-width: 600px;">
33
+ <GeneratedPathInput
34
+ v-model="single"
35
+ :multiple="state.multiple"
36
+ :disabled="state.disabled"
37
+ />
38
+ <p style="margin-top: 1rem; font-size: 0.8125rem; color: var(--text-secondary);">
39
+ Selection: <code>{{ describe(single) }}</code>
40
+ </p>
41
+ </div>
42
+ </template>
43
+
44
+ <template #controls="{ state }">
45
+ <HstCheckbox v-model="state.multiple" title="Allow multiple" />
46
+ <HstCheckbox v-model="state.disabled" title="Disabled" />
47
+ </template>
48
+ </Variant>
49
+
50
+ <Variant title="Single path">
51
+ <div style="padding: 2rem; max-width: 600px;">
52
+ <GeneratedPathInput v-model="single" />
53
+ </div>
54
+ </Variant>
55
+
56
+ <Variant title="Multiple paths">
57
+ <div style="padding: 2rem; max-width: 600px;">
58
+ <GeneratedPathInput v-model="multiple" multiple />
59
+ </div>
60
+ </Variant>
61
+
62
+ <Variant title="Disabled">
63
+ <div style="padding: 2rem; max-width: 600px;">
64
+ <GeneratedPathInput v-model="single" disabled />
65
+ </div>
66
+ </Variant>
67
+ </Story>
68
+ </template>