@morscherlab/mint-sdk 1.4.0-beta.8 → 1.4.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 (353) hide show
  1. package/README.md +14 -3
  2. package/dist/{ActionMenu-CScINahU.js → AlertBox-DwgNTEqf.js} +40 -209
  3. package/dist/AlertBox-DwgNTEqf.js.map +1 -0
  4. package/dist/{AppSidebar-BmiiPfz9.js → AppSidebar-CZZaxni0.js} +1249 -239
  5. package/dist/AppSidebar-CZZaxni0.js.map +1 -0
  6. package/dist/{ConfirmDialog-CJ7hqYUP.js → ConfirmDialog-CjWoxAD1.js} +2 -2
  7. package/dist/{ConfirmDialog-CJ7hqYUP.js.map → ConfirmDialog-CjWoxAD1.js.map} +1 -1
  8. package/dist/ExperimentPopover-DujiuQIO.js +337 -0
  9. package/dist/ExperimentPopover-DujiuQIO.js.map +1 -0
  10. package/dist/{ExperimentSelectorModal-D-9z7cNx.js → ExperimentSelectorModal-B4j4eUOJ.js} +244 -211
  11. package/dist/ExperimentSelectorModal-B4j4eUOJ.js.map +1 -0
  12. package/dist/{SegmentedControl-DERBN-Xd.js → SegmentedControl-DyUPH3I5.js} +2 -2
  13. package/dist/{SegmentedControl-DERBN-Xd.js.map → SegmentedControl-DyUPH3I5.js.map} +1 -1
  14. package/dist/{SettingsModal-CSLE31yg.js → SettingsModal-D2MOOtuO.js} +28 -27
  15. package/dist/SettingsModal-D2MOOtuO.js.map +1 -0
  16. package/dist/__stories__/experiment-helpers.d.ts +10 -0
  17. package/dist/__tests__/components/AppTopBarOnboarding.test.d.ts +1 -0
  18. package/dist/__tests__/components/FloatingPanelsInModal.test.d.ts +1 -0
  19. package/dist/__tests__/composables/useFloatingPanel.test.d.ts +1 -0
  20. package/dist/__tests__/composables/useOnboarding.test.d.ts +1 -0
  21. package/dist/__tests__/styles/paletteTokens.test.d.ts +1 -0
  22. package/dist/__tests__/styles/v2AuditRules.test.d.ts +1 -0
  23. package/dist/components/AppSidebar.vue.d.ts +1 -1
  24. package/dist/components/AppTopBar.vue.d.ts +20 -5
  25. package/dist/components/ArtifactSaveDialog.vue.d.ts +9 -1
  26. package/dist/components/AuditTrail.vue.d.ts +1 -1
  27. package/dist/components/BaseButton.vue.d.ts +4 -2
  28. package/dist/components/BaseSelect.vue.d.ts +2 -2
  29. package/dist/components/ChartContainer.vue.d.ts +2 -0
  30. package/dist/components/DatePicker.vue.d.ts +1 -1
  31. package/dist/components/ExperimentPopover.vue.d.ts +18 -0
  32. package/dist/components/ExperimentSelectorModal.vue.d.ts +15 -5
  33. package/dist/components/FilePicker.vue.d.ts +1 -1
  34. package/dist/components/FileUploader.vue.d.ts +2 -2
  35. package/dist/components/JobsStatusTray.vue.d.ts +15 -4
  36. package/dist/components/PluginIcon.vue.d.ts +2 -2
  37. package/dist/components/PluginWorkspaceView.props.d.ts +3 -0
  38. package/dist/components/PluginWorkspaceView.vue.d.ts +3 -0
  39. package/dist/components/SampleSelector.vue.d.ts +6 -6
  40. package/dist/components/SequenceProgressBar.vue.d.ts +3 -0
  41. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +3 -3
  42. package/dist/components/StepWizard.vue.d.ts +3 -0
  43. package/dist/components/internal/AppTopBarOnboardingInternal.vue.d.ts +7 -0
  44. package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -1
  45. package/dist/components/internal/AutoGroupModalInternal.vue.d.ts +3 -3
  46. package/dist/components/internal/DatePickerTimeInternal.vue.d.ts +1 -1
  47. package/dist/components/internal/OnboardingLayerInternal.vue.d.ts +7 -0
  48. package/dist/components/internal/ResourcePickerListInternal.vue.d.ts +2 -7
  49. package/dist/components/internal/SelectMultipleInternal.vue.d.ts +4 -0
  50. package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +8 -0
  51. package/dist/composables/createClient.d.ts +2 -0
  52. package/dist/composables/index.d.ts +1 -0
  53. package/dist/composables/pluginIdentity.d.ts +24 -0
  54. package/dist/composables/pluginWorkspaceModel.d.ts +2 -2
  55. package/dist/composables/useAppExperiment.d.ts +8 -0
  56. package/dist/composables/useCalendarGrid.d.ts +1 -1
  57. package/dist/composables/useExperimentSelector.d.ts +6 -2
  58. package/dist/composables/useFileImport.d.ts +7 -0
  59. package/dist/composables/useFloatingPanel.d.ts +29 -0
  60. package/dist/composables/useJobCenter.d.ts +41 -3
  61. package/dist/composables/useOnboarding.d.ts +119 -0
  62. package/dist/composables/usePlatform.d.ts +1 -0
  63. package/dist/{controlSchemaModel-CP5-_nAj.js → controlSchemaModel-Bsg0t5Ab.js} +2 -2
  64. package/dist/{controlSchemaModel-CP5-_nAj.js.map → controlSchemaModel-Bsg0t5Ab.js.map} +1 -1
  65. package/dist/{data-C2PwI_dn.js → data-Boeh4uPI.js} +180 -125
  66. package/dist/data-Boeh4uPI.js.map +1 -0
  67. package/dist/data.d.ts +1 -1
  68. package/dist/data.js +9 -9
  69. package/dist/{experiment-43OJtH7R.js → experiment-DyO54FQB.js} +25 -61
  70. package/dist/experiment-DyO54FQB.js.map +1 -0
  71. package/dist/{experimentStatus-BZmU4czV.js → experimentStatus-DCn2QKG7.js} +3 -3
  72. package/dist/{experimentStatus-BZmU4czV.js.map → experimentStatus-DCn2QKG7.js.map} +1 -1
  73. package/dist/index.js +20 -20
  74. package/dist/{install-DAID6c2-.js → install-BEHp7Mo-.js} +15 -14
  75. package/dist/{install-DAID6c2-.js.map → install-BEHp7Mo-.js.map} +1 -1
  76. package/dist/install.js +1 -1
  77. package/dist/{lab-DLwRl_Ql.js → lab-D61eaX6f.js} +136 -148
  78. package/dist/lab-D61eaX6f.js.map +1 -0
  79. package/dist/lab.js +4 -3
  80. package/dist/{records-BzTcxekG.js → records-D4aQXyZu.js} +647 -389
  81. package/dist/records-D4aQXyZu.js.map +1 -0
  82. package/dist/{runtime-D6gVat6r.js → runtime-q-R0CNLh.js} +417 -54
  83. package/dist/runtime-q-R0CNLh.js.map +1 -0
  84. package/dist/runtime.d.ts +1 -1
  85. package/dist/runtime.js +7 -7
  86. package/dist/{shell-5ju97nOS.js → shell-6CGFvUUw.js} +10 -5
  87. package/dist/{shell-5ju97nOS.js.map → shell-6CGFvUUw.js.map} +1 -1
  88. package/dist/shell.d.ts +1 -0
  89. package/dist/shell.js +6 -6
  90. package/dist/stores/index.d.ts +1 -1
  91. package/dist/stores/index.js +2 -2
  92. package/dist/stores/settings.d.ts +4 -12
  93. package/dist/styles.css +2753 -2101
  94. package/dist/types/componentWorkflowTypes.d.ts +2 -0
  95. package/dist/types/components.d.ts +2 -0
  96. package/dist/types/generated/platformContext.d.ts +1 -0
  97. package/dist/types/generated-ui.d.ts +4 -0
  98. package/dist/types/index.d.ts +1 -1
  99. package/dist/types/jobs.d.ts +9 -0
  100. package/dist/types/platform.d.ts +1 -1
  101. package/dist/{BaseModal-DfRIuVoj.js → useDropdownState-uFIz6Yv8.js} +75 -5
  102. package/dist/useDropdownState-uFIz6Yv8.js.map +1 -0
  103. package/dist/{useExperimentSamples-CxcnxZ8h.js → useExperimentSamples-QEFoq4tf.js} +48 -6
  104. package/dist/useExperimentSamples-QEFoq4tf.js.map +1 -0
  105. package/dist/{useListReorder-CcbEYxX-.js → useListReorder-DsuzwWGS.js} +219 -437
  106. package/dist/useListReorder-DsuzwWGS.js.map +1 -0
  107. package/dist/{useRackEditor-BD5NIo5s.js → useRackEditor-KpZ4iJ6o.js} +85 -81
  108. package/dist/useRackEditor-KpZ4iJ6o.js.map +1 -0
  109. package/dist/useRealtime-B58Lo-Tm.js +508 -0
  110. package/dist/useRealtime-B58Lo-Tm.js.map +1 -0
  111. package/dist/useRequest-BuDmW8Jc.js +215 -0
  112. package/dist/useRequest-BuDmW8Jc.js.map +1 -0
  113. package/dist/utils/time.d.ts +7 -0
  114. package/package.json +3 -2
  115. package/src/__stories__/experiment-helpers.ts +3 -3
  116. package/src/__tests__/components/ActionMenu.test.ts +2 -2
  117. package/src/__tests__/components/AppTopBar.test.ts +257 -3
  118. package/src/__tests__/components/AppTopBarOnboarding.test.ts +160 -0
  119. package/src/__tests__/components/AppTopBarPageSelector.test.ts +125 -9
  120. package/src/__tests__/components/AppTopBarPillNav.test.ts +35 -0
  121. package/src/__tests__/components/ArtifactSaveDialog.test.ts +78 -0
  122. package/src/__tests__/components/BaseButton.test.ts +19 -0
  123. package/src/__tests__/components/BaseModal.test.ts +13 -0
  124. package/src/__tests__/components/BaseSelect.multiple.test.ts +87 -32
  125. package/src/__tests__/components/BaseSelect.test.ts +2 -1
  126. package/src/__tests__/components/BatchProgressList.test.ts +16 -0
  127. package/src/__tests__/components/CalendarGridPanel.test.ts +2 -2
  128. package/src/__tests__/components/ChartContainer.test.ts +11 -0
  129. package/src/__tests__/components/ChemicalFormula.test.ts +6 -3
  130. package/src/__tests__/components/DatePicker.datetime.test.ts +6 -0
  131. package/src/__tests__/components/DatePicker.test.ts +21 -0
  132. package/src/__tests__/components/DatePicker.time.test.ts +2 -2
  133. package/src/__tests__/components/EmptyState.test.ts +1 -1
  134. package/src/__tests__/components/ExperimentPopover.test.ts +125 -16
  135. package/src/__tests__/components/ExperimentSelectorModal.test.ts +153 -14
  136. package/src/__tests__/components/FloatingPanelsInModal.test.ts +94 -0
  137. package/src/__tests__/components/GeneratedPluginView.test.ts +23 -2
  138. package/src/__tests__/components/InstrumentStateBadge.test.ts +4 -4
  139. package/src/__tests__/components/JobsStatusTray.test.ts +373 -71
  140. package/src/__tests__/components/PluginWorkspaceView.test.ts +63 -1
  141. package/src/__tests__/components/ResourcePickerListInternal.test.ts +0 -20
  142. package/src/__tests__/components/SampleSelector.test.ts +33 -8
  143. package/src/__tests__/components/SequenceProgressBar.test.ts +12 -0
  144. package/src/__tests__/components/SettingsModal.test.ts +9 -2
  145. package/src/__tests__/components/StepWizard.test.ts +11 -0
  146. package/src/__tests__/components/WellPlate.decoration.test.ts +11 -4
  147. package/src/__tests__/components/deprecationTags.test.ts +1 -1
  148. package/src/__tests__/composables/useAppExperiment.test.ts +27 -1
  149. package/src/__tests__/composables/useCalendarGrid.test.ts +4 -2
  150. package/src/__tests__/composables/useExperimentSelector.test.ts +111 -0
  151. package/src/__tests__/composables/useFileImport.test.ts +36 -0
  152. package/src/__tests__/composables/useFloatingPanel.test.ts +68 -0
  153. package/src/__tests__/composables/useJobCenter.test.ts +262 -3
  154. package/src/__tests__/composables/useOnboarding.test.ts +317 -0
  155. package/src/__tests__/docs/frontendDocsCatalog.test.ts +4 -3
  156. package/src/__tests__/fixtures/table-import/cells.xlsx +0 -0
  157. package/src/__tests__/fixtures/table-import/samples.xlsx +0 -0
  158. package/src/__tests__/stores/settings.test.ts +21 -21
  159. package/src/__tests__/styles/baseControlsRules.test.ts +6 -2
  160. package/src/__tests__/styles/controlRefreshRules.test.ts +0 -6
  161. package/src/__tests__/styles/cssTokens.test.ts +6 -3
  162. package/src/__tests__/styles/menusShellRefresh.test.ts +22 -12
  163. package/src/__tests__/styles/paletteTokens.test.ts +44 -0
  164. package/src/__tests__/styles/v2AuditRules.test.ts +104 -0
  165. package/src/__tests__/utils/plotlyTemplate.test.ts +4 -4
  166. package/src/__tests__/utils/time.test.ts +18 -1
  167. package/src/components/ActionMenu.vue +6 -37
  168. package/src/components/AdductText.story.vue +7 -0
  169. package/src/components/AdductText.vue +1 -1
  170. package/src/components/AlertBox.story.vue +2 -2
  171. package/src/components/AlertBox.vue +18 -16
  172. package/src/components/AppSidebar.story.vue +0 -28
  173. package/src/components/AppTopBar.onboarding.story.vue +69 -0
  174. package/src/components/AppTopBar.story.vue +105 -15
  175. package/src/components/AppTopBar.vue +248 -122
  176. package/src/components/ArtifactSaveDialog.story.vue +23 -0
  177. package/src/components/ArtifactSaveDialog.vue +102 -12
  178. package/src/components/AuditTrail.story.vue +2 -1
  179. package/src/components/AuditTrail.vue +2 -21
  180. package/src/components/Avatar.vue +10 -14
  181. package/src/components/BaseButton.vue +16 -2
  182. package/src/components/BaseModal.vue +2 -1
  183. package/src/components/BaseSelect.multiple.story.vue +13 -2
  184. package/src/components/BaseSelect.vue +4 -3
  185. package/src/components/BatchProgressList.vue +35 -25
  186. package/src/components/ChartContainer.story.vue +2 -1
  187. package/src/components/ChartContainer.vue +8 -6
  188. package/src/components/ConfirmDialog.story.vue +1 -1
  189. package/src/components/EmptyState.vue +1 -1
  190. package/src/components/ExperimentPopover.story.vue +165 -53
  191. package/src/components/ExperimentPopover.vue +169 -187
  192. package/src/components/ExperimentSelectorModal.story.vue +73 -31
  193. package/src/components/ExperimentSelectorModal.vue +144 -111
  194. package/src/components/FormField.story.vue +8 -48
  195. package/src/components/GeneratedPluginView.vue +11 -10
  196. package/src/components/GeneratedResultRenderer.vue +3 -4
  197. package/src/components/InstrumentStateBadge.vue +1 -1
  198. package/src/components/JobsStatusTray.story.vue +97 -43
  199. package/src/components/JobsStatusTray.vue +287 -290
  200. package/src/components/LayoutResizeHandle.story.vue +65 -4
  201. package/src/components/LoadingSpinner.vue +1 -1
  202. package/src/components/NumberInput.vue +3 -6
  203. package/src/components/PluginIcon.story.vue +2 -10
  204. package/src/components/PluginIcon.vue +2 -2
  205. package/src/components/PluginWorkspaceView.props.ts +3 -0
  206. package/src/components/PluginWorkspaceView.story.vue +1 -1
  207. package/src/components/PluginWorkspaceView.vue +17 -0
  208. package/src/components/RuntimeUpdateNotice.vue +1 -1
  209. package/src/components/SampleSelector.story.vue +22 -7
  210. package/src/components/SampleSelector.vue +34 -37
  211. package/src/components/SampleSelectorGroupNode.vue +1 -1
  212. package/src/components/SectionCard.story.vue +35 -2
  213. package/src/components/SequenceProgressBar.story.vue +9 -0
  214. package/src/components/SequenceProgressBar.vue +6 -1
  215. package/src/components/SettingsModal.schema.ts +1 -1
  216. package/src/components/SettingsModal.vue +9 -14
  217. package/src/components/SmartGroupFieldRecipe.story.vue +1 -1
  218. package/src/components/SmartGroupManual.story.vue +1 -1
  219. package/src/components/StepWizard.story.vue +33 -0
  220. package/src/components/StepWizard.vue +8 -1
  221. package/src/components/Tooltip.vue +9 -32
  222. package/src/components/WellPlate.story.vue +3 -1
  223. package/src/components/WellPlate.vue +7 -0
  224. package/src/components/internal/AppTopBarOnboardingInternal.vue +172 -0
  225. package/src/components/internal/AppTopBarPageSelectorInternal.vue +140 -72
  226. package/src/components/internal/AppTopBarPillNavInternal.vue +33 -2
  227. package/src/components/internal/DatePickerDateInternal.vue +23 -85
  228. package/src/components/internal/DatePickerDateTimeInternal.vue +10 -14
  229. package/src/components/internal/DatePickerTimeInternal.vue +13 -9
  230. package/src/components/internal/NumberUnitInputInternal.vue +4 -18
  231. package/src/components/internal/OnboardingLayerInternal.vue +173 -0
  232. package/src/components/internal/ResourcePickerListInternal.vue +45 -85
  233. package/src/components/internal/SelectMultipleInternal.vue +187 -65
  234. package/src/components/internal/SelectSearchableInternal.vue +8 -4
  235. package/src/components/internal/WellEditPopupInternal.vue +11 -22
  236. package/src/components/internal/WorkspaceShellInternal.vue +12 -0
  237. package/src/composables/createClient.ts +2 -0
  238. package/src/composables/index.ts +1 -0
  239. package/src/composables/pluginIdentity.ts +31 -0
  240. package/src/composables/pluginWorkspaceModel.ts +2 -2
  241. package/src/composables/useAppExperiment.ts +20 -0
  242. package/src/composables/useCalendarGrid.ts +4 -3
  243. package/src/composables/useExperimentSelector.ts +77 -31
  244. package/src/composables/useFileImport.ts +51 -1
  245. package/src/composables/useFloatingPanel.ts +107 -0
  246. package/src/composables/useJobCenter.ts +188 -6
  247. package/src/composables/useOnboarding.ts +465 -0
  248. package/src/composables/usePluginWorkspace.ts +1 -1
  249. package/src/data.ts +1 -0
  250. package/src/runtime.ts +2 -1
  251. package/src/shell.ts +17 -0
  252. package/src/stores/index.ts +0 -2
  253. package/src/stores/settings.ts +20 -50
  254. package/src/styles/components/action-menu.css +1 -1
  255. package/src/styles/components/adduct-text.css +13 -5
  256. package/src/styles/components/alert-box.css +39 -58
  257. package/src/styles/components/app-layout.css +10 -6
  258. package/src/styles/components/app-page-selector.css +121 -44
  259. package/src/styles/components/app-pill-nav.css +11 -12
  260. package/src/styles/components/app-sidebar.css +9 -18
  261. package/src/styles/components/app-top-bar.css +219 -55
  262. package/src/styles/components/artifact-save-dialog.css +153 -2
  263. package/src/styles/components/audit-trail.css +16 -19
  264. package/src/styles/components/avatar.css +6 -4
  265. package/src/styles/components/batch-progress-list.css +38 -36
  266. package/src/styles/components/button.css +36 -59
  267. package/src/styles/components/calendar.css +12 -12
  268. package/src/styles/components/chart-container.css +34 -23
  269. package/src/styles/components/checkbox.css +2 -12
  270. package/src/styles/components/collapsible-card.css +27 -29
  271. package/src/styles/components/confirm-dialog.css +13 -14
  272. package/src/styles/components/dataframe.css +13 -5
  273. package/src/styles/components/date-picker.css +84 -94
  274. package/src/styles/components/datetime-picker.css +35 -47
  275. package/src/styles/components/divider.css +20 -20
  276. package/src/styles/components/dose-calculator.css +3 -3
  277. package/src/styles/components/empty-state.css +20 -17
  278. package/src/styles/components/experiment-code-badge.css +2 -0
  279. package/src/styles/components/experiment-popover.css +174 -329
  280. package/src/styles/components/experiment-selector-modal.css +88 -56
  281. package/src/styles/components/file-picker.css +3 -3
  282. package/src/styles/components/file-uploader.css +38 -49
  283. package/src/styles/components/form-builder.css +3 -3
  284. package/src/styles/components/formula-input.css +1 -1
  285. package/src/styles/components/icon-button.css +18 -24
  286. package/src/styles/components/input.css +5 -4
  287. package/src/styles/components/instrument-monitor.css +13 -15
  288. package/src/styles/components/jobs-status-tray.css +140 -296
  289. package/src/styles/components/layout-resize-handle.css +59 -16
  290. package/src/styles/components/modal.css +5 -7
  291. package/src/styles/components/molecule-input.css +2 -2
  292. package/src/styles/components/multi-select.css +65 -117
  293. package/src/styles/components/number-input.css +26 -19
  294. package/src/styles/components/onboarding.css +368 -0
  295. package/src/styles/components/pill.css +3 -2
  296. package/src/styles/components/plate-editor.css +0 -1
  297. package/src/styles/components/plugin-icon.css +26 -23
  298. package/src/styles/components/popover.css +2 -2
  299. package/src/styles/components/presence-avatars.css +1 -1
  300. package/src/styles/components/progress-bar.css +3 -3
  301. package/src/styles/components/protocol-step-editor.css +1 -3
  302. package/src/styles/components/resource-card.css +2 -2
  303. package/src/styles/components/resource-picker-list.css +6 -57
  304. package/src/styles/components/sample-hierarchy-tree.css +4 -4
  305. package/src/styles/components/sample-selector.css +138 -79
  306. package/src/styles/components/schedule-calendar.css +8 -8
  307. package/src/styles/components/searchable-select.css +15 -19
  308. package/src/styles/components/section-card.css +54 -49
  309. package/src/styles/components/segmented-control.css +18 -15
  310. package/src/styles/components/select.css +3 -3
  311. package/src/styles/components/sequence-input.css +2 -2
  312. package/src/styles/components/sequence-progress-bar.css +17 -8
  313. package/src/styles/components/settings-modal.css +7 -2
  314. package/src/styles/components/smart-group.css +18 -18
  315. package/src/styles/components/step-wizard.css +52 -16
  316. package/src/styles/components/tabs.css +2 -2
  317. package/src/styles/components/textarea.css +3 -3
  318. package/src/styles/components/time-picker.css +37 -25
  319. package/src/styles/components/toast.css +13 -11
  320. package/src/styles/components/toggle.css +1 -11
  321. package/src/styles/components/tooltip.css +12 -11
  322. package/src/styles/components/unit-input.css +9 -8
  323. package/src/styles/components/well-edit-popup.css +2 -2
  324. package/src/styles/components/well-plate.css +9 -2
  325. package/src/styles/index.css +1 -0
  326. package/src/styles/variables.css +247 -78
  327. package/src/types/componentWorkflowTypes.ts +2 -0
  328. package/src/types/components.ts +2 -0
  329. package/src/types/generated/platformContext.ts +1 -0
  330. package/src/types/generated-ui.ts +4 -0
  331. package/src/types/index.ts +1 -0
  332. package/src/types/jobs.ts +10 -0
  333. package/src/types/platform.ts +1 -1
  334. package/src/utils/time.ts +21 -0
  335. package/dist/ActionMenu-CScINahU.js.map +0 -1
  336. package/dist/AppSidebar-BmiiPfz9.js.map +0 -1
  337. package/dist/BaseModal-DfRIuVoj.js.map +0 -1
  338. package/dist/ExperimentPopover-C4sGw-is.js +0 -359
  339. package/dist/ExperimentPopover-C4sGw-is.js.map +0 -1
  340. package/dist/ExperimentSelectorModal-D-9z7cNx.js.map +0 -1
  341. package/dist/SettingsModal-CSLE31yg.js.map +0 -1
  342. package/dist/data-C2PwI_dn.js.map +0 -1
  343. package/dist/experiment-43OJtH7R.js.map +0 -1
  344. package/dist/lab-DLwRl_Ql.js.map +0 -1
  345. package/dist/records-BzTcxekG.js.map +0 -1
  346. package/dist/runtime-D6gVat6r.js.map +0 -1
  347. package/dist/useExperimentSamples-CxcnxZ8h.js.map +0 -1
  348. package/dist/useListReorder-CcbEYxX-.js.map +0 -1
  349. package/dist/useRackEditor-BD5NIo5s.js.map +0 -1
  350. package/dist/useRealtime-PalKue84.js +0 -696
  351. package/dist/useRealtime-PalKue84.js.map +0 -1
  352. package/dist/useRequest-D5JDfsgZ.js +0 -76
  353. package/dist/useRequest-D5JDfsgZ.js.map +0 -1
@@ -10,6 +10,7 @@ const mockExperiments: ExperimentSummary[] = [
10
10
  {
11
11
  id: 1,
12
12
  experiment_code: 'DR-HeLa-DOX-001',
13
+ created_by: 1,
13
14
  name: 'Doxorubicin dose-response in HeLa cells',
14
15
  status: 'completed',
15
16
  experiment_type: 'dose_response',
@@ -34,6 +35,7 @@ const mockExperiments: ExperimentSummary[] = [
34
35
  {
35
36
  id: 3,
36
37
  experiment_code: 'DR-PANC1-GEM-003',
38
+ created_by: 1,
37
39
  name: 'Gemcitabine IC50 in PANC-1',
38
40
  status: 'ongoing',
39
41
  experiment_type: 'dose_response',
@@ -70,6 +72,7 @@ const mockExperiments: ExperimentSummary[] = [
70
72
  {
71
73
  id: 6,
72
74
  experiment_code: 'SYN-HeLa-COMBO-006',
75
+ created_by: 1,
73
76
  name: 'DOX + 5-FU synergy screen in HeLa',
74
77
  status: 'planned',
75
78
  experiment_type: 'synergy',
@@ -106,6 +109,7 @@ const mockExperiments: ExperimentSummary[] = [
106
109
  {
107
110
  id: 9,
108
111
  experiment_code: 'CV-JURKAT-VIN-009',
112
+ created_by: 1,
109
113
  name: 'Vincristine titration Jurkat T-cells',
110
114
  status: 'ongoing',
111
115
  experiment_type: 'cell_viability',
@@ -128,9 +132,9 @@ const mockExperiments: ExperimentSummary[] = [
128
132
  ]
129
133
 
130
134
  const mockExperimentTypes = [
131
- { name: 'dose_response', color: '#3b82f6' },
132
- { name: 'cell_viability', color: '#10b981' },
133
- { name: 'synergy', color: '#f59e0b' },
135
+ { value: 'dose_response', label: 'Dose response' },
136
+ { value: 'cell_viability', label: 'Cell viability' },
137
+ { value: 'synergy', label: 'Synergy' },
134
138
  ]
135
139
 
136
140
  const mockProjects = [
@@ -152,6 +156,7 @@ function applyMockFilters(
152
156
  const expType = params.get('experiment_type')
153
157
  const project = params.get('project')
154
158
  const search = params.get('search')?.toLowerCase()
159
+ const mine = params.get('mine') === 'true'
155
160
  const createdAfter = params.get('created_after')
156
161
  const sortBy = (params.get('sort_by') ?? 'created_at') as ExperimentSortField
157
162
  const sortOrder = params.get('sort_order') ?? 'desc'
@@ -159,6 +164,7 @@ function applyMockFilters(
159
164
  if (status) filtered = filtered.filter((e) => e.status === status)
160
165
  if (expType) filtered = filtered.filter((e) => e.experiment_type === expType)
161
166
  if (project) filtered = filtered.filter((e) => e.project === project)
167
+ if (mine) filtered = filtered.filter((e) => e.created_by === 1)
162
168
  if (search) {
163
169
  filtered = filtered.filter(
164
170
  (e) =>
@@ -208,7 +214,24 @@ onMounted(async () => {
208
214
  if (url.includes('/projects')) {
209
215
  config.adapter = () =>
210
216
  Promise.resolve({
211
- data: mockProjects,
217
+ data: { projects: mockProjects, total: mockProjects.length },
218
+ status: 200,
219
+ statusText: 'OK',
220
+ headers: {},
221
+ config,
222
+ })
223
+ return config
224
+ }
225
+
226
+ // Status counts: the list filters without status (the route never receives one).
227
+ if (/^(\/api)?\/experiments\/stats(\?|$)/.test(url)) {
228
+ const params = new URLSearchParams(url.split('?')[1] ?? '')
229
+ const filtered = applyMockFilters(mockExperiments, params)
230
+ const by_status: Record<string, number> = { planned: 0, ongoing: 0, completed: 0, cancelled: 0 }
231
+ for (const e of filtered) by_status[e.status] = (by_status[e.status] ?? 0) + 1
232
+ config.adapter = () =>
233
+ Promise.resolve({
234
+ data: { total: filtered.length, by_status },
212
235
  status: 200,
213
236
  statusText: 'OK',
214
237
  headers: {},
@@ -245,10 +268,10 @@ onMounted(async () => {
245
268
 
246
269
  // -- Story state --
247
270
  const isOpen = ref(false)
271
+ const isOpenRun = ref(false)
248
272
  const isOpenEmpty = ref(false)
249
- const isOpenGrouped = ref(false)
250
273
  const isOpenWithSelection = ref(false)
251
- const isOpenAdvanced = ref(false)
274
+ const isOpenFilters = ref(false)
252
275
 
253
276
  // The modal commits to the shared store rather than emitting; stories read the
254
277
  // selection back from the same place a plugin would.
@@ -262,7 +285,7 @@ const selectedExperiment = computed(() => experimentStore.current)
262
285
  <template #default="{ state }">
263
286
  <div style="padding: 2rem;">
264
287
  <button
265
- style="padding: 0.5rem 1rem; background: var(--color-primary, #3b82f6); color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 0.875rem;"
288
+ style="padding: 0.5rem 1rem; background: var(--color-primary); color: var(--text-on-accent); border: none; border-radius: var(--radius-md); cursor: pointer; font-size: 0.875rem;"
266
289
  @click="isOpen = true"
267
290
  >
268
291
  Open Experiment Selector
@@ -287,6 +310,7 @@ const selectedExperiment = computed(() => experimentStore.current)
287
310
  v-model:open="isOpen"
288
311
  :experiment-type="state.experimentType || undefined"
289
312
  :title="state.title"
313
+ :size="state.size || undefined"
290
314
  :current-experiment-id="selectedExperiment?.id ?? null"
291
315
  />
292
316
  </div>
@@ -294,68 +318,86 @@ const selectedExperiment = computed(() => experimentStore.current)
294
318
 
295
319
  <template #controls="{ state }">
296
320
  <HstCheckbox v-model="isOpen" title="Open" />
321
+ <HstSelect v-model="state.size" title="Size (default lg)" :options="['', 'md', 'lg', 'xl', 'full']" />
297
322
  <HstText v-model="state.title" title="Title" />
298
323
  <HstText v-model="state.experimentType" title="Experiment Type" />
299
324
  </template>
300
325
  </Variant>
301
326
 
302
- <Variant title="With Advanced Filters">
327
+ <Variant title="Active Filters">
303
328
  <div style="padding: 2rem;">
304
- <p style="font-size: 0.8125rem; color: var(--text-muted, #94a3b8); margin: 0 0 1rem;">
305
- Opens with advanced filters expanded: Project, Date range, Sort, and Group toggle.
329
+ <p style="font-size: 0.8125rem; color: var(--text-muted); margin: 0 0 1rem;">
330
+ Pick a status (each option shows its count), pick a project or press Mine: the trigger
331
+ fills with the accent tint and "Clear N" appears. Mine keeps the experiments of user 1.
306
332
  </p>
307
333
  <button
308
- style="padding: 0.5rem 1rem; background: var(--color-primary, #3b82f6); color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 0.875rem;"
309
- @click="isOpenAdvanced = true"
334
+ style="padding: 0.5rem 1rem; background: var(--color-primary); color: var(--text-on-accent); border: none; border-radius: var(--radius-md); cursor: pointer; font-size: 0.875rem;"
335
+ @click="isOpenFilters = true"
310
336
  >
311
337
  Open With Filters
312
338
  </button>
313
339
 
314
340
  <ExperimentSelectorModal
315
- v-model:open="isOpenAdvanced"
341
+ v-model:open="isOpenFilters"
316
342
  title="Select Experiment"
317
- :show-filters="true"
318
343
  />
319
344
  </div>
320
345
  </Variant>
321
346
 
322
- <Variant title="Grouped by Project">
347
+ <Variant title="With Clear Selection">
323
348
  <div style="padding: 2rem;">
324
349
  <p style="font-size: 0.8125rem; color: var(--text-muted, #94a3b8); margin: 0 0 1rem;">
325
- Opens with group-by-project enabled by default.
350
+ Shows the "Clear selection" footer when an experiment is selected.
326
351
  </p>
327
352
  <button
328
- style="padding: 0.5rem 1rem; background: var(--color-primary, #3b82f6); color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 0.875rem;"
329
- @click="isOpenGrouped = true"
353
+ style="padding: 0.5rem 1rem; background: var(--color-primary); color: var(--text-on-accent); border: none; border-radius: var(--radius-md); cursor: pointer; font-size: 0.875rem;"
354
+ @click="isOpenWithSelection = true"
330
355
  >
331
- Open Grouped Selector
356
+ Open Selector (with selection)
332
357
  </button>
333
358
 
334
359
  <ExperimentSelectorModal
335
- v-model:open="isOpenGrouped"
360
+ v-model:open="isOpenWithSelection"
336
361
  title="Select Experiment"
337
- :group-by-project="true"
362
+ :current-experiment-id="1"
338
363
  />
339
364
  </div>
340
365
  </Variant>
341
366
 
342
- <Variant title="With Clear Selection">
367
+ <Variant title="Run Destination (slots)">
343
368
  <div style="padding: 2rem;">
344
369
  <p style="font-size: 0.8125rem; color: var(--text-muted, #94a3b8); margin: 0 0 1rem;">
345
- Shows the "Clear selection" footer when an experiment is selected.
370
+ A plugin asks where to save a run: the description slot explains why, and the footer slot adds Skip with close().
346
371
  </p>
347
372
  <button
348
- style="padding: 0.5rem 1rem; background: var(--color-primary, #3b82f6); color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 0.875rem;"
349
- @click="isOpenWithSelection = true"
373
+ style="padding: 0.5rem 1rem; background: var(--color-primary); color: var(--text-on-accent); border: none; border-radius: var(--radius-md); cursor: pointer; font-size: 0.875rem;"
374
+ @click="isOpenRun = true"
350
375
  >
351
- Open Selector (with selection)
376
+ Run extraction
352
377
  </button>
353
378
 
354
379
  <ExperimentSelectorModal
355
- v-model:open="isOpenWithSelection"
356
- title="Select Experiment"
357
- :current-experiment-id="1"
358
- />
380
+ v-model:open="isOpenRun"
381
+ title="Save the result to an experiment?"
382
+ >
383
+ <template #description>
384
+ Pick an experiment to save this run as a new artifact in it, next to the samples it belongs to.
385
+ </template>
386
+ <template #footer="{ close }">
387
+ <div style="display: flex; align-items: center; gap: 0.75rem;">
388
+ <span style="flex: 1; font-size: 0.75rem; color: var(--text-secondary);">
389
+ Skip: the result stays in the plugin. You can save it to an experiment later.
390
+ </span>
391
+ <button
392
+ type="button"
393
+ style="height: 2rem; padding: 0 0.75rem; border: 1px solid var(--border-color); border-radius: var(--radius-md); background: var(--bg-card); color: var(--text-primary); cursor: pointer;"
394
+ @click="close"
395
+ >
396
+ Skip
397
+ </button>
398
+ </div>
399
+ </template>
400
+ </ExperimentSelectorModal>
359
401
  </div>
360
402
  </Variant>
361
403
 
@@ -365,7 +407,7 @@ const selectedExperiment = computed(() => experimentStore.current)
365
407
  Filters to a non-existent experiment type, showing the empty state.
366
408
  </p>
367
409
  <button
368
- style="padding: 0.5rem 1rem; background: var(--color-primary, #3b82f6); color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 0.875rem;"
410
+ style="padding: 0.5rem 1rem; background: var(--color-primary); color: var(--text-on-accent); border: none; border-radius: var(--radius-md); cursor: pointer; font-size: 0.875rem;"
369
411
  @click="isOpenEmpty = true"
370
412
  >
371
413
  Open Experiment Selector (Empty)
@@ -7,18 +7,15 @@
7
7
  * <ExperimentSelectorModal v-model:open="open" :allowed-experiment-types="['mass-spectrometry']" />
8
8
  * ```
9
9
  */
10
- import { ref, computed, watch } from 'vue'
11
- import type { ModalSize, ExperimentSummary, ExperimentFilters } from '../types'
10
+ import { ref, computed, watch, type Component } from 'vue'
11
+ import { ChevronDown, CircleDot, Folder, Shapes, User } from 'lucide-vue-next'
12
+ import type { ModalSize, ExperimentSummary, ExperimentFilters, ActionMenuItem, Tone } from '../types'
12
13
  import { useExperimentSelector } from '../composables/useExperimentSelector'
13
14
  import { useExperimentStore } from '../stores/experiment'
14
- import {
15
- formatExperimentDate,
16
- DATE_PRESET_OPTIONS,
17
- SORT_OPTIONS,
18
- } from '../composables/experiment-utils'
15
+ import { formatExperimentDate } from '../composables/experiment-utils'
19
16
  import * as experimentStatus from '../utils/experimentStatus'
20
17
  import BaseModal from './BaseModal.vue'
21
- import BaseSelect from './BaseSelect.vue'
18
+ import ActionMenu from './ActionMenu.vue'
22
19
  import ResourcePickerListInternal from './internal/ResourcePickerListInternal.vue'
23
20
 
24
21
  interface Props {
@@ -28,16 +25,12 @@ interface Props {
28
25
  currentExperimentId?: number | null
29
26
  title?: string
30
27
  size?: ModalSize
31
- groupByProject?: boolean
32
- showFilters?: boolean
33
28
  }
34
29
 
35
30
  const props = withDefaults(defineProps<Props>(), {
36
31
  currentExperimentId: null,
37
32
  title: 'Select Experiment',
38
- size: 'full',
39
- groupByProject: false,
40
- showFilters: false,
33
+ size: 'lg',
41
34
  })
42
35
 
43
36
  // Selection is committed to the shared experiment store rather than emitted.
@@ -47,6 +40,17 @@ const emit = defineEmits<{
47
40
  'update:open': [value: boolean]
48
41
  }>()
49
42
 
43
+ defineSlots<{
44
+ /** Text above the experiment list: why the caller asks for an experiment. */
45
+ description?: () => unknown
46
+ /** Extra footer content, before Clear selection. `close()` closes the modal without a selection. */
47
+ footer?: (props: { close: () => void }) => unknown
48
+ }>()
49
+
50
+ function close() {
51
+ emit('update:open', false)
52
+ }
53
+
50
54
  const experimentStore = useExperimentStore()
51
55
 
52
56
  const {
@@ -54,55 +58,102 @@ const {
54
58
  filters,
55
59
  isLoading,
56
60
  error,
57
- sortKey,
58
61
  experimentTypes,
59
62
  projects,
60
- groupedByProject,
63
+ statusCounts,
61
64
  fetch: fetchExperiments,
62
65
  fetchFilterOptions,
66
+ fetchStatusCounts,
63
67
  } = useExperimentSelector({
64
68
  experimentType: props.experimentType,
65
69
  allowedExperimentTypes: props.allowedExperimentTypes,
70
+ withStatusCounts: true,
66
71
  })
67
72
 
68
- const showAdvanced = ref(props.showFilters)
69
- const groupToggle = ref(props.groupByProject)
70
- // Re-mounting the list on open clears its collapsed groups and keyboard highlight.
73
+ // Re-mounting the list on open clears its keyboard highlight.
71
74
  const openCount = ref(0)
72
75
 
73
- // Track whether any advanced filter is active (for badge dot)
74
- const hasActiveAdvancedFilters = computed(() =>
75
- !!(filters.project || filters.experimentType || filters.datePreset || sortKey.value !== 'created_at:desc'),
76
- )
76
+ const STATUS_ORDER = ['ongoing', 'planned', 'completed', 'cancelled'] as const
77
77
 
78
- // Build type filter options from fetched experiment types
79
- const typeFilterOptions = computed(() => [
80
- { value: '', label: 'All types' },
81
- ...experimentTypes.value.map(t => ({ value: t.value, label: t.label })),
82
- ])
83
78
  const canChooseExperimentType = computed(() =>
84
- !props.experimentType && typeFilterOptions.value.length > 2,
79
+ !props.experimentType && experimentTypes.value.length > 1,
85
80
  )
86
81
 
87
- // Build project filter options from fetched projects
88
- const projectFilterOptions = computed(() => [
89
- { value: '', label: 'All projects' },
90
- ...projects.value,
91
- ])
82
+ type FilterKey = 'status' | 'project' | 'experimentType'
83
+
84
+ interface FilterMenu {
85
+ key: FilterKey
86
+ label: string
87
+ icon: Component
88
+ items: ActionMenuItem[]
89
+ /** Trigger text while the filter is set. */
90
+ activeLabel?: string
91
+ dotTone?: Tone
92
+ }
93
+
94
+ /** Every item carries `checked`, so ActionMenu renders a single-choice menu. */
95
+ function choiceItems(key: FilterKey, anyLabel: string, options: { value: string; label: string }[]): ActionMenuItem[] {
96
+ const current = filters[key] ?? ''
97
+ return [{ value: '', label: anyLabel }, ...options].map(option => ({
98
+ id: option.value,
99
+ label: option.label,
100
+ checked: option.value === current,
101
+ }))
102
+ }
103
+
104
+ const filterMenus = computed<FilterMenu[]>(() => {
105
+ const menus: FilterMenu[] = [{
106
+ key: 'status',
107
+ label: 'Status',
108
+ icon: CircleDot,
109
+ items: choiceItems('status', 'Any status', STATUS_ORDER.map(status => {
110
+ const count = statusCounts.value[status]
111
+ const label = experimentStatus.format(status)
112
+ return { value: status, label: count === undefined ? label : `${label} · ${count}` }
113
+ })),
114
+ activeLabel: filters.status ? experimentStatus.format(filters.status) : undefined,
115
+ dotTone: filters.status ? experimentStatus.tone(filters.status) : undefined,
116
+ }]
117
+ if (projects.value.length) {
118
+ menus.push({
119
+ key: 'project',
120
+ label: 'Project',
121
+ icon: Folder,
122
+ items: choiceItems('project', 'Any project', projects.value),
123
+ activeLabel: filters.project ?? undefined,
124
+ })
125
+ }
126
+ if (canChooseExperimentType.value) {
127
+ menus.push({
128
+ key: 'experimentType',
129
+ label: 'Type',
130
+ icon: Shapes,
131
+ items: choiceItems('experimentType', 'Any type', experimentTypes.value),
132
+ activeLabel: experimentTypes.value.find(t => t.value === filters.experimentType)?.label
133
+ ?? filters.experimentType ?? undefined,
134
+ })
135
+ }
136
+ return menus
137
+ })
92
138
 
93
- const groups = computed(() =>
94
- groupToggle.value
95
- ? groupedByProject.value.map(([label, items]) => ({ label, items }))
96
- : null,
139
+ const activeFilterCount = computed(() =>
140
+ [filters.status, filters.project, filters.experimentType, filters.mine].filter(Boolean).length,
97
141
  )
98
142
 
143
+ function clearFilters() {
144
+ filters.status = undefined
145
+ filters.project = undefined
146
+ filters.experimentType = undefined
147
+ filters.mine = undefined
148
+ }
149
+
99
150
  function describe(experiment: ExperimentSummary) {
100
151
  const owner = experiment.created_by_user
101
152
  return {
102
153
  code: experiment.experiment_code,
103
154
  title: experiment.name,
104
155
  meta: [
105
- ...(groupToggle.value ? [] : [experiment.project_name || experiment.project || '']),
156
+ experiment.project_name || experiment.project || '',
106
157
  owner ? [owner.first_name, owner.last_name].filter(Boolean).join(' ') || owner.username : '',
107
158
  ].filter(Boolean),
108
159
  status: experiment.status
@@ -116,10 +167,6 @@ function setFilter<K extends keyof ExperimentFilters>(key: K, value: string | nu
116
167
  ;(filters as Record<string, unknown>)[key] = String(value) || undefined
117
168
  }
118
169
 
119
- function handleSortChange(value: string | number) {
120
- sortKey.value = String(value) || 'created_at:desc'
121
- }
122
-
123
170
  function handleSelect(experiment: ExperimentSummary) {
124
171
  experimentStore.select(experiment)
125
172
  emit('update:open', false)
@@ -138,6 +185,7 @@ watch(
138
185
  openCount.value++
139
186
  fetchFilterOptions()
140
187
  fetchExperiments()
188
+ fetchStatusCounts()
141
189
  }
142
190
  },
143
191
  { immediate: true },
@@ -151,14 +199,18 @@ watch(
151
199
  :size="size"
152
200
  @update:open="emit('update:open', $event)"
153
201
  >
202
+ <div v-if="$slots.description" class="mint-experiment-selector__description">
203
+ <slot name="description" />
204
+ </div>
205
+
154
206
  <ResourcePickerListInternal
155
207
  :key="openCount"
156
208
  :search="filters.search ?? ''"
157
209
  class="mint-experiment-selector"
210
+ autofocus-search
158
211
  label="Experiments"
159
212
  placeholder="Search experiments…"
160
213
  :items="experiments"
161
- :groups="groups"
162
214
  :item-key="(experiment) => experiment.id"
163
215
  :describe="describe"
164
216
  :selected-key="currentExperimentId"
@@ -169,82 +221,63 @@ watch(
169
221
  @select="handleSelect"
170
222
  >
171
223
  <template #filters>
172
- <div class="mint-experiment-selector__filter-select">
173
- <BaseSelect
174
- :model-value="filters.status ?? ''"
175
- :options="experimentStatus.OPTIONS"
176
- size="sm"
177
- aria-label="Filter by status"
178
- @update:model-value="v => setFilter('status', v)"
179
- />
180
- </div>
181
- <div v-if="canChooseExperimentType" class="mint-experiment-selector__filter-select">
182
- <BaseSelect
183
- :model-value="filters.experimentType ?? ''"
184
- :options="typeFilterOptions"
185
- size="sm"
186
- aria-label="Filter by type"
187
- @update:model-value="v => setFilter('experimentType', v)"
188
- />
189
- </div>
224
+ <ActionMenu
225
+ v-for="menu in filterMenus"
226
+ :key="menu.key"
227
+ :label="menu.label"
228
+ :items="menu.items"
229
+ @select="item => setFilter(menu.key, item.id)"
230
+ >
231
+ <template #trigger="{ open: menuOpen, toggle, keydown }">
232
+ <button
233
+ type="button"
234
+ class="mint-experiment-selector__toggle"
235
+ :class="{ 'mint-experiment-selector__toggle--active': menu.activeLabel }"
236
+ :aria-label="`${menu.label}: ${menu.activeLabel ?? menu.items[0].label}`"
237
+ aria-haspopup="menu"
238
+ :aria-expanded="menuOpen"
239
+ @click="toggle"
240
+ @keydown="keydown"
241
+ >
242
+ <span
243
+ v-if="menu.dotTone"
244
+ class="mint-experiment-selector__dot"
245
+ :class="`mint-experiment-selector__dot--${menu.dotTone}`"
246
+ aria-hidden="true"
247
+ />
248
+ <component :is="menu.icon" v-else :size="13" aria-hidden="true" />
249
+ <span class="mint-experiment-selector__toggle-label">{{ menu.activeLabel ?? menu.label }}</span>
250
+ <ChevronDown :size="12" aria-hidden="true" />
251
+ </button>
252
+ </template>
253
+ </ActionMenu>
190
254
  <button
191
- class="mint-experiment-selector__filters-toggle"
192
- :class="{ 'mint-experiment-selector__filters-toggle--active': hasActiveAdvancedFilters }"
193
255
  type="button"
194
- :aria-expanded="showAdvanced"
195
- @click="showAdvanced = !showAdvanced"
256
+ class="mint-experiment-selector__toggle"
257
+ :class="{ 'mint-experiment-selector__toggle--active': filters.mine }"
258
+ :aria-pressed="!!filters.mine"
259
+ @click="filters.mine = filters.mine ? undefined : true"
196
260
  >
197
- <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
198
- <line x1="4" y1="6" x2="20" y2="6" /><line x1="8" y1="12" x2="20" y2="12" /><line x1="12" y1="18" x2="20" y2="18" />
199
- <circle cx="6" cy="12" r="2" /><circle cx="10" cy="18" r="2" /><circle cx="6" cy="6" r="2" />
200
- </svg>
201
- Filters
202
- <span v-if="hasActiveAdvancedFilters" class="mint-experiment-selector__filters-dot" />
261
+ <User :size="13" aria-hidden="true" />
262
+ Mine
263
+ </button>
264
+ <button
265
+ v-if="activeFilterCount"
266
+ type="button"
267
+ class="mint-experiment-selector__clear-filters"
268
+ @click="clearFilters"
269
+ >
270
+ Clear {{ activeFilterCount }}
203
271
  </button>
204
- </template>
205
- <template #advanced>
206
- <div v-if="showAdvanced" class="mint-experiment-selector__filters-advanced">
207
- <div v-if="projectFilterOptions.length > 1" class="mint-experiment-selector__filter-select">
208
- <BaseSelect
209
- :model-value="filters.project ?? ''"
210
- :options="projectFilterOptions"
211
- size="sm"
212
- aria-label="Filter by project"
213
- @update:model-value="v => setFilter('project', v)"
214
- />
215
- </div>
216
- <div class="mint-experiment-selector__filter-select">
217
- <BaseSelect
218
- :model-value="filters.datePreset ?? ''"
219
- :options="DATE_PRESET_OPTIONS"
220
- size="sm"
221
- aria-label="Filter by date"
222
- @update:model-value="v => setFilter('datePreset', v)"
223
- />
224
- </div>
225
- <div class="mint-experiment-selector__filter-select">
226
- <BaseSelect
227
- :model-value="sortKey"
228
- :options="SORT_OPTIONS"
229
- size="sm"
230
- aria-label="Sort"
231
- @update:model-value="handleSortChange"
232
- />
233
- </div>
234
- <label class="mint-experiment-selector__group-toggle">
235
- <input
236
- v-model="groupToggle"
237
- type="checkbox"
238
- class="mint-experiment-selector__group-checkbox"
239
- />
240
- Group by project
241
- </label>
242
- </div>
243
272
  </template>
244
273
  </ResourcePickerListInternal>
245
274
 
246
- <div v-if="currentExperimentId != null" class="mint-experiment-selector__footer">
275
+ <div v-if="$slots.footer || currentExperimentId != null" class="mint-experiment-selector__footer">
276
+ <div v-if="$slots.footer" class="mint-experiment-selector__footer-slot">
277
+ <slot name="footer" :close="close" />
278
+ </div>
247
279
  <button
280
+ v-if="currentExperimentId != null"
248
281
  type="button"
249
282
  class="mint-experiment-selector__clear-btn"
250
283
  @click="handleDeselect"