@morscherlab/mint-sdk 1.4.0-beta.2 → 1.4.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 (330) hide show
  1. package/README.md +14 -3
  2. package/dist/{ActionMenu-CScINahU.js → AlertBox-CzLg0UaL.js} +40 -209
  3. package/dist/AlertBox-CzLg0UaL.js.map +1 -0
  4. package/dist/{AppSidebar-BmiiPfz9.js → AppSidebar-6oTT-gPO.js} +1249 -239
  5. package/dist/AppSidebar-6oTT-gPO.js.map +1 -0
  6. package/dist/{ConfirmDialog-CJ7hqYUP.js → ConfirmDialog-CSls2Nuv.js} +2 -2
  7. package/dist/{ConfirmDialog-CJ7hqYUP.js.map → ConfirmDialog-CSls2Nuv.js.map} +1 -1
  8. package/dist/ExperimentPopover-9l4QZlvQ.js +337 -0
  9. package/dist/ExperimentPopover-9l4QZlvQ.js.map +1 -0
  10. package/dist/{ExperimentSelectorModal-D-9z7cNx.js → ExperimentSelectorModal-pR5fK3pA.js} +244 -211
  11. package/dist/ExperimentSelectorModal-pR5fK3pA.js.map +1 -0
  12. package/dist/{SegmentedControl-DERBN-Xd.js → SegmentedControl-CJ7EAmOq.js} +2 -2
  13. package/dist/{SegmentedControl-DERBN-Xd.js.map → SegmentedControl-CJ7EAmOq.js.map} +1 -1
  14. package/dist/{SettingsModal-CSLE31yg.js → SettingsModal-Dyitgzfp.js} +28 -27
  15. package/dist/SettingsModal-Dyitgzfp.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__/composables/useOnboarding.test.d.ts +1 -0
  19. package/dist/__tests__/styles/paletteTokens.test.d.ts +1 -0
  20. package/dist/__tests__/styles/v2AuditRules.test.d.ts +1 -0
  21. package/dist/components/AppSidebar.vue.d.ts +1 -1
  22. package/dist/components/AppTopBar.vue.d.ts +20 -5
  23. package/dist/components/ArtifactSaveDialog.vue.d.ts +9 -1
  24. package/dist/components/AuditTrail.vue.d.ts +1 -1
  25. package/dist/components/BaseButton.vue.d.ts +4 -2
  26. package/dist/components/BaseSelect.vue.d.ts +2 -2
  27. package/dist/components/ChartContainer.vue.d.ts +2 -0
  28. package/dist/components/DatePicker.vue.d.ts +1 -1
  29. package/dist/components/ExperimentPopover.vue.d.ts +18 -0
  30. package/dist/components/ExperimentSelectorModal.vue.d.ts +15 -5
  31. package/dist/components/FilePicker.vue.d.ts +1 -1
  32. package/dist/components/FileUploader.vue.d.ts +2 -2
  33. package/dist/components/JobsStatusTray.vue.d.ts +15 -4
  34. package/dist/components/PluginIcon.vue.d.ts +2 -2
  35. package/dist/components/PluginWorkspaceView.props.d.ts +3 -0
  36. package/dist/components/PluginWorkspaceView.vue.d.ts +3 -0
  37. package/dist/components/SampleSelector.vue.d.ts +6 -6
  38. package/dist/components/SequenceProgressBar.vue.d.ts +3 -0
  39. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +1 -1
  40. package/dist/components/StepWizard.vue.d.ts +3 -0
  41. package/dist/components/internal/AppTopBarOnboardingInternal.vue.d.ts +7 -0
  42. package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -1
  43. package/dist/components/internal/AutoGroupModalInternal.vue.d.ts +1 -1
  44. package/dist/components/internal/DatePickerTimeInternal.vue.d.ts +1 -1
  45. package/dist/components/internal/OnboardingLayerInternal.vue.d.ts +7 -0
  46. package/dist/components/internal/ResourcePickerListInternal.vue.d.ts +2 -7
  47. package/dist/components/internal/SelectMultipleInternal.vue.d.ts +4 -0
  48. package/dist/components/internal/WorkspaceShellInternal.vue.d.ts +8 -0
  49. package/dist/composables/createClient.d.ts +2 -0
  50. package/dist/composables/index.d.ts +1 -0
  51. package/dist/composables/pluginIdentity.d.ts +24 -0
  52. package/dist/composables/pluginWorkspaceModel.d.ts +2 -2
  53. package/dist/composables/useAppExperiment.d.ts +8 -0
  54. package/dist/composables/useCalendarGrid.d.ts +1 -1
  55. package/dist/composables/useExperimentSelector.d.ts +6 -2
  56. package/dist/composables/useJobCenter.d.ts +41 -3
  57. package/dist/composables/useOnboarding.d.ts +119 -0
  58. package/dist/composables/usePlatform.d.ts +1 -0
  59. package/dist/{controlSchemaModel-CP5-_nAj.js → controlSchemaModel-DCUOx8ll.js} +2 -2
  60. package/dist/{controlSchemaModel-CP5-_nAj.js.map → controlSchemaModel-DCUOx8ll.js.map} +1 -1
  61. package/dist/{data-C2PwI_dn.js → data-DBnmeBZX.js} +179 -125
  62. package/dist/data-DBnmeBZX.js.map +1 -0
  63. package/dist/data.js +8 -8
  64. package/dist/{experiment-43OJtH7R.js → experiment-DyO54FQB.js} +25 -61
  65. package/dist/experiment-DyO54FQB.js.map +1 -0
  66. package/dist/{experimentStatus-BZmU4czV.js → experimentStatus-BFrKpHAH.js} +3 -3
  67. package/dist/{experimentStatus-BZmU4czV.js.map → experimentStatus-BFrKpHAH.js.map} +1 -1
  68. package/dist/index.js +20 -20
  69. package/dist/{install-DAID6c2-.js → install-qjELyNwc.js} +15 -14
  70. package/dist/{install-DAID6c2-.js.map → install-qjELyNwc.js.map} +1 -1
  71. package/dist/install.js +1 -1
  72. package/dist/{lab-DLwRl_Ql.js → lab-UyTbokQC.js} +136 -148
  73. package/dist/lab-UyTbokQC.js.map +1 -0
  74. package/dist/lab.js +4 -3
  75. package/dist/{records-BzTcxekG.js → records-CR_pYzIP.js} +533 -335
  76. package/dist/records-CR_pYzIP.js.map +1 -0
  77. package/dist/{runtime-D6gVat6r.js → runtime-CoHhBP10.js} +417 -54
  78. package/dist/runtime-CoHhBP10.js.map +1 -0
  79. package/dist/runtime.d.ts +1 -1
  80. package/dist/runtime.js +7 -7
  81. package/dist/{shell-5ju97nOS.js → shell-BDuZf2zb.js} +10 -5
  82. package/dist/{shell-5ju97nOS.js.map → shell-BDuZf2zb.js.map} +1 -1
  83. package/dist/shell.d.ts +1 -0
  84. package/dist/shell.js +6 -6
  85. package/dist/stores/index.d.ts +1 -1
  86. package/dist/stores/index.js +2 -2
  87. package/dist/stores/settings.d.ts +4 -12
  88. package/dist/styles.css +2732 -2083
  89. package/dist/types/componentWorkflowTypes.d.ts +2 -0
  90. package/dist/types/components.d.ts +2 -0
  91. package/dist/types/generated/platformContext.d.ts +1 -0
  92. package/dist/types/generated-ui.d.ts +4 -0
  93. package/dist/types/index.d.ts +1 -1
  94. package/dist/types/jobs.d.ts +9 -0
  95. package/dist/types/platform.d.ts +1 -1
  96. package/dist/{BaseModal-DfRIuVoj.js → useDropdownState-Bb2N4m40.js} +74 -4
  97. package/dist/useDropdownState-Bb2N4m40.js.map +1 -0
  98. package/dist/{useExperimentSamples-CxcnxZ8h.js → useExperimentSamples-Dno1fFMq.js} +4 -4
  99. package/dist/{useExperimentSamples-CxcnxZ8h.js.map → useExperimentSamples-Dno1fFMq.js.map} +1 -1
  100. package/dist/{useListReorder-CcbEYxX-.js → useListReorder-CQ9OCScc.js} +183 -351
  101. package/dist/useListReorder-CQ9OCScc.js.map +1 -0
  102. package/dist/{useRackEditor-BD5NIo5s.js → useRackEditor-wL3kPrRT.js} +73 -59
  103. package/dist/useRackEditor-wL3kPrRT.js.map +1 -0
  104. package/dist/useRealtime-C3whhVvb.js +508 -0
  105. package/dist/useRealtime-C3whhVvb.js.map +1 -0
  106. package/dist/useRequest-CDkrXNU7.js +244 -0
  107. package/dist/useRequest-CDkrXNU7.js.map +1 -0
  108. package/dist/utils/time.d.ts +7 -0
  109. package/package.json +1 -1
  110. package/src/__stories__/experiment-helpers.ts +3 -3
  111. package/src/__tests__/components/AppTopBar.test.ts +257 -3
  112. package/src/__tests__/components/AppTopBarOnboarding.test.ts +160 -0
  113. package/src/__tests__/components/AppTopBarPageSelector.test.ts +125 -9
  114. package/src/__tests__/components/AppTopBarPillNav.test.ts +35 -0
  115. package/src/__tests__/components/ArtifactSaveDialog.test.ts +78 -0
  116. package/src/__tests__/components/BaseButton.test.ts +19 -0
  117. package/src/__tests__/components/BaseSelect.multiple.test.ts +87 -32
  118. package/src/__tests__/components/BaseSelect.test.ts +2 -1
  119. package/src/__tests__/components/BatchProgressList.test.ts +16 -0
  120. package/src/__tests__/components/CalendarGridPanel.test.ts +2 -2
  121. package/src/__tests__/components/ChartContainer.test.ts +11 -0
  122. package/src/__tests__/components/ChemicalFormula.test.ts +6 -3
  123. package/src/__tests__/components/DatePicker.datetime.test.ts +6 -0
  124. package/src/__tests__/components/DatePicker.test.ts +21 -0
  125. package/src/__tests__/components/DatePicker.time.test.ts +2 -2
  126. package/src/__tests__/components/EmptyState.test.ts +1 -1
  127. package/src/__tests__/components/ExperimentPopover.test.ts +125 -16
  128. package/src/__tests__/components/ExperimentSelectorModal.test.ts +153 -14
  129. package/src/__tests__/components/GeneratedPluginView.test.ts +23 -2
  130. package/src/__tests__/components/InstrumentStateBadge.test.ts +4 -4
  131. package/src/__tests__/components/JobsStatusTray.test.ts +373 -71
  132. package/src/__tests__/components/PluginWorkspaceView.test.ts +63 -1
  133. package/src/__tests__/components/ResourcePickerListInternal.test.ts +0 -20
  134. package/src/__tests__/components/SampleSelector.test.ts +33 -8
  135. package/src/__tests__/components/SequenceProgressBar.test.ts +12 -0
  136. package/src/__tests__/components/SettingsModal.test.ts +9 -2
  137. package/src/__tests__/components/StepWizard.test.ts +11 -0
  138. package/src/__tests__/components/WellPlate.decoration.test.ts +11 -4
  139. package/src/__tests__/components/deprecationTags.test.ts +1 -1
  140. package/src/__tests__/composables/useAppExperiment.test.ts +27 -1
  141. package/src/__tests__/composables/useCalendarGrid.test.ts +4 -2
  142. package/src/__tests__/composables/useExperimentSelector.test.ts +111 -0
  143. package/src/__tests__/composables/useJobCenter.test.ts +262 -3
  144. package/src/__tests__/composables/useOnboarding.test.ts +317 -0
  145. package/src/__tests__/docs/frontendDocsCatalog.test.ts +4 -3
  146. package/src/__tests__/stores/settings.test.ts +21 -21
  147. package/src/__tests__/styles/baseControlsRules.test.ts +6 -2
  148. package/src/__tests__/styles/controlRefreshRules.test.ts +0 -6
  149. package/src/__tests__/styles/cssTokens.test.ts +6 -3
  150. package/src/__tests__/styles/menusShellRefresh.test.ts +22 -12
  151. package/src/__tests__/styles/paletteTokens.test.ts +44 -0
  152. package/src/__tests__/styles/v2AuditRules.test.ts +104 -0
  153. package/src/__tests__/utils/plotlyTemplate.test.ts +4 -4
  154. package/src/__tests__/utils/time.test.ts +18 -1
  155. package/src/components/AdductText.story.vue +7 -0
  156. package/src/components/AdductText.vue +1 -1
  157. package/src/components/AlertBox.story.vue +2 -2
  158. package/src/components/AlertBox.vue +18 -16
  159. package/src/components/AppSidebar.story.vue +0 -28
  160. package/src/components/AppTopBar.onboarding.story.vue +69 -0
  161. package/src/components/AppTopBar.story.vue +105 -15
  162. package/src/components/AppTopBar.vue +248 -122
  163. package/src/components/ArtifactSaveDialog.story.vue +23 -0
  164. package/src/components/ArtifactSaveDialog.vue +102 -12
  165. package/src/components/AuditTrail.story.vue +2 -1
  166. package/src/components/AuditTrail.vue +2 -21
  167. package/src/components/Avatar.vue +10 -14
  168. package/src/components/BaseButton.vue +16 -2
  169. package/src/components/BaseSelect.multiple.story.vue +13 -2
  170. package/src/components/BaseSelect.vue +4 -3
  171. package/src/components/BatchProgressList.vue +35 -25
  172. package/src/components/ChartContainer.story.vue +2 -1
  173. package/src/components/ChartContainer.vue +8 -6
  174. package/src/components/ConfirmDialog.story.vue +1 -1
  175. package/src/components/EmptyState.vue +1 -1
  176. package/src/components/ExperimentPopover.story.vue +165 -53
  177. package/src/components/ExperimentPopover.vue +169 -187
  178. package/src/components/ExperimentSelectorModal.story.vue +73 -31
  179. package/src/components/ExperimentSelectorModal.vue +144 -111
  180. package/src/components/FormField.story.vue +8 -48
  181. package/src/components/GeneratedPluginView.vue +11 -10
  182. package/src/components/GeneratedResultRenderer.vue +3 -4
  183. package/src/components/InstrumentStateBadge.vue +1 -1
  184. package/src/components/JobsStatusTray.story.vue +97 -43
  185. package/src/components/JobsStatusTray.vue +287 -290
  186. package/src/components/LayoutResizeHandle.story.vue +65 -4
  187. package/src/components/LoadingSpinner.vue +1 -1
  188. package/src/components/NumberInput.vue +3 -6
  189. package/src/components/PluginIcon.story.vue +2 -10
  190. package/src/components/PluginIcon.vue +2 -2
  191. package/src/components/PluginWorkspaceView.props.ts +3 -0
  192. package/src/components/PluginWorkspaceView.story.vue +1 -1
  193. package/src/components/PluginWorkspaceView.vue +17 -0
  194. package/src/components/RuntimeUpdateNotice.vue +1 -1
  195. package/src/components/SampleSelector.story.vue +22 -7
  196. package/src/components/SampleSelector.vue +34 -37
  197. package/src/components/SampleSelectorGroupNode.vue +1 -1
  198. package/src/components/SectionCard.story.vue +35 -2
  199. package/src/components/SequenceProgressBar.story.vue +9 -0
  200. package/src/components/SequenceProgressBar.vue +6 -1
  201. package/src/components/SettingsModal.schema.ts +1 -1
  202. package/src/components/SettingsModal.vue +9 -14
  203. package/src/components/SmartGroupFieldRecipe.story.vue +1 -1
  204. package/src/components/SmartGroupManual.story.vue +1 -1
  205. package/src/components/StepWizard.story.vue +33 -0
  206. package/src/components/StepWizard.vue +8 -1
  207. package/src/components/WellPlate.story.vue +3 -1
  208. package/src/components/WellPlate.vue +7 -0
  209. package/src/components/internal/AppTopBarOnboardingInternal.vue +172 -0
  210. package/src/components/internal/AppTopBarPageSelectorInternal.vue +140 -72
  211. package/src/components/internal/AppTopBarPillNavInternal.vue +33 -2
  212. package/src/components/internal/DatePickerDateInternal.vue +16 -40
  213. package/src/components/internal/DatePickerDateTimeInternal.vue +3 -13
  214. package/src/components/internal/DatePickerTimeInternal.vue +5 -8
  215. package/src/components/internal/OnboardingLayerInternal.vue +173 -0
  216. package/src/components/internal/ResourcePickerListInternal.vue +45 -85
  217. package/src/components/internal/SelectMultipleInternal.vue +182 -65
  218. package/src/components/internal/SelectSearchableInternal.vue +2 -3
  219. package/src/components/internal/WorkspaceShellInternal.vue +12 -0
  220. package/src/composables/createClient.ts +2 -0
  221. package/src/composables/index.ts +1 -0
  222. package/src/composables/pluginIdentity.ts +31 -0
  223. package/src/composables/pluginWorkspaceModel.ts +2 -2
  224. package/src/composables/useAppExperiment.ts +20 -0
  225. package/src/composables/useCalendarGrid.ts +4 -3
  226. package/src/composables/useExperimentSelector.ts +77 -31
  227. package/src/composables/useJobCenter.ts +188 -6
  228. package/src/composables/useOnboarding.ts +465 -0
  229. package/src/composables/usePluginWorkspace.ts +1 -1
  230. package/src/runtime.ts +2 -1
  231. package/src/shell.ts +17 -0
  232. package/src/stores/index.ts +0 -2
  233. package/src/stores/settings.ts +20 -50
  234. package/src/styles/components/adduct-text.css +13 -5
  235. package/src/styles/components/alert-box.css +39 -58
  236. package/src/styles/components/app-layout.css +7 -5
  237. package/src/styles/components/app-page-selector.css +121 -44
  238. package/src/styles/components/app-pill-nav.css +11 -12
  239. package/src/styles/components/app-sidebar.css +9 -18
  240. package/src/styles/components/app-top-bar.css +219 -55
  241. package/src/styles/components/artifact-save-dialog.css +153 -2
  242. package/src/styles/components/audit-trail.css +16 -19
  243. package/src/styles/components/avatar.css +6 -4
  244. package/src/styles/components/batch-progress-list.css +38 -36
  245. package/src/styles/components/button.css +36 -59
  246. package/src/styles/components/calendar.css +12 -12
  247. package/src/styles/components/chart-container.css +34 -23
  248. package/src/styles/components/checkbox.css +2 -12
  249. package/src/styles/components/collapsible-card.css +27 -29
  250. package/src/styles/components/confirm-dialog.css +13 -14
  251. package/src/styles/components/dataframe.css +13 -5
  252. package/src/styles/components/date-picker.css +80 -92
  253. package/src/styles/components/datetime-picker.css +31 -43
  254. package/src/styles/components/divider.css +20 -20
  255. package/src/styles/components/dose-calculator.css +3 -3
  256. package/src/styles/components/empty-state.css +20 -17
  257. package/src/styles/components/experiment-code-badge.css +2 -0
  258. package/src/styles/components/experiment-popover.css +174 -329
  259. package/src/styles/components/experiment-selector-modal.css +88 -56
  260. package/src/styles/components/file-picker.css +3 -3
  261. package/src/styles/components/file-uploader.css +38 -49
  262. package/src/styles/components/form-builder.css +3 -3
  263. package/src/styles/components/formula-input.css +1 -1
  264. package/src/styles/components/icon-button.css +18 -24
  265. package/src/styles/components/input.css +5 -4
  266. package/src/styles/components/instrument-monitor.css +13 -15
  267. package/src/styles/components/jobs-status-tray.css +140 -296
  268. package/src/styles/components/layout-resize-handle.css +59 -16
  269. package/src/styles/components/modal.css +4 -6
  270. package/src/styles/components/molecule-input.css +2 -2
  271. package/src/styles/components/multi-select.css +65 -117
  272. package/src/styles/components/number-input.css +26 -19
  273. package/src/styles/components/onboarding.css +368 -0
  274. package/src/styles/components/pill.css +3 -2
  275. package/src/styles/components/plate-editor.css +0 -1
  276. package/src/styles/components/plugin-icon.css +26 -23
  277. package/src/styles/components/popover.css +2 -2
  278. package/src/styles/components/presence-avatars.css +1 -1
  279. package/src/styles/components/progress-bar.css +3 -3
  280. package/src/styles/components/protocol-step-editor.css +1 -3
  281. package/src/styles/components/resource-card.css +2 -2
  282. package/src/styles/components/resource-picker-list.css +6 -57
  283. package/src/styles/components/sample-hierarchy-tree.css +4 -4
  284. package/src/styles/components/sample-selector.css +138 -79
  285. package/src/styles/components/schedule-calendar.css +8 -8
  286. package/src/styles/components/searchable-select.css +12 -12
  287. package/src/styles/components/section-card.css +54 -49
  288. package/src/styles/components/segmented-control.css +18 -15
  289. package/src/styles/components/select.css +3 -3
  290. package/src/styles/components/sequence-input.css +2 -2
  291. package/src/styles/components/sequence-progress-bar.css +17 -8
  292. package/src/styles/components/settings-modal.css +7 -2
  293. package/src/styles/components/smart-group.css +18 -18
  294. package/src/styles/components/step-wizard.css +52 -16
  295. package/src/styles/components/tabs.css +2 -2
  296. package/src/styles/components/textarea.css +3 -3
  297. package/src/styles/components/time-picker.css +36 -21
  298. package/src/styles/components/toast.css +12 -10
  299. package/src/styles/components/toggle.css +1 -11
  300. package/src/styles/components/tooltip.css +10 -9
  301. package/src/styles/components/unit-input.css +8 -7
  302. package/src/styles/components/well-plate.css +9 -2
  303. package/src/styles/index.css +1 -0
  304. package/src/styles/variables.css +241 -78
  305. package/src/types/componentWorkflowTypes.ts +2 -0
  306. package/src/types/components.ts +2 -0
  307. package/src/types/generated/platformContext.ts +1 -0
  308. package/src/types/generated-ui.ts +4 -0
  309. package/src/types/index.ts +1 -0
  310. package/src/types/jobs.ts +10 -0
  311. package/src/types/platform.ts +1 -1
  312. package/src/utils/time.ts +21 -0
  313. package/dist/ActionMenu-CScINahU.js.map +0 -1
  314. package/dist/AppSidebar-BmiiPfz9.js.map +0 -1
  315. package/dist/BaseModal-DfRIuVoj.js.map +0 -1
  316. package/dist/ExperimentPopover-C4sGw-is.js +0 -359
  317. package/dist/ExperimentPopover-C4sGw-is.js.map +0 -1
  318. package/dist/ExperimentSelectorModal-D-9z7cNx.js.map +0 -1
  319. package/dist/SettingsModal-CSLE31yg.js.map +0 -1
  320. package/dist/data-C2PwI_dn.js.map +0 -1
  321. package/dist/experiment-43OJtH7R.js.map +0 -1
  322. package/dist/lab-DLwRl_Ql.js.map +0 -1
  323. package/dist/records-BzTcxekG.js.map +0 -1
  324. package/dist/runtime-D6gVat6r.js.map +0 -1
  325. package/dist/useListReorder-CcbEYxX-.js.map +0 -1
  326. package/dist/useRackEditor-BD5NIo5s.js.map +0 -1
  327. package/dist/useRealtime-PalKue84.js +0 -696
  328. package/dist/useRealtime-PalKue84.js.map +0 -1
  329. package/dist/useRequest-D5JDfsgZ.js +0 -76
  330. package/dist/useRequest-D5JDfsgZ.js.map +0 -1
@@ -42,7 +42,6 @@ const {
42
42
  weekDays,
43
43
  monthYear,
44
44
  calendarDays,
45
- isDateDisabled,
46
45
  formatDateValue,
47
46
  setCurrentMonthFromDate,
48
47
  prevMonth,
@@ -58,14 +57,7 @@ const selectedDate = computed(() => {
58
57
  return isNaN(date.getTime()) ? null : date
59
58
  })
60
59
 
61
- const displayValue = computed(() => {
62
- if (!selectedDate.value) return ''
63
- return selectedDate.value.toLocaleDateString('en-US', {
64
- year: 'numeric',
65
- month: 'short',
66
- day: 'numeric',
67
- })
68
- })
60
+ const displayValue = computed(() => (selectedDate.value ? formatDateValue(selectedDate.value) : ''))
69
61
 
70
62
  function selectDate(day: CalendarGridDay) {
71
63
  if (day.isDisabled || props.disabled) return
@@ -73,15 +65,6 @@ function selectDate(day: CalendarGridDay) {
73
65
  close()
74
66
  }
75
67
 
76
- function goToToday() {
77
- const today = new Date()
78
- setCurrentMonthFromDate(today)
79
- if (!isDateDisabled(today)) {
80
- emit('update:modelValue', formatDateValue(today))
81
- close()
82
- }
83
- }
84
-
85
68
  function clear() {
86
69
  emit('update:modelValue', undefined)
87
70
  close()
@@ -167,6 +150,11 @@ onBeforeUnmount(stopPositioning)
167
150
  <template>
168
151
  <div ref="container" class="mint-date-picker">
169
152
  <div class="mint-date-picker__input-wrapper">
153
+ <div class="mint-date-picker__icon">
154
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
155
+ <path d="M8 2v4" /><path d="M16 2v4" /><rect width="18" height="18" x="3" y="4" rx="2" /><path d="M3 10h18" />
156
+ </svg>
157
+ </div>
170
158
  <input
171
159
  ref="triggerRef"
172
160
  type="text"
@@ -185,11 +173,17 @@ onBeforeUnmount(stopPositioning)
185
173
  @click="toggleCalendar"
186
174
  @keydown="handleTriggerKeydown"
187
175
  />
188
- <div class="mint-date-picker__icon">
189
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
190
- <path d="M8 2v4" /><path d="M16 2v4" /><rect width="18" height="18" x="3" y="4" rx="2" /><path d="M3 10h18" />
176
+ <button
177
+ v-if="clearable && modelValue && !disabled"
178
+ type="button"
179
+ class="mint-date-picker__clear-btn"
180
+ aria-label="Clear date"
181
+ @click.stop="clear"
182
+ >
183
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
184
+ <path d="M18 6 6 18" /><path d="m6 6 12 12" />
191
185
  </svg>
192
- </div>
186
+ </button>
193
187
  </div>
194
188
 
195
189
  <Teleport to="body">
@@ -218,24 +212,6 @@ onBeforeUnmount(stopPositioning)
218
212
  @next-month="nextMonth"
219
213
  @select="selectDate"
220
214
  />
221
-
222
- <div class="mint-date-picker__footer">
223
- <button
224
- type="button"
225
- class="mint-date-picker__footer-btn mint-date-picker__today-btn"
226
- @click="goToToday"
227
- >
228
- Today
229
- </button>
230
- <button
231
- v-if="clearable && modelValue"
232
- type="button"
233
- class="mint-date-picker__footer-btn mint-date-picker__clear-btn"
234
- @click="clear"
235
- >
236
- Clear
237
- </button>
238
- </div>
239
215
  </div>
240
216
  </Transition>
241
217
  </Teleport>
@@ -76,17 +76,12 @@ const selectedTimeStr = computed(() => {
76
76
 
77
77
  const displayValue = computed(() => {
78
78
  if (!selectedDate.value) return ''
79
- const dateStr = selectedDate.value.toLocaleDateString(props.locale, {
80
- year: 'numeric',
81
- month: 'short',
82
- day: 'numeric',
83
- })
84
79
  const timeStr = formatTime(
85
80
  selectedDate.value.getHours(),
86
81
  selectedDate.value.getMinutes(),
87
82
  props.timeFormat,
88
83
  )
89
- return `${dateStr} ${timeStr}`
84
+ return `${formatDateValue(selectedDate.value)} ${timeStr}`
90
85
  })
91
86
 
92
87
  // Time slots
@@ -198,8 +193,8 @@ watch(isOpen, async (opened) => {
198
193
  <div ref="root" class="mint-datetime-picker">
199
194
  <div class="mint-datetime-picker__input-wrapper">
200
195
  <div class="mint-datetime-picker__icon-calendar">
201
- <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
202
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
196
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
197
+ <path d="M8 2v4" /><path d="M16 2v4" /><rect width="18" height="18" x="3" y="4" rx="2" /><path d="M3 10h18" />
203
198
  </svg>
204
199
  </div>
205
200
  <input
@@ -221,11 +216,6 @@ watch(isOpen, async (opened) => {
221
216
  @click="toggleDropdown"
222
217
  @keydown="handleTriggerKeydown"
223
218
  />
224
- <div class="mint-datetime-picker__icon-clock">
225
- <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
226
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
227
- </svg>
228
- </div>
229
219
  </div>
230
220
 
231
221
  <Transition
@@ -210,6 +210,11 @@ watch(isOpen, (open) => {
210
210
  <template>
211
211
  <div ref="root" class="mint-time-picker" @keydown="handleKeydown">
212
212
  <div class="mint-time-picker__input-wrapper">
213
+ <div class="mint-time-picker__icon">
214
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
215
+ <circle cx="12" cy="12" r="10" /><path d="M12 6v6l4 2" />
216
+ </svg>
217
+ </div>
213
218
  <input
214
219
  ref="trigger"
215
220
  type="text"
@@ -241,11 +246,6 @@ watch(isOpen, (open) => {
241
246
  <path d="M18 6 6 18" /><path d="m6 6 12 12" />
242
247
  </svg>
243
248
  </button>
244
- <div class="mint-time-picker__icon">
245
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
246
- <circle cx="12" cy="12" r="10" /><path d="M12 6v6l4 2" />
247
- </svg>
248
- </div>
249
249
  </div>
250
250
 
251
251
  <Transition
@@ -284,9 +284,6 @@ watch(isOpen, (open) => {
284
284
  >
285
285
  <span class="mint-time-picker__slot-time">{{ formatTimeSlot(slot, format) }}</span>
286
286
  <span v-if="slotReason(slot)" class="mint-time-picker__slot-reason">{{ slotReason(slot) }}</span>
287
- <svg class="mint-menu-item__check" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
288
- <path d="M3.5 8.5l3 3 6-7" />
289
- </svg>
290
287
  </li>
291
288
  </ul>
292
289
  </div>
@@ -0,0 +1,173 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * The tour layer: a scrim with a hole over the anchor, the step card, and the
4
+ * what's-new dots. AppTopBar renders it when the app provides onboarding.
5
+ */
6
+ import { computed, nextTick, onBeforeUnmount, ref, useId, watch } from 'vue'
7
+ import { autoUpdate, computePosition, flip, offset, shift } from '@floating-ui/dom'
8
+ import { X } from 'lucide-vue-next'
9
+ import BaseButton from '../BaseButton.vue'
10
+ import { useEventListener } from '../../composables/useEventListener'
11
+ import type { OnboardingState } from '../../composables/useOnboarding'
12
+
13
+ const props = defineProps<{ state: OnboardingState }>()
14
+
15
+ // Space between the anchor and the edge of the hole.
16
+ const HOLE_PAD = 4
17
+
18
+ const active = computed(() => props.state.active.value)
19
+ const card = ref<HTMLElement | null>(null)
20
+ const hole = ref<DOMRect | null>(null)
21
+ const cardPosition = ref({ x: 0, y: 0 })
22
+ const titleId = useId()
23
+ let stopAutoUpdate: (() => void) | undefined
24
+
25
+ async function position() {
26
+ const current = active.value
27
+ if (!current || !card.value) return
28
+ hole.value = current.element.getBoundingClientRect()
29
+ const { x, y } = await computePosition(current.element, card.value, {
30
+ strategy: 'fixed',
31
+ placement: current.step.placement ?? 'bottom',
32
+ middleware: [offset(12), flip(), shift({ padding: 12 })],
33
+ })
34
+ // The step may have changed while the position was computed.
35
+ if (active.value === current) cardPosition.value = { x, y }
36
+ }
37
+
38
+ // Focus goes back where it was when the run ends.
39
+ let returnFocus: HTMLElement | null = null
40
+ watch(active, async (current, previous) => {
41
+ stopAutoUpdate?.()
42
+ stopAutoUpdate = undefined
43
+ hole.value = null
44
+ if (current && !previous) returnFocus = document.activeElement as HTMLElement | null
45
+ if (!current) {
46
+ if (returnFocus?.isConnected) returnFocus.focus()
47
+ returnFocus = null
48
+ return
49
+ }
50
+ await nextTick()
51
+ if (!card.value || active.value !== current) return
52
+ current.element.scrollIntoView({ block: 'nearest', inline: 'nearest' })
53
+ stopAutoUpdate = autoUpdate(current.element, card.value, () => void position())
54
+ // A click step: the keyboard user presses the control itself.
55
+ if (current.step.advanceOn === 'click') current.element.focus()
56
+ // Otherwise the card itself: no focus ring on load, and Tab reaches Back and Next.
57
+ else card.value.focus()
58
+ }, { immediate: true })
59
+ onBeforeUnmount(() => stopAutoUpdate?.())
60
+
61
+ // The layer is its own focus trap: Tab cycles over the card's buttons (and the
62
+ // anchor on a click step), never the page behind; from the card itself Tab goes
63
+ // to the first stop and Shift+Tab to the last.
64
+ useEventListener(document, 'keydown', (event) => {
65
+ const current = active.value
66
+ if (!current || !card.value) return
67
+ // Keys belong to the tour only while focus is on its card, its anchor, or nowhere.
68
+ const focused = document.activeElement
69
+ if (focused && focused !== document.body && !card.value.contains(focused) && focused !== current.element) return
70
+ const onCard = focused === card.value
71
+ if (event.key === 'Escape') {
72
+ event.stopPropagation()
73
+ props.state.dismiss()
74
+ } else if (event.key === 'Tab') {
75
+ const buttons = [...card.value.querySelectorAll<HTMLElement>('button')]
76
+ const stops = current.step.advanceOn === 'click' ? [current.element, ...buttons] : buttons
77
+ const at = stops.indexOf(document.activeElement as HTMLElement)
78
+ const target = at === -1 ? (event.shiftKey ? stops.length - 1 : 0) : (at + (event.shiftKey ? -1 : 1) + stops.length) % stops.length
79
+ event.preventDefault()
80
+ stops[target].focus()
81
+ } else if (event.key === 'Enter' && onCard && current.step.advanceOn !== 'click') {
82
+ event.preventDefault()
83
+ props.state.next()
84
+ }
85
+ }, { capture: true })
86
+
87
+ const holeStyle = computed(() => hole.value && {
88
+ left: `${hole.value.left - HOLE_PAD}px`,
89
+ top: `${hole.value.top - HOLE_PAD}px`,
90
+ width: `${hole.value.width + 2 * HOLE_PAD}px`,
91
+ height: `${hole.value.height + 2 * HOLE_PAD}px`,
92
+ })
93
+ // advanceOn 'click': cut the hole out of the click blocker, so the anchor takes the click.
94
+ const blockerStyle = computed(() => {
95
+ const rect = hole.value
96
+ if (!rect || active.value?.step.advanceOn !== 'click') return undefined
97
+ const [x, y, w, h] = [rect.left - HOLE_PAD, rect.top - HOLE_PAD, rect.width + 2 * HOLE_PAD, rect.height + 2 * HOLE_PAD]
98
+ return { clipPath: `path(evenodd, 'M0 0H${window.innerWidth}V${window.innerHeight}H0Z M${x} ${y}h${w}v${h}h${-w}Z')` }
99
+ })
100
+ const isLast = computed(() => !!active.value && active.value.index === active.value.count - 1)
101
+ const nextLabel = computed(() => active.value?.news ? 'Got it' : isLast.value ? 'Done' : 'Next')
102
+
103
+ // What's-new dots: one on each element with unseen news, hidden while a card shows.
104
+ const dots = ref<Array<{ id: string; title: string; x: number; y: number }>>([])
105
+ let frame = 0
106
+ function placeDots() {
107
+ cancelAnimationFrame(frame)
108
+ frame = requestAnimationFrame(() => {
109
+ dots.value = active.value ? [] : props.state.news.value.flatMap((item) => {
110
+ if (!item.unseen) return []
111
+ const element = document.querySelector(`[data-onboarding="${CSS.escape(item.anchor)}"]`)
112
+ if (!element) return []
113
+ const rect = element.getBoundingClientRect()
114
+ return rect.width ? [{ id: item.id, title: item.title, x: rect.right, y: rect.top }] : []
115
+ })
116
+ })
117
+ }
118
+ const observer = new MutationObserver(placeDots)
119
+ watch(() => props.state.unseenNews.value > 0, (watching) => {
120
+ observer.disconnect()
121
+ if (watching) observer.observe(document.body, { childList: true, subtree: true })
122
+ placeDots()
123
+ }, { immediate: true })
124
+ watch(active, placeDots)
125
+ useEventListener(window, 'resize', placeDots)
126
+ useEventListener(window, 'scroll', placeDots, { capture: true, passive: true })
127
+ onBeforeUnmount(() => {
128
+ observer.disconnect()
129
+ cancelAnimationFrame(frame)
130
+ })
131
+ </script>
132
+
133
+ <template>
134
+ <Teleport to="body">
135
+ <button
136
+ v-for="dot in dots"
137
+ :key="dot.id"
138
+ type="button"
139
+ class="mint-onboarding__dot"
140
+ :style="{ left: `${dot.x}px`, top: `${dot.y}px` }"
141
+ :aria-label="`New: ${dot.title}`"
142
+ @click="state.showNews(dot.id)"
143
+ />
144
+ <div v-if="active" class="mint-onboarding">
145
+ <div class="mint-onboarding__blocker" :style="blockerStyle" />
146
+ <div v-if="holeStyle" class="mint-onboarding__hole" :style="holeStyle" />
147
+ <div
148
+ ref="card"
149
+ class="mint-onboarding__card"
150
+ role="dialog"
151
+ aria-modal="true"
152
+ :aria-labelledby="titleId"
153
+ tabindex="-1"
154
+ :style="{ left: `${cardPosition.x}px`, top: `${cardPosition.y}px` }"
155
+ >
156
+ <button type="button" class="mint-onboarding__close" :aria-label="active.news ? 'Close' : 'Close tour'" @click="state.dismiss()">
157
+ <X :size="14" aria-hidden="true" />
158
+ </button>
159
+ <span v-if="active.count > 1" class="mint-onboarding__count">
160
+ <span aria-hidden="true">{{ active.index + 1 }} / {{ active.count }}</span>
161
+ <span class="mint-onboarding__sr">Step {{ active.index + 1 }} of {{ active.count }}</span>
162
+ </span>
163
+ <p :id="titleId" class="mint-onboarding__title">{{ active.step.title }}</p>
164
+ <p class="mint-onboarding__body">{{ active.step.body }}</p>
165
+ <div class="mint-onboarding__footer">
166
+ <span v-if="active.step.advanceOn === 'click'" class="mint-onboarding__hint">Click the highlighted control.</span>
167
+ <BaseButton v-if="active.index > 0" variant="ghost" size="sm" @click="state.back()">Back</BaseButton>
168
+ <BaseButton v-if="active.step.advanceOn !== 'click'" size="sm" @click="state.next()">{{ nextLabel }}</BaseButton>
169
+ </div>
170
+ </div>
171
+ </div>
172
+ </Teleport>
173
+ </template>
@@ -1,11 +1,11 @@
1
1
  <script setup lang="ts" generic="T">
2
2
  /**
3
- * Searchable, optionally grouped single-select list shared by the experiment and
3
+ * Searchable single-select list shared by the experiment and
4
4
  * artifact selector modals: two-line rows (title, then code + meta) with status and date
5
5
  * in a right-hand column, a filled selected row, skeleton,
6
6
  * error and empty states, and the combobox keyboard model (↑ ↓ Enter).
7
7
  */
8
- import { computed, nextTick, reactive, ref, useId, watch } from 'vue'
8
+ import { computed, nextTick, ref, useId, watch } from 'vue'
9
9
  import BaseInput from '../BaseInput.vue'
10
10
  import Skeleton from '../Skeleton.vue'
11
11
  import EmptyState from '../EmptyState.vue'
@@ -26,8 +26,6 @@ export interface ResourcePickerRow {
26
26
  const props = withDefaults(
27
27
  defineProps<{
28
28
  items: T[]
29
- /** When set, rows render under collapsible group headers in this order. */
30
- groups?: { label: string; items: T[] }[] | null
31
29
  itemKey: (item: T) => string | number
32
30
  describe: (item: T) => ResourcePickerRow
33
31
  selectedKey?: string | number | null
@@ -39,9 +37,10 @@ const props = withDefaults(
39
37
  error?: string | null
40
38
  emptyTitle?: string
41
39
  emptyDescription?: string
40
+ /** Focus the search field when the list mounts (the modal's focus trap honours `autofocus`). */
41
+ autofocusSearch?: boolean
42
42
  }>(),
43
43
  {
44
- groups: null,
45
44
  selectedKey: null,
46
45
  placeholder: 'Search…',
47
46
  loading: false,
@@ -57,50 +56,33 @@ const emit = defineEmits<{
57
56
  defineSlots<{
58
57
  /** Extra filters on the search row. */
59
58
  filters?: () => unknown
60
- /** A second filter row under the search. */
61
- advanced?: () => unknown
62
59
  /** Row controls before the check; keys pressed inside them never select the row. */
63
60
  actions?: (props: { item: T }) => unknown
64
61
  }>()
65
62
 
66
63
  const listId = `mint-resource-picker-${useId().replace(/:/g, '')}`
67
- const collapsed = reactive(new Set<string>())
68
64
  const activeIndex = ref(-1)
69
65
  const listRef = ref<HTMLElement | null>(null)
70
66
 
71
- const visibleGroups = computed(() =>
72
- props.groups?.map((group) => ({
73
- ...group,
74
- rows: collapsed.has(group.label) ? [] : group.items,
75
- })),
76
- )
77
- /** Keyboard order: the rows on screen, top to bottom. */
78
- const flat = computed(() =>
79
- visibleGroups.value ? visibleGroups.value.flatMap((group) => group.rows) : props.items,
80
- )
81
- const indexByKey = computed(() => new Map(flat.value.map((item, i) => [props.itemKey(item), i])))
67
+ const indexByKey = computed(() => new Map(props.items.map((item, i) => [props.itemKey(item), i])))
82
68
  const showList = computed(() => !props.loading && !props.error && props.items.length > 0)
83
69
 
84
70
  function optionId(item: T): string {
85
71
  return `${listId}-${props.itemKey(item)}`
86
72
  }
87
73
  const activeDescendant = computed(() => {
88
- const item = flat.value[activeIndex.value]
74
+ const item = props.items[activeIndex.value]
89
75
  return item === undefined ? undefined : optionId(item)
90
76
  })
91
77
 
92
78
  function indexOf(item: T): number {
93
79
  return indexByKey.value.get(props.itemKey(item)) ?? -1
94
80
  }
95
- function toggleGroup(label: string) {
96
- if (collapsed.has(label)) collapsed.delete(label)
97
- else collapsed.add(label)
98
- }
99
81
  function keydown(event: KeyboardEvent) {
100
- // Keys belong to the search combobox; a focused header, filter or row action keeps its own Enter.
82
+ // Keys belong to the search combobox; a focused filter or row action keeps its own Enter.
101
83
  const target = event.target as HTMLElement | null
102
84
  if (target !== event.currentTarget && !target?.closest('.mint-resource-picker__search')) return
103
- const rows = flat.value
85
+ const rows = props.items
104
86
  if (!rows.length) return
105
87
  if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
106
88
  event.preventDefault()
@@ -120,7 +102,7 @@ function keydown(event: KeyboardEvent) {
120
102
  }
121
103
 
122
104
  watch(
123
- () => [props.items, props.groups],
105
+ () => props.items,
124
106
  () => {
125
107
  activeIndex.value = -1
126
108
  },
@@ -136,6 +118,7 @@ watch(
136
118
  :placeholder="placeholder"
137
119
  size="sm"
138
120
  type="search"
121
+ :autofocus="autofocusSearch"
139
122
  role="combobox"
140
123
  :aria-label="`Search ${label.toLowerCase()}`"
141
124
  :aria-expanded="showList"
@@ -151,7 +134,6 @@ watch(
151
134
  </BaseInput>
152
135
  <slot name="filters" />
153
136
  </div>
154
- <slot name="advanced" />
155
137
 
156
138
  <div v-if="loading" class="mint-resource-picker__frame" aria-busy="true">
157
139
  <div v-for="n in 4" :key="n" class="mint-resource-picker__skeleton-row">
@@ -174,64 +156,42 @@ watch(
174
156
  role="listbox"
175
157
  :aria-label="label"
176
158
  >
177
- <template v-for="group in visibleGroups ?? [{ label: '', items, rows: items }]" :key="group.label">
178
- <button
179
- v-if="visibleGroups"
180
- type="button"
181
- class="mint-resource-picker__group"
182
- :aria-expanded="!collapsed.has(group.label)"
183
- @click="toggleGroup(group.label)"
184
- >
185
- <svg
186
- class="mint-resource-picker__chevron"
187
- viewBox="0 0 16 16"
188
- fill="none"
189
- stroke="currentColor"
190
- stroke-width="1.5"
191
- aria-hidden="true"
159
+ <div
160
+ v-for="item in items"
161
+ :id="optionId(item)"
162
+ :key="itemKey(item)"
163
+ role="option"
164
+ :aria-selected="itemKey(item) === selectedKey"
165
+ class="mint-resource-picker__row"
166
+ :class="{
167
+ 'mint-resource-picker__row--selected': itemKey(item) === selectedKey,
168
+ 'mint-resource-picker__row--active': indexOf(item) === activeIndex,
169
+ }"
170
+ @click="emit('select', item)"
171
+ @mouseenter="activeIndex = indexOf(item)"
172
+ >
173
+ <span class="mint-resource-picker__text">
174
+ <span class="mint-resource-picker__title">{{ describe(item).title }}</span>
175
+ <span v-if="describe(item).code || describe(item).meta?.length" class="mint-resource-picker__meta"
176
+ ><span v-if="describe(item).code" class="mint-resource-picker__code mint-exp-code mint-exp-code--sm">{{
177
+ describe(item).code
178
+ }}</span
179
+ ><span v-if="describe(item).meta?.length">{{ describe(item).meta!.join(' · ') }}</span></span
192
180
  >
193
- <path d="M4 6l4 4 4-4" />
194
- </svg>
195
- <span class="mint-resource-picker__group-label">{{ group.label }}</span>
196
- <span class="mint-resource-picker__group-count">{{ group.items.length }}</span>
197
- </button>
198
- <div
199
- v-for="item in group.rows"
200
- :id="optionId(item)"
201
- :key="itemKey(item)"
202
- role="option"
203
- :aria-selected="itemKey(item) === selectedKey"
204
- class="mint-resource-picker__row"
205
- :class="{
206
- 'mint-resource-picker__row--selected': itemKey(item) === selectedKey,
207
- 'mint-resource-picker__row--active': indexOf(item) === activeIndex,
208
- }"
209
- @click="emit('select', item)"
210
- @mouseenter="activeIndex = indexOf(item)"
211
- >
212
- <span class="mint-resource-picker__text">
213
- <span class="mint-resource-picker__title">{{ describe(item).title }}</span>
214
- <span v-if="describe(item).code || describe(item).meta?.length" class="mint-resource-picker__meta"
215
- ><span v-if="describe(item).code" class="mint-resource-picker__code mint-exp-code mint-exp-code--sm">{{
216
- describe(item).code
217
- }}</span
218
- ><span v-if="describe(item).meta?.length">{{ describe(item).meta!.join(' · ') }}</span></span
219
- >
220
- </span>
221
- <span v-if="describe(item).status || describe(item).date" class="mint-resource-picker__aside">
222
- <span
223
- v-if="describe(item).status"
224
- class="mint-resource-picker__status"
225
- :class="`mint-resource-picker__status--${describe(item).status!.tone}`"
226
- >{{ describe(item).status!.label }}</span
227
- >
228
- <span v-if="describe(item).date" class="mint-resource-picker__date">{{ describe(item).date }}</span>
229
- </span>
230
- <span v-if="$slots.actions" class="mint-resource-picker__actions" @click.stop>
231
- <slot name="actions" :item="item" />
232
- </span>
233
- </div>
234
- </template>
181
+ </span>
182
+ <span v-if="describe(item).status || describe(item).date" class="mint-resource-picker__aside">
183
+ <span
184
+ v-if="describe(item).status"
185
+ class="mint-resource-picker__status"
186
+ :class="`mint-resource-picker__status--${describe(item).status!.tone}`"
187
+ >{{ describe(item).status!.label }}</span
188
+ >
189
+ <span v-if="describe(item).date" class="mint-resource-picker__date">{{ describe(item).date }}</span>
190
+ </span>
191
+ <span v-if="$slots.actions" class="mint-resource-picker__actions" @click.stop>
192
+ <slot name="actions" :item="item" />
193
+ </span>
194
+ </div>
235
195
  </div>
236
196
  </div>
237
197
  </template>