@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,7 +1,8 @@
1
1
  <script setup lang="ts">
2
2
  /** Avatar-triggered dropdown with user name/email header, configurable menu items, dividers, and a sign-out action. */
3
- import { computed } from 'vue'
3
+ import { computed, ref } from 'vue'
4
4
  import { useDropdownState } from '../composables/useDropdownState'
5
+ import { useMenuKeyboard } from '../composables/useMenuKeyboard'
5
6
  import type { AccountMenuItem } from '../types/components'
6
7
  import ActionItemInternal from './internal/ActionItemInternal.vue'
7
8
 
@@ -27,11 +28,25 @@ const emit = defineEmits<{
27
28
  'menu-close': []
28
29
  }>()
29
30
 
30
- const { isOpen, rootRef, close, toggle } = useDropdownState({
31
+ const { isOpen, rootRef, triggerRef, open, close, toggle } = useDropdownState({
31
32
  onOpen: () => emit('menu-open'),
32
33
  onClose: () => emit('menu-close'),
33
34
  })
34
35
 
36
+ const panelRef = ref<HTMLElement | null>(null)
37
+
38
+ function menuItems(): HTMLElement[] {
39
+ if (!panelRef.value) return []
40
+ return Array.from(panelRef.value.querySelectorAll<HTMLElement>('[role="menuitem"]'))
41
+ }
42
+
43
+ const { handleTriggerKeydown, handlePanelKeydown } = useMenuKeyboard({
44
+ items: menuItems,
45
+ isOpen: () => isOpen.value,
46
+ open,
47
+ close,
48
+ })
49
+
35
50
  const initials = computed(() => {
36
51
  if (props.userInitial) return props.userInitial.slice(0, 2).toUpperCase()
37
52
  if (props.userName) {
@@ -64,6 +79,7 @@ function handleSignOut() {
64
79
  <template>
65
80
  <div ref="rootRef" class="mint-avatar-menu">
66
81
  <button
82
+ ref="triggerRef"
67
83
  type="button"
68
84
  class="mint-avatar-menu__trigger"
69
85
  :class="{ 'mint-avatar-menu__trigger--open': isOpen }"
@@ -71,6 +87,7 @@ function handleSignOut() {
71
87
  aria-haspopup="menu"
72
88
  :title="userName ? `${userName} · Account menu` : 'Account menu'"
73
89
  @click.stop="toggle"
90
+ @keydown="handleTriggerKeydown"
74
91
  >
75
92
  <span class="mint-avatar-menu__avatar">
76
93
  <slot name="avatar" :initials="initials">
@@ -80,7 +97,13 @@ function handleSignOut() {
80
97
  <span v-if="userName" class="mint-avatar-menu__name">{{ userName }}</span>
81
98
  </button>
82
99
 
83
- <div v-if="isOpen" class="mint-avatar-menu__panel" role="menu">
100
+ <div
101
+ v-if="isOpen"
102
+ ref="panelRef"
103
+ class="mint-avatar-menu__panel"
104
+ role="menu"
105
+ @keydown="handlePanelKeydown"
106
+ >
84
107
  <div v-if="userName || userEmail" class="mint-avatar-menu__header">
85
108
  <div v-if="userName" class="mint-avatar-menu__user-name">{{ userName }}</div>
86
109
  <div v-if="userEmail" class="mint-avatar-menu__user-email">{{ userEmail }}</div>
@@ -127,7 +150,3 @@ function handleSignOut() {
127
150
  </div>
128
151
  </div>
129
152
  </template>
130
-
131
- <style>
132
- @import '../styles/components/app-avatar-menu.css';
133
- </style>
@@ -150,7 +150,3 @@ function closeSidebar() {
150
150
  </div>
151
151
  </div>
152
152
  </template>
153
-
154
- <style>
155
- @import '../styles/components/app-layout.css';
156
- </style>
@@ -0,0 +1,87 @@
1
+ <script setup lang="ts">
2
+ import AppPluginSwitcher from './AppPluginSwitcher.vue'
3
+ import type { PluginSwitcherPlugin } from '../types/components'
4
+
5
+ const current: PluginSwitcherPlugin = {
6
+ id: 'ms-designer',
7
+ label: 'MS Designer',
8
+ version: '1.4.2',
9
+ color: 'var(--mint-sample-1)',
10
+ }
11
+
12
+ const plugins: PluginSwitcherPlugin[] = [
13
+ { id: 'ms-designer', label: 'MS Designer', version: '1.4.2', color: 'var(--mint-sample-1)' },
14
+ { id: 'ms-uploader', label: 'MS Uploader', version: '0.9.0', color: 'var(--mint-sample-2)' },
15
+ { id: 'ms-planner', label: 'MS Planner', version: '2.0.1', color: 'var(--mint-sample-5)' },
16
+ { id: 'drp', label: 'Dose Response', version: '3.1.0', color: 'var(--mint-sample-6)' },
17
+ ]
18
+
19
+ function handleSelect(plugin: PluginSwitcherPlugin) {
20
+ console.log('Switch to', plugin.id)
21
+ }
22
+
23
+ function handleInstall() {
24
+ console.log('Install plugin clicked')
25
+ }
26
+
27
+ function initState() {
28
+ return {
29
+ label: 'MS Designer',
30
+ version: '1.4.2',
31
+ installLabel: 'Install plugin…',
32
+ }
33
+ }
34
+ </script>
35
+
36
+ <template>
37
+ <Story title="Layout/AppPluginSwitcher">
38
+ <Variant title="Playground" :init-state="initState">
39
+ <template #default="{ state }">
40
+ <div style="padding: 2rem; max-width: 600px; min-height: 22rem; background: var(--bg-primary);">
41
+ <AppPluginSwitcher
42
+ :current="{ id: 'active', label: state.label, version: state.version }"
43
+ :plugins="plugins"
44
+ :install-label="state.installLabel"
45
+ install-href="#install"
46
+ @select="handleSelect"
47
+ @install-click="handleInstall"
48
+ />
49
+ </div>
50
+ </template>
51
+
52
+ <template #controls="{ state }">
53
+ <HstText v-model="state.label" title="Current label" />
54
+ <HstText v-model="state.version" title="Current version" />
55
+ <HstText v-model="state.installLabel" title="Install label" />
56
+ </template>
57
+ </Variant>
58
+
59
+ <Variant title="Closed (top-bar placement)">
60
+ <div style="padding: 2rem; max-width: 600px; background: var(--bg-primary);">
61
+ <AppPluginSwitcher :current="current" :plugins="plugins" @select="handleSelect" />
62
+ </div>
63
+ </Variant>
64
+
65
+ <Variant title="Single plugin (no siblings)">
66
+ <!-- The menu still opens so the install affordance stays reachable. -->
67
+ <div style="padding: 2rem; max-width: 600px; min-height: 16rem; background: var(--bg-primary);">
68
+ <AppPluginSwitcher
69
+ :current="current"
70
+ :plugins="[current]"
71
+ install-href="#install"
72
+ @install-click="handleInstall"
73
+ />
74
+ </div>
75
+ </Variant>
76
+
77
+ <Variant title="Without version badge">
78
+ <div style="padding: 2rem; max-width: 600px; background: var(--bg-primary);">
79
+ <AppPluginSwitcher
80
+ :current="{ id: 'hmdb', label: 'HMDB Lookup' }"
81
+ :plugins="plugins"
82
+ @select="handleSelect"
83
+ />
84
+ </div>
85
+ </Variant>
86
+ </Story>
87
+ </template>
@@ -22,7 +22,7 @@ const emit = defineEmits<{
22
22
  'install-click': []
23
23
  }>()
24
24
 
25
- const { isOpen, rootRef, close, toggle } = useDropdownState()
25
+ const { isOpen, rootRef, triggerRef, close, toggle } = useDropdownState()
26
26
 
27
27
  function initialsOf(plugin: PluginSwitcherPlugin) {
28
28
  const label = plugin.label || plugin.id
@@ -47,6 +47,7 @@ function handleInstall() {
47
47
  <template>
48
48
  <div ref="rootRef" class="mint-plugin-switcher">
49
49
  <button
50
+ ref="triggerRef"
50
51
  type="button"
51
52
  class="mint-plugin-switcher__trigger"
52
53
  :class="{ 'mint-plugin-switcher__trigger--open': isOpen }"
@@ -131,7 +132,3 @@ function handleInstall() {
131
132
  </div>
132
133
  </div>
133
134
  </template>
134
-
135
- <style>
136
- @import '../styles/components/app-plugin-switcher.css';
137
- </style>
@@ -465,7 +465,3 @@ function firstVisibleViewId(panels: Record<string, SidebarToolSection[]>): strin
465
465
  </div>
466
466
  </aside>
467
467
  </template>
468
-
469
- <style>
470
- @import '../styles/components/app-sidebar.css';
471
- </style>
@@ -5,11 +5,13 @@ import type { Toast } from '../types'
5
5
 
6
6
  const { toasts, dismiss } = useToast()
7
7
 
8
+ // Semantic accents come from the shared tokens rather than a fourth copy of
9
+ // the same four hexes.
8
10
  const accentColors: Record<Toast['type'], string> = {
9
- success: '#10B981',
10
- error: '#EF4444',
11
- warning: '#F59E0B',
12
- info: '#3B82F6',
11
+ success: 'var(--mint-success)',
12
+ error: 'var(--mint-error)',
13
+ warning: 'var(--mint-warning)',
14
+ info: 'var(--mint-info)',
13
15
  }
14
16
  </script>
15
17
 
@@ -56,7 +58,3 @@ const accentColors: Record<Toast['type'], string> = {
56
58
  </div>
57
59
  </Teleport>
58
60
  </template>
59
-
60
- <style>
61
- @import '../styles/components/toast.css';
62
- </style>
@@ -468,7 +468,3 @@ const effectiveCurrentPageSelectorId = computed(() =>
468
468
  @update:model-value="$event ? appExperiment.openModal() : appExperiment.closeModal()"
469
469
  />
470
470
  </template>
471
-
472
- <style>
473
- @import '../styles/components/app-top-bar.css';
474
- </style>
@@ -428,7 +428,3 @@ function handleCancel(): void {
428
428
  </template>
429
429
  </BaseModal>
430
430
  </template>
431
-
432
- <style>
433
- @import '../styles/components/artifact-save-dialog.css';
434
- </style>
@@ -327,7 +327,3 @@ watch(
327
327
  </div>
328
328
  </BaseModal>
329
329
  </template>
330
-
331
- <style>
332
- @import '../styles/components/artifact-selector-modal.css';
333
- </style>
@@ -78,6 +78,8 @@ const mockEntries = [
78
78
 
79
79
  function initState() {
80
80
  return {
81
+ loading: false,
82
+ error: '',
81
83
  entries: mockEntries,
82
84
  showFilters: false,
83
85
  emptyMessage: 'No activity yet',
@@ -93,6 +95,8 @@ function initState() {
93
95
  <template #default="{ state }">
94
96
  <div style="padding: 2rem; max-width: 600px;">
95
97
  <AuditTrail
98
+ :loading="state.loading"
99
+ :error="state.error || null"
96
100
  :entries="state.entries"
97
101
  :show-filters="state.showFilters"
98
102
  :empty-message="state.emptyMessage"
@@ -102,6 +106,8 @@ function initState() {
102
106
  </div>
103
107
  </template>
104
108
  <template #controls="{ state }">
109
+ <HstCheckbox v-model="state.loading" title="Loading" />
110
+ <HstText v-model="state.error" title="Error Message" />
105
111
  <HstCheckbox v-model="state.showFilters" title="Show Filters" />
106
112
  <HstText v-model="state.emptyMessage" title="Empty Message" />
107
113
  <HstSelect
@@ -159,5 +165,17 @@ function initState() {
159
165
  />
160
166
  </div>
161
167
  </Variant>
168
+
169
+ <Variant title="Loading">
170
+ <div style="padding: 2rem; max-width: 600px;">
171
+ <AuditTrail :entries="[]" loading />
172
+ </div>
173
+ </Variant>
174
+
175
+ <Variant title="Error">
176
+ <div style="padding: 2rem; max-width: 600px;">
177
+ <AuditTrail :entries="[]" error="Could not load the audit trail." />
178
+ </div>
179
+ </Variant>
162
180
  </Story>
163
181
  </template>
@@ -2,6 +2,7 @@
2
2
  /** Filterable, sortable timeline of audit entries for tracking experiment or resource history. */
3
3
  import { computed, ref } from 'vue'
4
4
  import type { AuditEntryType, AuditEntry } from '../types'
5
+ import DataStateInternal from './internal/DataStateInternal.vue'
5
6
 
6
7
  interface Props {
7
8
  entries: AuditEntry[]
@@ -10,6 +11,13 @@ interface Props {
10
11
  emptyMessage?: string
11
12
  order?: 'newest' | 'oldest'
12
13
  size?: 'sm' | 'md' | 'lg'
14
+ /** Replace the timeline with a loading placeholder. */
15
+ loading?: boolean
16
+ /**
17
+ * Error message. When set, the timeline is replaced by an error state.
18
+ * `null`/`undefined` renders normally.
19
+ */
20
+ error?: string | null
13
21
  }
14
22
 
15
23
  const props = withDefaults(defineProps<Props>(), {
@@ -17,6 +25,8 @@ const props = withDefaults(defineProps<Props>(), {
17
25
  emptyMessage: 'No activity yet',
18
26
  order: 'newest',
19
27
  size: 'md',
28
+ loading: false,
29
+ error: null,
20
30
  })
21
31
 
22
32
  const emit = defineEmits<{
@@ -104,7 +114,7 @@ function handleEntryClick(entry: AuditEntry) {
104
114
  </div>
105
115
 
106
116
  <div
107
- v-if="sortedEntries.length"
117
+ v-if="!loading && !error && sortedEntries.length"
108
118
  class="mint-audit-trail__list"
109
119
  :style="maxHeight ? { maxHeight, overflowY: 'auto' } : {}"
110
120
  >
@@ -140,12 +150,22 @@ function handleEntryClick(entry: AuditEntry) {
140
150
  </div>
141
151
  </div>
142
152
 
143
- <div v-if="!sortedEntries.length" class="mint-audit-trail__empty">
144
- <slot name="empty">{{ emptyMessage }}</slot>
153
+ <div v-if="error" class="mint-audit-trail__state">
154
+ <slot name="error" :error="error">
155
+ <DataStateInternal state="error" size="sm" :title="error" />
156
+ </slot>
157
+ </div>
158
+
159
+ <div v-else-if="loading" class="mint-audit-trail__state">
160
+ <slot name="loading">
161
+ <DataStateInternal state="loading" size="sm" loading-label="Loading activity" />
162
+ </slot>
163
+ </div>
164
+
165
+ <div v-else-if="!sortedEntries.length" class="mint-audit-trail__state">
166
+ <slot name="empty">
167
+ <DataStateInternal state="empty" size="sm" :title="emptyMessage" />
168
+ </slot>
145
169
  </div>
146
170
  </div>
147
171
  </template>
148
-
149
- <style>
150
- @import '../styles/components/audit-trail.css';
151
- </style>
@@ -288,7 +288,3 @@ watch(
288
288
  />
289
289
  </BaseModal>
290
290
  </template>
291
-
292
- <style>
293
- @import '../styles/components/smart-group.css';
294
- </style>
@@ -73,7 +73,3 @@ const backgroundColor = computed(() => {
73
73
  />
74
74
  </span>
75
75
  </template>
76
-
77
- <style>
78
- @import '../styles/components/avatar.css';
79
- </style>
@@ -69,7 +69,3 @@ function handleClick(event: MouseEvent) {
69
69
  <slot name="icon-right" />
70
70
  </button>
71
71
  </template>
72
-
73
- <style>
74
- @import '../styles/components/button.css';
75
- </style>
@@ -125,7 +125,3 @@ function iconStyle(): Record<string, string> {
125
125
  </span>
126
126
  </label>
127
127
  </template>
128
-
129
- <style>
130
- @import '../styles/components/checkbox.css';
131
- </style>
@@ -70,7 +70,3 @@ function handleInput(event: Event) {
70
70
  @keydown="emit('keydown', $event)"
71
71
  />
72
72
  </template>
73
-
74
- <style>
75
- @import '../styles/components/input.css';
76
- </style>
@@ -1,8 +1,9 @@
1
1
  <script setup lang="ts">
2
2
  /** Modal dialog with backdrop, focus trap, Escape-to-close, and configurable size/variant/layout. */
3
- import { computed, ref, watch, nextTick, onUnmounted, type ComponentPublicInstance } from 'vue'
3
+ import { computed, ref, toRef, watch, onUnmounted, type ComponentPublicInstance } from 'vue'
4
4
  import type { ModalLayout, ModalSize, ModalTab, ModalVariant } from '../types'
5
5
  import { useEventListener } from '../composables/useEventListener'
6
+ import { useFocusTrap } from '../composables/useFocusTrap'
6
7
 
7
8
  interface Props {
8
9
  modelValue: boolean
@@ -75,47 +76,16 @@ function isPathIcon(icon: ModalTab['icon']): icon is string | string[] {
75
76
  }
76
77
 
77
78
  const containerRef = ref<HTMLElement | null>(null)
78
- let previouslyFocused: HTMLElement | null = null
79
79
 
80
- const FOCUSABLE_SELECTOR = [
81
- 'a[href]',
82
- 'button:not([disabled])',
83
- 'input:not([disabled])',
84
- 'select:not([disabled])',
85
- 'textarea:not([disabled])',
86
- '[tabindex]:not([tabindex="-1"])',
87
- ].join(', ')
80
+ useFocusTrap({ containerRef, active: toRef(props, 'modelValue') })
88
81
 
89
- function getFocusableElements(): HTMLElement[] {
90
- if (!containerRef.value) return []
91
- return Array.from(containerRef.value.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR))
92
- // Roving tabindex (inactive tabs/rail items) stays out of the Tab cycle.
93
- .filter((el) => el.tabIndex !== -1)
94
- }
82
+ watch(() => props.modelValue, (isOpen) => {
83
+ document.body.style.overflow = isOpen ? 'hidden' : ''
84
+ })
95
85
 
96
- function handleKeydown(event: KeyboardEvent) {
86
+ function handleEscapeKeydown(event: KeyboardEvent) {
97
87
  if (event.key === 'Escape' && props.closeOnEscape && props.modelValue) {
98
88
  close()
99
- return
100
- }
101
-
102
- if (event.key !== 'Tab' || !containerRef.value) return
103
-
104
- const focusable = getFocusableElements()
105
- if (focusable.length === 0) {
106
- event.preventDefault()
107
- return
108
- }
109
-
110
- const first = focusable[0]
111
- const last = focusable[focusable.length - 1]
112
-
113
- if (event.shiftKey && document.activeElement === first) {
114
- event.preventDefault()
115
- last.focus()
116
- } else if (!event.shiftKey && document.activeElement === last) {
117
- event.preventDefault()
118
- first.focus()
119
89
  }
120
90
  }
121
91
 
@@ -132,25 +102,7 @@ function handleOverlayClick(event: MouseEvent) {
132
102
  }
133
103
  }
134
104
 
135
- watch(() => props.modelValue, async (isOpen) => {
136
- if (isOpen) {
137
- previouslyFocused = document.activeElement as HTMLElement | null
138
- document.body.style.overflow = 'hidden'
139
- await nextTick()
140
- const focusable = getFocusableElements()
141
- if (focusable.length > 0) {
142
- focusable[0].focus()
143
- } else {
144
- containerRef.value?.focus()
145
- }
146
- } else {
147
- document.body.style.overflow = ''
148
- previouslyFocused?.focus()
149
- previouslyFocused = null
150
- }
151
- })
152
-
153
- useEventListener(() => document, 'keydown', handleKeydown)
105
+ useEventListener(() => document, 'keydown', handleEscapeKeydown)
154
106
 
155
107
  onUnmounted(() => {
156
108
  document.body.style.overflow = ''
@@ -322,7 +274,3 @@ onUnmounted(() => {
322
274
  </Transition>
323
275
  </Teleport>
324
276
  </template>
325
-
326
- <style>
327
- @import '../styles/components/modal.css';
328
- </style>
@@ -83,7 +83,3 @@ function handleRemove(event: MouseEvent) {
83
83
  </button>
84
84
  </span>
85
85
  </template>
86
-
87
- <style>
88
- @import '../styles/components/pill.css';
89
- </style>
@@ -122,7 +122,3 @@ function handleChange(value: string | number) {
122
122
  </label>
123
123
  </div>
124
124
  </template>
125
-
126
- <style>
127
- @import '../styles/components/radio-group.css';
128
- </style>
@@ -83,7 +83,3 @@ function handleChange(event: Event) {
83
83
  </div>
84
84
  </div>
85
85
  </template>
86
-
87
- <style>
88
- @import '../styles/components/select.css';
89
- </style>
@@ -120,7 +120,3 @@ function handleInput(event: Event) {
120
120
  </span>
121
121
  </div>
122
122
  </template>
123
-
124
- <style>
125
- @import '../styles/components/slider.css';
126
- </style>
@@ -1,8 +1,9 @@
1
1
  <script setup lang="ts">
2
2
  /** Renders a tab bar with underline or pills variant, badges, icons, and disabled tab support. */
3
- import { computed } from 'vue'
3
+ import { computed, type ComponentPublicInstance } from 'vue'
4
4
  import type { TabItem, TabItemInput } from '../types'
5
5
  import { normalizeItemInput } from '../utils/items'
6
+ import { useRovingFocus } from '../composables/useRovingFocus'
6
7
 
7
8
  interface Props {
8
9
  modelValue: string
@@ -32,23 +33,47 @@ function selectTab(tabId: string) {
32
33
  emit('update:modelValue', tabId)
33
34
  }
34
35
  }
36
+
37
+ const tabButtonRefs = new Map<string, HTMLElement>()
38
+
39
+ function setTabButtonRef(id: string, el: Element | ComponentPublicInstance | null) {
40
+ if (el instanceof HTMLElement) {
41
+ tabButtonRefs.set(id, el)
42
+ } else {
43
+ tabButtonRefs.delete(id)
44
+ }
45
+ }
46
+
47
+ // Left/Right only — BaseTabs renders a single horizontal strip with no vertical
48
+ // variant, so there is no Up/Down axis to support.
49
+ const { handleKeydown } = useRovingFocus({
50
+ ids: () => normalizedTabs.value.filter(tab => !tab.disabled).map(tab => tab.id),
51
+ activeId: () => activeTab.value,
52
+ activate: selectTab,
53
+ getElement: (id) => tabButtonRefs.get(id),
54
+ })
35
55
  </script>
36
56
 
37
57
  <template>
38
58
  <div :class="['mint-tabs', `mint-tabs--${variant}`]" role="tablist">
39
59
  <button
40
60
  v-for="tab in normalizedTabs"
61
+ :id="`mint-tab-${tab.id}`"
41
62
  :key="tab.id"
63
+ :ref="(el) => setTabButtonRef(tab.id, el)"
42
64
  type="button"
43
65
  role="tab"
44
66
  :aria-selected="activeTab === tab.id"
45
67
  :aria-disabled="tab.disabled"
68
+ :aria-controls="`mint-tabpanel-${tab.id}`"
69
+ :tabindex="activeTab === tab.id ? 0 : -1"
46
70
  :class="[
47
71
  'mint-tab',
48
72
  activeTab === tab.id ? 'mint-tab--active' : '',
49
73
  tab.disabled ? 'mint-tab--disabled' : '',
50
74
  ]"
51
75
  @click="selectTab(tab.id)"
76
+ @keydown="handleKeydown"
52
77
  >
53
78
  <span class="mint-tab__content">
54
79
  <svg
@@ -76,7 +101,3 @@ function selectTab(tabId: string) {
76
101
  </button>
77
102
  </div>
78
103
  </template>
79
-
80
- <style>
81
- @import '../styles/components/tabs.css';
82
- </style>
@@ -56,7 +56,3 @@ function handleInput(event: Event) {
56
56
  @blur="emit('blur', $event)"
57
57
  />
58
58
  </template>
59
-
60
- <style>
61
- @import '../styles/components/textarea.css';
62
- </style>
@@ -137,7 +137,3 @@ function iconStyle(): Record<string, string> {
137
137
  </span>
138
138
  </div>
139
139
  </template>
140
-
141
- <style>
142
- @import '../styles/components/toggle.css';
143
- </style>