@morscherlab/mint-sdk 1.4.0-beta.1 → 1.4.0-beta.11

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 (266) hide show
  1. package/dist/{ActionMenu-CScINahU.js → AlertBox-B2Bgr3ei.js} +40 -209
  2. package/dist/AlertBox-B2Bgr3ei.js.map +1 -0
  3. package/dist/{AppSidebar-BmiiPfz9.js → AppSidebar-mvm--GxN.js} +161 -110
  4. package/dist/AppSidebar-mvm--GxN.js.map +1 -0
  5. package/dist/{ConfirmDialog-CJ7hqYUP.js → ConfirmDialog-nbJj51is.js} +2 -2
  6. package/dist/{ConfirmDialog-CJ7hqYUP.js.map → ConfirmDialog-nbJj51is.js.map} +1 -1
  7. package/dist/ExperimentPopover-5T1fAq2L.js +337 -0
  8. package/dist/ExperimentPopover-5T1fAq2L.js.map +1 -0
  9. package/dist/{ExperimentSelectorModal-D-9z7cNx.js → ExperimentSelectorModal-65peG4Up.js} +198 -181
  10. package/dist/ExperimentSelectorModal-65peG4Up.js.map +1 -0
  11. package/dist/{SegmentedControl-DERBN-Xd.js → SegmentedControl-BtnnjWzs.js} +2 -2
  12. package/dist/{SegmentedControl-DERBN-Xd.js.map → SegmentedControl-BtnnjWzs.js.map} +1 -1
  13. package/dist/{SettingsModal-CSLE31yg.js → SettingsModal-DO3IZ7qz.js} +9 -9
  14. package/dist/SettingsModal-DO3IZ7qz.js.map +1 -0
  15. package/dist/__tests__/styles/v2AuditRules.test.d.ts +1 -0
  16. package/dist/components/AppSidebar.vue.d.ts +1 -1
  17. package/dist/components/ArtifactSaveDialog.vue.d.ts +9 -1
  18. package/dist/components/AuditTrail.vue.d.ts +1 -1
  19. package/dist/components/BaseSelect.vue.d.ts +2 -2
  20. package/dist/components/ChartContainer.vue.d.ts +2 -0
  21. package/dist/components/DatePicker.vue.d.ts +1 -1
  22. package/dist/components/ExperimentPopover.vue.d.ts +18 -0
  23. package/dist/components/ExperimentSelectorModal.vue.d.ts +0 -4
  24. package/dist/components/FilePicker.vue.d.ts +1 -1
  25. package/dist/components/FileUploader.vue.d.ts +2 -2
  26. package/dist/components/PluginIcon.vue.d.ts +2 -2
  27. package/dist/components/SampleSelector.vue.d.ts +6 -6
  28. package/dist/components/SequenceProgressBar.vue.d.ts +3 -0
  29. package/dist/components/StepWizard.vue.d.ts +3 -0
  30. package/dist/components/internal/AutoGroupModalInternal.vue.d.ts +1 -1
  31. package/dist/components/internal/DatePickerTimeInternal.vue.d.ts +1 -1
  32. package/dist/components/internal/ResourcePickerListInternal.vue.d.ts +2 -7
  33. package/dist/components/internal/SelectMultipleInternal.vue.d.ts +4 -0
  34. package/dist/composables/createClient.d.ts +2 -0
  35. package/dist/composables/index.d.ts +1 -0
  36. package/dist/composables/pluginIdentity.d.ts +24 -0
  37. package/dist/composables/pluginWorkspaceModel.d.ts +2 -2
  38. package/dist/composables/useAppExperiment.d.ts +8 -0
  39. package/dist/composables/useCalendarGrid.d.ts +1 -1
  40. package/dist/composables/useExperimentSelector.d.ts +6 -2
  41. package/dist/composables/usePlatform.d.ts +1 -0
  42. package/dist/{controlSchemaModel-CP5-_nAj.js → controlSchemaModel-B8CTXagP.js} +2 -2
  43. package/dist/{controlSchemaModel-CP5-_nAj.js.map → controlSchemaModel-B8CTXagP.js.map} +1 -1
  44. package/dist/{data-C2PwI_dn.js → data-CgILxDLW.js} +178 -124
  45. package/dist/data-CgILxDLW.js.map +1 -0
  46. package/dist/data.js +8 -8
  47. package/dist/{experimentStatus-BZmU4czV.js → experimentStatus-Cqp6qNrR.js} +3 -3
  48. package/dist/{experimentStatus-BZmU4czV.js.map → experimentStatus-Cqp6qNrR.js.map} +1 -1
  49. package/dist/index.js +19 -19
  50. package/dist/{install-DAID6c2-.js → install-mB8-IyvO.js} +15 -14
  51. package/dist/{install-DAID6c2-.js.map → install-mB8-IyvO.js.map} +1 -1
  52. package/dist/install.js +1 -1
  53. package/dist/{lab-DLwRl_Ql.js → lab-D5bIX426.js} +128 -147
  54. package/dist/lab-D5bIX426.js.map +1 -0
  55. package/dist/lab.js +4 -3
  56. package/dist/{records-BzTcxekG.js → records-B6gpM_3e.js} +472 -274
  57. package/dist/records-B6gpM_3e.js.map +1 -0
  58. package/dist/{runtime-D6gVat6r.js → runtime-D7vKpfbF.js} +27 -31
  59. package/dist/runtime-D7vKpfbF.js.map +1 -0
  60. package/dist/runtime.js +6 -6
  61. package/dist/{shell-5ju97nOS.js → shell-CywENwBT.js} +5 -5
  62. package/dist/{shell-5ju97nOS.js.map → shell-CywENwBT.js.map} +1 -1
  63. package/dist/shell.js +5 -5
  64. package/dist/styles.css +1644 -1688
  65. package/dist/types/componentWorkflowTypes.d.ts +2 -0
  66. package/dist/types/generated/platformContext.d.ts +1 -0
  67. package/dist/types/generated-ui.d.ts +4 -0
  68. package/dist/{BaseModal-DfRIuVoj.js → useDropdownState-8yWMu-7_.js} +60 -2
  69. package/dist/useDropdownState-8yWMu-7_.js.map +1 -0
  70. package/dist/{useExperimentSamples-CxcnxZ8h.js → useExperimentSamples-DHnxKFAF.js} +3 -3
  71. package/dist/{useExperimentSamples-CxcnxZ8h.js.map → useExperimentSamples-DHnxKFAF.js.map} +1 -1
  72. package/dist/{useListReorder-CcbEYxX-.js → useListReorder-BitdUhxn.js} +109 -277
  73. package/dist/useListReorder-BitdUhxn.js.map +1 -0
  74. package/dist/{useRackEditor-BD5NIo5s.js → useRackEditor-Q8xO-cCy.js} +72 -58
  75. package/dist/useRackEditor-Q8xO-cCy.js.map +1 -0
  76. package/dist/{useRealtime-PalKue84.js → useRealtime-C3iy9QkU.js} +7 -4
  77. package/dist/useRealtime-C3iy9QkU.js.map +1 -0
  78. package/dist/useRequest-D506eHi8.js +244 -0
  79. package/dist/useRequest-D506eHi8.js.map +1 -0
  80. package/dist/utils/time.d.ts +7 -0
  81. package/package.json +1 -1
  82. package/src/__tests__/components/AppTopBar.test.ts +51 -2
  83. package/src/__tests__/components/AppTopBarPillNav.test.ts +35 -0
  84. package/src/__tests__/components/ArtifactSaveDialog.test.ts +78 -0
  85. package/src/__tests__/components/BaseSelect.multiple.test.ts +87 -32
  86. package/src/__tests__/components/BaseSelect.test.ts +2 -1
  87. package/src/__tests__/components/BatchProgressList.test.ts +16 -0
  88. package/src/__tests__/components/CalendarGridPanel.test.ts +2 -2
  89. package/src/__tests__/components/ChartContainer.test.ts +11 -0
  90. package/src/__tests__/components/ChemicalFormula.test.ts +6 -3
  91. package/src/__tests__/components/DatePicker.datetime.test.ts +6 -0
  92. package/src/__tests__/components/DatePicker.test.ts +21 -0
  93. package/src/__tests__/components/DatePicker.time.test.ts +2 -2
  94. package/src/__tests__/components/EmptyState.test.ts +1 -1
  95. package/src/__tests__/components/ExperimentPopover.test.ts +125 -16
  96. package/src/__tests__/components/ExperimentSelectorModal.test.ts +119 -13
  97. package/src/__tests__/components/GeneratedPluginView.test.ts +22 -1
  98. package/src/__tests__/components/InstrumentStateBadge.test.ts +4 -4
  99. package/src/__tests__/components/PluginWorkspaceView.test.ts +7 -0
  100. package/src/__tests__/components/ResourcePickerListInternal.test.ts +0 -20
  101. package/src/__tests__/components/SampleSelector.test.ts +13 -8
  102. package/src/__tests__/components/SequenceProgressBar.test.ts +12 -0
  103. package/src/__tests__/components/StepWizard.test.ts +11 -0
  104. package/src/__tests__/components/WellPlate.decoration.test.ts +11 -4
  105. package/src/__tests__/components/deprecationTags.test.ts +1 -1
  106. package/src/__tests__/composables/useAppExperiment.test.ts +27 -1
  107. package/src/__tests__/composables/useCalendarGrid.test.ts +4 -2
  108. package/src/__tests__/composables/useExperimentSelector.test.ts +111 -0
  109. package/src/__tests__/styles/baseControlsRules.test.ts +6 -2
  110. package/src/__tests__/styles/controlRefreshRules.test.ts +0 -6
  111. package/src/__tests__/styles/cssTokens.test.ts +2 -2
  112. package/src/__tests__/styles/menusShellRefresh.test.ts +14 -10
  113. package/src/__tests__/styles/v2AuditRules.test.ts +96 -0
  114. package/src/__tests__/utils/plotlyTemplate.test.ts +4 -4
  115. package/src/__tests__/utils/time.test.ts +18 -1
  116. package/src/components/AdductText.story.vue +7 -0
  117. package/src/components/AdductText.vue +1 -1
  118. package/src/components/AlertBox.story.vue +2 -2
  119. package/src/components/AlertBox.vue +18 -16
  120. package/src/components/AppSidebar.story.vue +0 -28
  121. package/src/components/AppTopBar.story.vue +47 -12
  122. package/src/components/AppTopBar.vue +118 -114
  123. package/src/components/ArtifactSaveDialog.story.vue +23 -0
  124. package/src/components/ArtifactSaveDialog.vue +102 -12
  125. package/src/components/AuditTrail.story.vue +2 -1
  126. package/src/components/AuditTrail.vue +2 -21
  127. package/src/components/Avatar.vue +10 -14
  128. package/src/components/BaseSelect.multiple.story.vue +13 -2
  129. package/src/components/BaseSelect.vue +4 -3
  130. package/src/components/BatchProgressList.vue +35 -25
  131. package/src/components/ChartContainer.story.vue +2 -1
  132. package/src/components/ChartContainer.vue +8 -6
  133. package/src/components/ConfirmDialog.story.vue +1 -1
  134. package/src/components/EmptyState.vue +1 -1
  135. package/src/components/ExperimentPopover.story.vue +165 -53
  136. package/src/components/ExperimentPopover.vue +169 -187
  137. package/src/components/ExperimentSelectorModal.story.vue +40 -36
  138. package/src/components/ExperimentSelectorModal.vue +124 -110
  139. package/src/components/FormField.story.vue +8 -48
  140. package/src/components/GeneratedPluginView.vue +7 -1
  141. package/src/components/GeneratedResultRenderer.vue +3 -4
  142. package/src/components/InstrumentStateBadge.vue +1 -1
  143. package/src/components/JobsStatusTray.vue +1 -1
  144. package/src/components/LoadingSpinner.vue +1 -1
  145. package/src/components/NumberInput.vue +3 -6
  146. package/src/components/PluginIcon.story.vue +2 -10
  147. package/src/components/PluginIcon.vue +2 -2
  148. package/src/components/PluginWorkspaceView.story.vue +1 -1
  149. package/src/components/RuntimeUpdateNotice.vue +1 -1
  150. package/src/components/SampleSelector.story.vue +1 -1
  151. package/src/components/SampleSelector.vue +27 -37
  152. package/src/components/SampleSelectorGroupNode.vue +1 -1
  153. package/src/components/SectionCard.story.vue +2 -2
  154. package/src/components/SequenceProgressBar.story.vue +9 -0
  155. package/src/components/SequenceProgressBar.vue +6 -1
  156. package/src/components/SettingsModal.schema.ts +1 -1
  157. package/src/components/SettingsModal.vue +2 -2
  158. package/src/components/SmartGroupFieldRecipe.story.vue +1 -1
  159. package/src/components/SmartGroupManual.story.vue +1 -1
  160. package/src/components/StepWizard.story.vue +33 -0
  161. package/src/components/StepWizard.vue +8 -1
  162. package/src/components/WellPlate.story.vue +3 -1
  163. package/src/components/WellPlate.vue +7 -0
  164. package/src/components/internal/AppTopBarPillNavInternal.vue +33 -2
  165. package/src/components/internal/DatePickerDateInternal.vue +16 -40
  166. package/src/components/internal/DatePickerDateTimeInternal.vue +3 -13
  167. package/src/components/internal/DatePickerTimeInternal.vue +5 -8
  168. package/src/components/internal/ResourcePickerListInternal.vue +45 -85
  169. package/src/components/internal/SelectMultipleInternal.vue +182 -65
  170. package/src/components/internal/SelectSearchableInternal.vue +2 -3
  171. package/src/composables/createClient.ts +2 -0
  172. package/src/composables/index.ts +1 -0
  173. package/src/composables/pluginIdentity.ts +31 -0
  174. package/src/composables/pluginWorkspaceModel.ts +2 -2
  175. package/src/composables/useAppExperiment.ts +20 -0
  176. package/src/composables/useCalendarGrid.ts +4 -3
  177. package/src/composables/useExperimentSelector.ts +77 -31
  178. package/src/composables/usePluginWorkspace.ts +1 -1
  179. package/src/styles/components/adduct-text.css +13 -5
  180. package/src/styles/components/alert-box.css +39 -58
  181. package/src/styles/components/app-layout.css +7 -5
  182. package/src/styles/components/app-page-selector.css +3 -1
  183. package/src/styles/components/app-pill-nav.css +11 -12
  184. package/src/styles/components/app-sidebar.css +9 -18
  185. package/src/styles/components/app-top-bar.css +57 -55
  186. package/src/styles/components/artifact-save-dialog.css +153 -2
  187. package/src/styles/components/audit-trail.css +16 -19
  188. package/src/styles/components/avatar.css +6 -4
  189. package/src/styles/components/batch-progress-list.css +38 -36
  190. package/src/styles/components/button.css +28 -59
  191. package/src/styles/components/calendar.css +12 -12
  192. package/src/styles/components/chart-container.css +34 -23
  193. package/src/styles/components/checkbox.css +2 -12
  194. package/src/styles/components/collapsible-card.css +27 -29
  195. package/src/styles/components/confirm-dialog.css +13 -14
  196. package/src/styles/components/dataframe.css +13 -5
  197. package/src/styles/components/date-picker.css +80 -92
  198. package/src/styles/components/datetime-picker.css +31 -43
  199. package/src/styles/components/divider.css +20 -20
  200. package/src/styles/components/dose-calculator.css +3 -3
  201. package/src/styles/components/empty-state.css +20 -17
  202. package/src/styles/components/experiment-code-badge.css +2 -0
  203. package/src/styles/components/experiment-popover.css +174 -329
  204. package/src/styles/components/experiment-selector-modal.css +75 -56
  205. package/src/styles/components/file-picker.css +3 -3
  206. package/src/styles/components/file-uploader.css +38 -49
  207. package/src/styles/components/form-builder.css +3 -3
  208. package/src/styles/components/formula-input.css +1 -1
  209. package/src/styles/components/icon-button.css +18 -24
  210. package/src/styles/components/input.css +5 -4
  211. package/src/styles/components/instrument-monitor.css +13 -15
  212. package/src/styles/components/jobs-status-tray.css +31 -25
  213. package/src/styles/components/modal.css +4 -6
  214. package/src/styles/components/molecule-input.css +2 -2
  215. package/src/styles/components/multi-select.css +65 -117
  216. package/src/styles/components/number-input.css +26 -19
  217. package/src/styles/components/pill.css +3 -2
  218. package/src/styles/components/plate-editor.css +0 -1
  219. package/src/styles/components/plugin-icon.css +26 -23
  220. package/src/styles/components/popover.css +2 -2
  221. package/src/styles/components/presence-avatars.css +1 -1
  222. package/src/styles/components/progress-bar.css +3 -3
  223. package/src/styles/components/protocol-step-editor.css +1 -3
  224. package/src/styles/components/resource-card.css +2 -2
  225. package/src/styles/components/resource-picker-list.css +6 -57
  226. package/src/styles/components/sample-hierarchy-tree.css +4 -4
  227. package/src/styles/components/sample-selector.css +95 -79
  228. package/src/styles/components/schedule-calendar.css +8 -8
  229. package/src/styles/components/searchable-select.css +12 -12
  230. package/src/styles/components/section-card.css +30 -47
  231. package/src/styles/components/segmented-control.css +18 -15
  232. package/src/styles/components/select.css +3 -3
  233. package/src/styles/components/sequence-input.css +2 -2
  234. package/src/styles/components/sequence-progress-bar.css +17 -8
  235. package/src/styles/components/settings-modal.css +7 -2
  236. package/src/styles/components/smart-group.css +18 -18
  237. package/src/styles/components/step-wizard.css +52 -16
  238. package/src/styles/components/tabs.css +2 -2
  239. package/src/styles/components/textarea.css +3 -3
  240. package/src/styles/components/time-picker.css +36 -21
  241. package/src/styles/components/toast.css +12 -10
  242. package/src/styles/components/toggle.css +1 -11
  243. package/src/styles/components/tooltip.css +10 -9
  244. package/src/styles/components/unit-input.css +8 -7
  245. package/src/styles/components/well-plate.css +9 -2
  246. package/src/styles/variables.css +118 -77
  247. package/src/types/componentWorkflowTypes.ts +2 -0
  248. package/src/types/generated/platformContext.ts +1 -0
  249. package/src/types/generated-ui.ts +4 -0
  250. package/src/utils/time.ts +21 -0
  251. package/dist/ActionMenu-CScINahU.js.map +0 -1
  252. package/dist/AppSidebar-BmiiPfz9.js.map +0 -1
  253. package/dist/BaseModal-DfRIuVoj.js.map +0 -1
  254. package/dist/ExperimentPopover-C4sGw-is.js +0 -359
  255. package/dist/ExperimentPopover-C4sGw-is.js.map +0 -1
  256. package/dist/ExperimentSelectorModal-D-9z7cNx.js.map +0 -1
  257. package/dist/SettingsModal-CSLE31yg.js.map +0 -1
  258. package/dist/data-C2PwI_dn.js.map +0 -1
  259. package/dist/lab-DLwRl_Ql.js.map +0 -1
  260. package/dist/records-BzTcxekG.js.map +0 -1
  261. package/dist/runtime-D6gVat6r.js.map +0 -1
  262. package/dist/useListReorder-CcbEYxX-.js.map +0 -1
  263. package/dist/useRackEditor-BD5NIo5s.js.map +0 -1
  264. package/dist/useRealtime-PalKue84.js.map +0 -1
  265. package/dist/useRequest-D5JDfsgZ.js +0 -76
  266. package/dist/useRequest-D5JDfsgZ.js.map +0 -1
@@ -1,6 +1,7 @@
1
- import { a as __exportAll, i as BaseButton_default, r as useEventListener } from "./BaseModal-DfRIuVoj.js";
1
+ import { a as BaseButton_default, i as useEventListener, o as __exportAll, t as useDropdownState } from "./useDropdownState-8yWMu-7_.js";
2
2
  import { t as useExperimentStore } from "./experiment-43OJtH7R.js";
3
- import { Fragment, Teleport, TransitionGroup, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, guardReactiveProps, mergeProps, nextTick, normalizeClass, normalizeProps, normalizeStyle, onBeforeUnmount, onScopeDispose, openBlock, provide, reactive, ref, renderList, renderSlot, toDisplayString, toValue, unref, useAttrs, useId, useSlots, useTemplateRef, vModelText, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
3
+ import { Fragment, Teleport, TransitionGroup, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, guardReactiveProps, mergeProps, nextTick, normalizeClass, normalizeProps, normalizeStyle, onBeforeUnmount, onScopeDispose, openBlock, provide, ref, renderList, renderSlot, toDisplayString, toValue, unref, useAttrs, useId, useSlots, useTemplateRef, vModelText, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
4
+ import { Check, ChevronDown, ChevronsUpDown, X } from "lucide-vue-next";
4
5
  import { computePosition, flip, offset, shift } from "@floating-ui/dom";
5
6
  //#region src/components/BaseInput.vue?vue&type=script&setup=true&lang.ts
6
7
  var _hoisted_1$12 = [
@@ -327,25 +328,42 @@ function uniqueValues(values) {
327
328
  }
328
329
  //#endregion
329
330
  //#region src/components/internal/SelectMultipleInternal.vue?vue&type=script&setup=true&lang.ts
330
- var _hoisted_1$11 = {
331
+ var _hoisted_1$11 = [
332
+ "tabindex",
333
+ "aria-expanded",
334
+ "aria-disabled",
335
+ "aria-invalid",
336
+ "aria-labelledby",
337
+ "aria-describedby"
338
+ ];
339
+ var _hoisted_2$11 = { class: "mint-multi-select__chips" };
340
+ var _hoisted_3$11 = ["aria-label", "onClick"];
341
+ var _hoisted_4$8 = {
331
342
  key: 0,
332
343
  class: "mint-multi-select__placeholder"
333
344
  };
334
- var _hoisted_2$11 = ["aria-invalid"];
335
- var _hoisted_3$11 = [
336
- "aria-checked",
337
- "disabled",
338
- "onClick",
339
- "onKeydown"
340
- ];
341
- var _hoisted_4$8 = { class: "mint-multi-select__chip-label" };
342
345
  var _hoisted_5$8 = {
343
- key: 1,
344
- class: "mint-multi-select__summary"
346
+ key: 0,
347
+ class: "mint-popover mint-searchable-select__panel"
348
+ };
349
+ var _hoisted_6$8 = { class: "mint-searchable-select__search-wrap" };
350
+ var _hoisted_7$7 = ["aria-expanded", "aria-activedescendant"];
351
+ var _hoisted_8$3 = [
352
+ "id",
353
+ "aria-selected",
354
+ "aria-disabled",
355
+ "onMouseenter",
356
+ "onClick"
357
+ ];
358
+ var _hoisted_9$3 = { class: "mint-menu-item__label" };
359
+ var _hoisted_10$3 = {
360
+ key: 0,
361
+ class: "mint-searchable-select__empty"
345
362
  };
346
363
  //#endregion
347
364
  //#region src/components/internal/SelectMultipleInternal.vue
348
365
  var SelectMultipleInternal_default = /* @__PURE__ */ defineComponent({
366
+ inheritAttrs: false,
349
367
  __name: "SelectMultipleInternal",
350
368
  props: {
351
369
  modelValue: {},
@@ -360,79 +378,203 @@ var SelectMultipleInternal_default = /* @__PURE__ */ defineComponent({
360
378
  default: false
361
379
  },
362
380
  max: { default: void 0 },
363
- size: { default: "md" }
381
+ size: { default: "md" },
382
+ ariaLabelledby: { default: void 0 },
383
+ ariaDescribedby: { default: void 0 }
364
384
  },
365
385
  emits: ["update:modelValue"],
366
386
  setup(__props, { emit: __emit }) {
367
- /** BaseSelect with `multiple`: a checkbox chip list with an optional selection cap (`max`). */
387
+ /** BaseSelect with `multiple`: a field of removable chips that opens a filterable checkbox listbox, capped by `max`. */
368
388
  const props = __props;
389
+ const attrs = useAttrs();
390
+ const fieldAttrs = computed(() => {
391
+ const { class: _class, style: _style, ...rest } = attrs;
392
+ return rest;
393
+ });
369
394
  const emit = __emit;
395
+ const listboxId = `mint-multi-select-${useId().replace(/:/g, "")}`;
396
+ const root = ref(null);
397
+ const field = ref(null);
398
+ const search = ref(null);
399
+ const open = ref(false);
400
+ const query = ref("");
401
+ const activeIndex = ref(-1);
370
402
  const normalizedOptions = computed(() => props.options.map(normalizeOptionInput));
371
- const optionSelection = useListSelection({
403
+ const selection = useListSelection({
372
404
  selected: () => props.modelValue,
373
405
  items: normalizedOptions,
374
406
  getValue: (option) => option.value,
375
407
  disabled: () => props.disabled,
376
408
  max: () => props.max
377
409
  });
378
- const canSelectMore = optionSelection.canAddMore;
379
- function isSelected(value) {
380
- return optionSelection.isSelected(value);
410
+ const chips = computed(() => props.modelValue.map((value) => ({
411
+ value,
412
+ label: normalizedOptions.value.find((option) => option.value === value)?.label ?? String(value)
413
+ })));
414
+ const visibleOptions = computed(() => {
415
+ const needle = query.value.trim().toLocaleLowerCase();
416
+ if (!needle) return normalizedOptions.value;
417
+ return normalizedOptions.value.filter((option) => option.label.toLocaleLowerCase().includes(needle));
418
+ });
419
+ const activeDescendant = computed(() => activeIndex.value >= 0 ? `${listboxId}-option-${activeIndex.value}` : void 0);
420
+ function isUnavailable(option) {
421
+ return !!option.disabled || !selection.isSelected(option.value) && !selection.canAddMore.value;
381
422
  }
382
- function toggleOption(option) {
383
- if (props.disabled || option.disabled) return;
384
- if (isSelected(option.value) || canSelectMore.value) emit("update:modelValue", optionSelection.toggleValue(option.value));
423
+ async function openPanel() {
424
+ if (props.disabled || open.value) return;
425
+ query.value = "";
426
+ open.value = true;
427
+ activeIndex.value = visibleOptions.value.length > 0 ? 0 : -1;
428
+ await nextTick();
429
+ search.value?.focus();
385
430
  }
386
- function handleKeydown(event, option) {
387
- if (event.key === "Enter" || event.key === " ") {
388
- event.preventDefault();
389
- toggleOption(option);
431
+ async function closePanel(restoreFocus = false) {
432
+ open.value = false;
433
+ query.value = "";
434
+ activeIndex.value = -1;
435
+ if (restoreFocus) {
436
+ await nextTick();
437
+ field.value?.focus();
390
438
  }
391
439
  }
392
- const selectedLabels = computed(() => {
393
- return props.modelValue.map((v) => normalizedOptions.value.find((o) => o.value === v)?.label).filter(Boolean);
440
+ function moveActive(direction) {
441
+ const count = visibleOptions.value.length;
442
+ if (count === 0) return;
443
+ const start = activeIndex.value < 0 ? direction === 1 ? -1 : count : activeIndex.value;
444
+ activeIndex.value = (start + direction + count) % count;
445
+ nextTick(() => document.getElementById(activeDescendant.value ?? "")?.scrollIntoView({ block: "nearest" }));
446
+ }
447
+ function toggle(option) {
448
+ if (props.disabled || isUnavailable(option)) return;
449
+ emit("update:modelValue", selection.toggleValue(option.value));
450
+ }
451
+ function remove(value) {
452
+ if (props.disabled) return;
453
+ emit("update:modelValue", props.modelValue.filter((selected) => selected !== value));
454
+ }
455
+ function handleFieldKeydown(event) {
456
+ if (event.key !== "Enter" && event.key !== " " && event.key !== "ArrowDown") return;
457
+ event.preventDefault();
458
+ openPanel();
459
+ }
460
+ function handleSearchKeydown(event) {
461
+ if (event.key === "ArrowDown") moveActive(1);
462
+ else if (event.key === "ArrowUp") moveActive(-1);
463
+ else if (event.key === "Enter") {
464
+ const option = visibleOptions.value[activeIndex.value];
465
+ if (option) toggle(option);
466
+ } else if (event.key === "Escape") closePanel(true);
467
+ else if (event.key === "Backspace" && query.value === "" && props.modelValue.length > 0) remove(props.modelValue[props.modelValue.length - 1]);
468
+ else return;
469
+ event.preventDefault();
470
+ }
471
+ watch(visibleOptions, (options) => {
472
+ activeIndex.value = options.length > 0 ? 0 : -1;
473
+ });
474
+ watch(() => props.disabled, (disabled) => {
475
+ if (disabled) closePanel();
476
+ });
477
+ useEventListener(() => document, "pointerdown", (event) => {
478
+ if (open.value && !root.value?.contains(event.target)) closePanel();
394
479
  });
395
480
  return (_ctx, _cache) => {
396
- return openBlock(), createElementBlock("div", { class: normalizeClass([
397
- "mint-multi-select",
398
- `mint-multi-select--${__props.size}`,
399
- __props.disabled ? "mint-multi-select--disabled" : "",
400
- __props.invalid ? "mint-multi-select--error" : ""
401
- ]) }, [
402
- __props.modelValue.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_1$11, toDisplayString(__props.placeholder), 1)) : createCommentVNode("", true),
403
- createElementVNode("div", {
404
- class: "mint-multi-select__options",
405
- role: "group",
406
- "aria-invalid": __props.invalid || void 0
407
- }, [(openBlock(true), createElementBlock(Fragment, null, renderList(normalizedOptions.value, (option) => {
408
- return openBlock(), createElementBlock("button", {
409
- key: String(option.value),
410
- type: "button",
411
- role: "checkbox",
412
- "aria-checked": isSelected(option.value),
413
- disabled: __props.disabled || option.disabled || !isSelected(option.value) && !unref(canSelectMore),
414
- class: normalizeClass([
415
- "mint-multi-select__chip",
416
- `mint-multi-select__chip--${__props.size}`,
417
- isSelected(option.value) ? "mint-multi-select__chip--active" : "",
418
- option.disabled ? "mint-multi-select__chip--disabled" : "",
419
- !isSelected(option.value) && !unref(canSelectMore) ? "mint-multi-select__chip--disabled" : ""
420
- ]),
421
- onClick: ($event) => toggleOption(option),
422
- onKeydown: ($event) => handleKeydown($event, option)
423
- }, [_cache[0] || (_cache[0] = createElementVNode("svg", {
424
- class: "mint-multi-select__chip-check",
425
- viewBox: "0 0 24 24",
426
- fill: "none",
427
- stroke: "currentColor",
428
- "stroke-width": "2.5",
429
- "stroke-linecap": "round",
430
- "stroke-linejoin": "round",
431
- "aria-hidden": "true"
432
- }, [createElementVNode("path", { d: "M20 6 9 17l-5-5" })], -1)), createElementVNode("span", _hoisted_4$8, toDisplayString(option.label), 1)], 42, _hoisted_3$11);
433
- }), 128))], 8, _hoisted_2$11),
434
- __props.modelValue.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_5$8, toDisplayString(selectedLabels.value.join(", ")), 1)) : createCommentVNode("", true)
435
- ], 2);
481
+ return openBlock(), createElementBlock("div", {
482
+ ref_key: "root",
483
+ ref: root,
484
+ class: normalizeClass([
485
+ "mint-multi-select",
486
+ `mint-multi-select--${__props.size}`,
487
+ _ctx.$attrs.class
488
+ ]),
489
+ style: normalizeStyle(_ctx.$attrs.style),
490
+ onFocusout: _cache[3] || (_cache[3] = ($event) => !root.value?.contains($event.relatedTarget) && closePanel())
491
+ }, [createElementVNode("div", mergeProps(fieldAttrs.value, {
492
+ ref_key: "field",
493
+ ref: field,
494
+ role: "combobox",
495
+ tabindex: __props.disabled ? void 0 : 0,
496
+ class: ["mint-multi-select__field", {
497
+ "mint-multi-select__field--open": open.value,
498
+ "mint-multi-select__field--error": __props.invalid,
499
+ "mint-multi-select__field--disabled": __props.disabled
500
+ }],
501
+ "aria-haspopup": "listbox",
502
+ "aria-expanded": open.value,
503
+ "aria-controls": listboxId,
504
+ "aria-disabled": __props.disabled || void 0,
505
+ "aria-invalid": __props.invalid || void 0,
506
+ "aria-labelledby": __props.ariaLabelledby || void 0,
507
+ "aria-describedby": __props.ariaDescribedby || void 0,
508
+ onClick: _cache[0] || (_cache[0] = ($event) => open.value ? closePanel() : openPanel()),
509
+ onKeydown: withModifiers(handleFieldKeydown, ["self"])
510
+ }), [createElementVNode("div", _hoisted_2$11, [(openBlock(true), createElementBlock(Fragment, null, renderList(chips.value, (chip) => {
511
+ return openBlock(), createElementBlock("span", {
512
+ key: String(chip.value),
513
+ class: "mint-multi-select__chip"
514
+ }, [createTextVNode(toDisplayString(chip.label) + " ", 1), !__props.disabled ? (openBlock(), createElementBlock("button", {
515
+ key: 0,
516
+ type: "button",
517
+ tabindex: "-1",
518
+ class: "mint-multi-select__chip-remove",
519
+ "aria-label": `Remove ${chip.label}`,
520
+ onClick: withModifiers(($event) => remove(chip.value), ["stop"])
521
+ }, [createVNode(unref(X), {
522
+ size: 11,
523
+ "stroke-width": 2.25,
524
+ "aria-hidden": "true"
525
+ })], 8, _hoisted_3$11)) : createCommentVNode("", true)]);
526
+ }), 128)), chips.value.length === 0 ? (openBlock(), createElementBlock("span", _hoisted_4$8, toDisplayString(__props.placeholder), 1)) : createCommentVNode("", true)]), createVNode(unref(ChevronDown), {
527
+ class: "mint-multi-select__icon",
528
+ size: 14,
529
+ "aria-hidden": "true"
530
+ })], 16, _hoisted_1$11), open.value ? (openBlock(), createElementBlock("div", _hoisted_5$8, [createElementVNode("div", _hoisted_6$8, [_cache[4] || (_cache[4] = createElementVNode("svg", {
531
+ viewBox: "0 0 20 20",
532
+ fill: "none",
533
+ stroke: "currentColor",
534
+ "aria-hidden": "true"
535
+ }, [createElementVNode("circle", {
536
+ cx: "8.5",
537
+ cy: "8.5",
538
+ r: "5.5"
539
+ }), createElementVNode("path", { d: "m13 13 4 4" })], -1)), withDirectives(createElementVNode("input", {
540
+ ref_key: "search",
541
+ ref: search,
542
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => query.value = $event),
543
+ role: "combobox",
544
+ type: "search",
545
+ class: "mint-searchable-select__search",
546
+ placeholder: "Filter…",
547
+ "aria-label": "Filter options",
548
+ "aria-expanded": open.value,
549
+ "aria-controls": listboxId,
550
+ "aria-activedescendant": activeDescendant.value,
551
+ "aria-autocomplete": "list",
552
+ onKeydown: handleSearchKeydown
553
+ }, null, 40, _hoisted_7$7), [[vModelText, query.value]])]), createElementVNode("ul", {
554
+ id: listboxId,
555
+ class: "mint-searchable-select__list",
556
+ role: "listbox",
557
+ "aria-multiselectable": "true"
558
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(visibleOptions.value, (option, index) => {
559
+ return openBlock(), createElementBlock("li", {
560
+ id: `${listboxId}-option-${index}`,
561
+ key: String(option.value),
562
+ role: "option",
563
+ class: normalizeClass(["mint-menu-item mint-multi-select__option", { "mint-menu-item--active": activeIndex.value === index }]),
564
+ "aria-selected": unref(selection).isSelected(option.value),
565
+ "aria-disabled": isUnavailable(option) || void 0,
566
+ onMousedown: _cache[2] || (_cache[2] = withModifiers(() => {}, ["prevent"])),
567
+ onMouseenter: ($event) => !isUnavailable(option) && (activeIndex.value = index),
568
+ onClick: ($event) => toggle(option)
569
+ }, [createElementVNode("span", {
570
+ class: normalizeClass(["mint-multi-select__check", { "mint-multi-select__check--on": unref(selection).isSelected(option.value) }]),
571
+ "aria-hidden": "true"
572
+ }, [unref(selection).isSelected(option.value) ? (openBlock(), createBlock(unref(Check), {
573
+ key: 0,
574
+ size: 10,
575
+ "stroke-width": 3.5
576
+ })) : createCommentVNode("", true)], 2), createElementVNode("span", _hoisted_9$3, toDisplayString(option.label), 1)], 42, _hoisted_8$3);
577
+ }), 128)), visibleOptions.value.length === 0 ? (openBlock(), createElementBlock("li", _hoisted_10$3, "No matching options")) : createCommentVNode("", true)])])) : createCommentVNode("", true)], 38);
436
578
  };
437
579
  }
438
580
  });
@@ -629,18 +771,11 @@ var SelectSearchableInternal_default = /* @__PURE__ */ defineComponent({
629
771
  "aria-haspopup": "listbox",
630
772
  onClick: _cache[0] || (_cache[0] = ($event) => open.value ? closePanel() : openPanel()),
631
773
  onKeydown: handleTriggerKeydown
632
- }), [createElementVNode("span", { class: normalizeClass(["mint-searchable-select__value", { "mint-searchable-select__value--placeholder": !selectedOption.value }]) }, toDisplayString(selectedOption.value?.label ?? __props.placeholder), 3), _cache[4] || (_cache[4] = createElementVNode("svg", {
633
- viewBox: "0 0 20 20",
634
- fill: "none",
635
- stroke: "currentColor",
774
+ }), [createElementVNode("span", { class: normalizeClass(["mint-searchable-select__value", { "mint-searchable-select__value--placeholder": !selectedOption.value }]) }, toDisplayString(selectedOption.value?.label ?? __props.placeholder), 3), createVNode(unref(ChevronsUpDown), {
775
+ size: 14,
636
776
  "aria-hidden": "true"
637
- }, [createElementVNode("path", {
638
- "stroke-linecap": "round",
639
- "stroke-linejoin": "round",
640
- "stroke-width": "1.75",
641
- d: "m6 8 4 4 4-4"
642
- })], -1))], 16, _hoisted_1$10), open.value ? (openBlock(), createElementBlock("div", _hoisted_2$10, [
643
- createElementVNode("div", _hoisted_3$10, [_cache[5] || (_cache[5] = createElementVNode("svg", {
777
+ })], 16, _hoisted_1$10), open.value ? (openBlock(), createElementBlock("div", _hoisted_2$10, [
778
+ createElementVNode("div", _hoisted_3$10, [_cache[4] || (_cache[4] = createElementVNode("svg", {
644
779
  viewBox: "0 0 20 20",
645
780
  fill: "none",
646
781
  stroke: "currentColor",
@@ -690,7 +825,7 @@ var SelectSearchableInternal_default = /* @__PURE__ */ defineComponent({
690
825
  }, () => [
691
826
  createElementVNode("span", _hoisted_6$7, [createElementVNode("span", _hoisted_7$6, toDisplayString(option.label), 1), (option.disabled ? option.disabledReason || option.description : option.description) ? (openBlock(), createElementBlock("span", _hoisted_8$2, toDisplayString(option.disabled ? option.disabledReason || option.description : option.description), 1)) : createCommentVNode("", true)]),
692
827
  option.meta ? (openBlock(), createElementBlock("span", _hoisted_9$2, toDisplayString(option.meta), 1)) : createCommentVNode("", true),
693
- _cache[6] || (_cache[6] = createElementVNode("svg", {
828
+ _cache[5] || (_cache[5] = createElementVNode("svg", {
694
829
  class: "mint-menu-item__check mint-searchable-select__check",
695
830
  viewBox: "0 0 20 20",
696
831
  fill: "none",
@@ -758,7 +893,7 @@ var BaseSelect_default = /* @__PURE__ */ defineComponent({
758
893
  /**
759
894
  * Select one or several options.
760
895
  * Default: a native `<select>`. `searchable`: a listbox with a search field and the `#option` / `#footer` slots.
761
- * `multiple`: a checkbox chip list bound to an array, capped by `max`.
896
+ * `multiple`: a field of removable chips with a filterable checkbox listbox, bound to an array and capped by `max`.
762
897
  *
763
898
  * @example
764
899
  * ```vue
@@ -804,6 +939,7 @@ var BaseSelect_default = /* @__PURE__ */ defineComponent({
804
939
  invalid: __props.invalid,
805
940
  max: __props.max,
806
941
  size: __props.size,
942
+ "aria-labelledby": __props.ariaLabelledby,
807
943
  "aria-describedby": __props.ariaDescribedby,
808
944
  "onUpdate:modelValue": update
809
945
  }), null, 16, [
@@ -814,6 +950,7 @@ var BaseSelect_default = /* @__PURE__ */ defineComponent({
814
950
  "invalid",
815
951
  "max",
816
952
  "size",
953
+ "aria-labelledby",
817
954
  "aria-describedby"
818
955
  ])) : __props.searchable ? (openBlock(), createBlock(SelectSearchableInternal_default, mergeProps({ key: 1 }, unref(attrs), {
819
956
  "model-value": singleValue.value,
@@ -1430,6 +1567,7 @@ var EmptyState_default = /* @__PURE__ */ defineComponent({
1430
1567
  ]),
1431
1568
  __props.actionLabel ? (openBlock(), createElementBlock("div", _hoisted_7$4, [createVNode(BaseButton_default, {
1432
1569
  variant: "secondary",
1570
+ size: "sm",
1433
1571
  onClick: _cache[0] || (_cache[0] = ($event) => emit("action"))
1434
1572
  }, {
1435
1573
  default: withCtx(() => [createTextVNode(toDisplayString(__props.actionLabel), 1)]),
@@ -1504,62 +1642,150 @@ var FormField_default = /* @__PURE__ */ defineComponent({
1504
1642
  }
1505
1643
  });
1506
1644
  //#endregion
1507
- //#region src/composables/useDropdownState.ts
1508
- /**
1509
- * Shared disclosure state for dropdown-style SDK components: open/close state,
1510
- * outside-click and Escape closing, optional scroll/resize closing, and focus
1511
- * return to the trigger. `close(returnFocus)` mirrors `useMenuKeyboard`'s
1512
- * contract, so the two compose directly.
1513
- */
1514
- function useDropdownState(options = {}) {
1515
- const isOpen = ref(false);
1516
- const rootRef = options.rootRef ?? ref(null);
1517
- const triggerRef = options.triggerRef ?? ref(null);
1518
- const closeOnOutsideClick = options.closeOnOutsideClick ?? true;
1519
- const closeOnEscape = options.closeOnEscape ?? true;
1520
- const closeOnScroll = options.closeOnScroll ?? false;
1521
- function open() {
1522
- if (isOpen.value) return;
1523
- isOpen.value = true;
1524
- options.onOpen?.();
1525
- }
1526
- function close(returnFocus = false) {
1527
- if (!isOpen.value) return;
1528
- isOpen.value = false;
1529
- options.onClose?.();
1530
- if (returnFocus) nextTick(() => triggerRef.value?.focus());
1531
- }
1532
- function toggle() {
1533
- if (isOpen.value) close();
1534
- else open();
1535
- }
1536
- function handleClickOutside(event) {
1537
- if (!closeOnOutsideClick || !isOpen.value || !rootRef.value) return;
1538
- const target = event.target;
1539
- if (target instanceof Node && !rootRef.value.contains(target) && !options.insideRefs?.some((ref) => ref.value?.contains(target))) close();
1540
- }
1541
- function handleKeydown(event) {
1542
- if (closeOnEscape && event.key === "Escape") close(true);
1645
+ //#region src/utils/time.ts
1646
+ var time_exports = /* @__PURE__ */ __exportAll({
1647
+ addMinutes: () => addMinutes,
1648
+ compareTime: () => compareTime,
1649
+ durationMinutes: () => durationMinutes,
1650
+ findAvailableSlots: () => findAvailableSlots,
1651
+ findNearestTimeSlotIndex: () => findNearestTimeSlotIndex,
1652
+ formatDuration: () => formatDuration,
1653
+ formatRelativeTime: () => formatRelativeTime,
1654
+ formatTime: () => formatTime,
1655
+ formatTimeSlot: () => formatTimeSlot,
1656
+ fromMinutes: () => fromMinutes,
1657
+ generateTimeSlots: () => generateTimeSlots,
1658
+ isTimeInRange: () => isTimeInRange,
1659
+ parseTime: () => parseTime,
1660
+ rangesOverlap: () => rangesOverlap,
1661
+ snapToSlot: () => snapToSlot,
1662
+ toMinutes: () => toMinutes
1663
+ });
1664
+ function parseTime(time) {
1665
+ const [h, m] = time.split(":").map(Number);
1666
+ return {
1667
+ hour: h,
1668
+ minute: m
1669
+ };
1670
+ }
1671
+ function formatTime(hour, minute, format = "24h") {
1672
+ if (format === "24h") return `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
1673
+ const period = hour >= 12 ? "PM" : "AM";
1674
+ return `${hour === 0 ? 12 : hour > 12 ? hour - 12 : hour}:${String(minute).padStart(2, "0")} ${period}`;
1675
+ }
1676
+ function formatTimeSlot(time, format = "24h") {
1677
+ const { hour, minute } = parseTime(time);
1678
+ return formatTime(hour, minute, format);
1679
+ }
1680
+ function generateTimeSlots(start, end, stepMinutes) {
1681
+ const slots = [];
1682
+ const s = parseTime(start);
1683
+ const e = parseTime(end);
1684
+ const startMin = s.hour * 60 + s.minute;
1685
+ const endMin = e.hour * 60 + e.minute;
1686
+ for (let m = startMin; m <= endMin; m += stepMinutes) {
1687
+ const hour = Math.floor(m / 60);
1688
+ const minute = m % 60;
1689
+ if (hour >= 24) break;
1690
+ slots.push(formatTime(hour, minute));
1543
1691
  }
1544
- function handleViewportChange() {
1545
- if (isOpen.value) close();
1692
+ return slots;
1693
+ }
1694
+ function rangesOverlap(a, b) {
1695
+ const aStart = toMinutes(a.start);
1696
+ const aEnd = toMinutes(a.end);
1697
+ const bStart = toMinutes(b.start);
1698
+ return aStart < toMinutes(b.end) && bStart < aEnd;
1699
+ }
1700
+ function durationMinutes(start, end) {
1701
+ return toMinutes(end) - toMinutes(start);
1702
+ }
1703
+ function formatDuration(minutes) {
1704
+ if (minutes < 0) return "-" + formatDuration(-minutes);
1705
+ const h = Math.floor(minutes / 60);
1706
+ const m = minutes % 60;
1707
+ if (h === 0) return `${m}m`;
1708
+ if (m === 0) return `${h}h`;
1709
+ return `${h}h ${m}m`;
1710
+ }
1711
+ function isTimeInRange(time, start, end) {
1712
+ const t = toMinutes(time);
1713
+ return t >= toMinutes(start) && t <= toMinutes(end);
1714
+ }
1715
+ function findAvailableSlots(dayStart, dayEnd, occupied, minDuration) {
1716
+ const sorted = [...occupied].sort((a, b) => toMinutes(a.start) - toMinutes(b.start));
1717
+ const available = [];
1718
+ let cursor = toMinutes(dayStart);
1719
+ const end = toMinutes(dayEnd);
1720
+ for (const slot of sorted) {
1721
+ const slotStart = toMinutes(slot.start);
1722
+ const slotEnd = toMinutes(slot.end);
1723
+ if (slotStart > cursor && slotStart - cursor >= minDuration) available.push({
1724
+ start: fromMinutes(cursor),
1725
+ end: fromMinutes(slotStart)
1726
+ });
1727
+ cursor = Math.max(cursor, slotEnd);
1546
1728
  }
1547
- if (closeOnOutsideClick) useEventListener(() => document, "click", handleClickOutside);
1548
- if (closeOnEscape) useEventListener(() => document, "keydown", handleKeydown);
1549
- if (closeOnScroll) {
1550
- useEventListener(() => window, "scroll", handleViewportChange, true);
1551
- useEventListener(() => window, "resize", handleViewportChange);
1729
+ if (end > cursor && end - cursor >= minDuration) available.push({
1730
+ start: fromMinutes(cursor),
1731
+ end: fromMinutes(end)
1732
+ });
1733
+ return available;
1734
+ }
1735
+ function snapToSlot(time, stepMinutes) {
1736
+ const total = toMinutes(time);
1737
+ return fromMinutes(Math.round(total / stepMinutes) * stepMinutes);
1738
+ }
1739
+ function addMinutes(time, minutes) {
1740
+ const total = toMinutes(time) + minutes;
1741
+ return fromMinutes(Math.max(0, Math.min(total, 1439)));
1742
+ }
1743
+ function compareTime(a, b) {
1744
+ const ma = toMinutes(a);
1745
+ const mb = toMinutes(b);
1746
+ if (ma < mb) return -1;
1747
+ if (ma > mb) return 1;
1748
+ return 0;
1749
+ }
1750
+ function findNearestTimeSlotIndex(time, slots) {
1751
+ if (slots.length === 0) return -1;
1752
+ const target = toMinutes(time);
1753
+ let bestIndex = 0;
1754
+ let bestDiff = Infinity;
1755
+ for (let index = 0; index < slots.length; index++) {
1756
+ const diff = Math.abs(toMinutes(slots[index]) - target);
1757
+ if (diff < bestDiff) {
1758
+ bestDiff = diff;
1759
+ bestIndex = index;
1760
+ }
1552
1761
  }
1553
- return {
1554
- isOpen,
1555
- rootRef,
1556
- triggerRef,
1557
- open,
1558
- close,
1559
- toggle,
1560
- handleClickOutside,
1561
- handleKeydown
1562
- };
1762
+ return bestIndex;
1763
+ }
1764
+ var relativeTimeFormat = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
1765
+ /**
1766
+ * "in 5 minutes" / "2 hours ago" up to a week, then a locale date.
1767
+ * With `weeks`, times up to five weeks away read as a week count first.
1768
+ */
1769
+ function formatRelativeTime(value, { weeks = false } = {}) {
1770
+ const date = value instanceof Date ? value : new Date(value);
1771
+ const diffSec = Math.round((date.getTime() - Date.now()) / 1e3);
1772
+ const diffMin = Math.round(diffSec / 60);
1773
+ const diffHr = Math.round(diffMin / 60);
1774
+ const diffDay = Math.round(diffHr / 24);
1775
+ const diffWeek = Math.round(diffDay / 7);
1776
+ if (Math.abs(diffSec) < 60) return relativeTimeFormat.format(diffSec, "second");
1777
+ if (Math.abs(diffMin) < 60) return relativeTimeFormat.format(diffMin, "minute");
1778
+ if (Math.abs(diffHr) < 24) return relativeTimeFormat.format(diffHr, "hour");
1779
+ if (Math.abs(diffDay) < 7) return relativeTimeFormat.format(diffDay, "day");
1780
+ if (weeks && Math.abs(diffWeek) < 5) return relativeTimeFormat.format(diffWeek, "week");
1781
+ return date.toLocaleDateString();
1782
+ }
1783
+ function toMinutes(time) {
1784
+ const { hour, minute } = parseTime(time);
1785
+ return hour * 60 + minute;
1786
+ }
1787
+ function fromMinutes(total) {
1788
+ return formatTime(Math.floor(total / 60) % 24, total % 60);
1563
1789
  }
1564
1790
  //#endregion
1565
1791
  //#region src/composables/useMenuKeyboard.ts
@@ -1669,9 +1895,9 @@ var _hoisted_9$1 = {
1669
1895
  var _hoisted_10$1 = { class: "mint-file-uploader__folder-info" };
1670
1896
  var _hoisted_11$1 = { class: "mint-file-uploader__folder-details" };
1671
1897
  var _hoisted_12$1 = { class: "mint-file-uploader__folder-name" };
1672
- var _hoisted_13$1 = { class: "mint-file-uploader__folder-count" };
1673
- var _hoisted_14$1 = { class: "mint-file-uploader__file-info" };
1674
- var _hoisted_15$1 = { class: "mint-file-uploader__file-meta" };
1898
+ var _hoisted_13 = { class: "mint-file-uploader__folder-count" };
1899
+ var _hoisted_14 = { class: "mint-file-uploader__file-info" };
1900
+ var _hoisted_15 = { class: "mint-file-uploader__file-meta" };
1675
1901
  var _hoisted_16 = { class: "mint-file-uploader__file-name" };
1676
1902
  var _hoisted_17 = { class: "mint-file-uploader__file-size" };
1677
1903
  var _hoisted_18 = ["aria-label", "onClick"];
@@ -2011,7 +2237,7 @@ var FileUploader_default = /* @__PURE__ */ defineComponent({
2011
2237
  "stroke-linecap": "round",
2012
2238
  "stroke-linejoin": "round",
2013
2239
  viewBox: "0 0 24 24"
2014
- }, [createElementVNode("path", { d: "m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2" })])], -1)), createElementVNode("div", _hoisted_11$1, [createElementVNode("span", _hoisted_12$1, toDisplayString(folderName.value), 1), createElementVNode("span", _hoisted_13$1, toDisplayString(selectedFiles.value.length) + " file" + toDisplayString(selectedFiles.value.length !== 1 ? "s" : ""), 1)])]), createElementVNode("button", {
2240
+ }, [createElementVNode("path", { d: "m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2" })])], -1)), createElementVNode("div", _hoisted_11$1, [createElementVNode("span", _hoisted_12$1, toDisplayString(folderName.value), 1), createElementVNode("span", _hoisted_13, toDisplayString(selectedFiles.value.length) + " file" + toDisplayString(selectedFiles.value.length !== 1 ? "s" : ""), 1)])]), createElementVNode("button", {
2015
2241
  type: "button",
2016
2242
  "aria-label": "Clear folder",
2017
2243
  class: "mint-file-uploader__remove-btn",
@@ -2035,10 +2261,10 @@ var FileUploader_default = /* @__PURE__ */ defineComponent({
2035
2261
  return openBlock(), createElementBlock("li", {
2036
2262
  key: `${file.name}-${file.size}-${index}`,
2037
2263
  class: "mint-file-uploader__file"
2038
- }, [createElementVNode("div", _hoisted_14$1, [createElementVNode("span", {
2264
+ }, [createElementVNode("div", _hoisted_14, [createElementVNode("span", {
2039
2265
  class: "mint-file-uploader__file-badge",
2040
2266
  style: normalizeStyle({ "--badge-color": getFileType(file.name).color })
2041
- }, toDisplayString(getFileType(file.name).label), 5), createElementVNode("div", _hoisted_15$1, [createElementVNode("span", _hoisted_16, toDisplayString(file.name), 1), createElementVNode("span", _hoisted_17, toDisplayString(formatFileSize(file.size)), 1)])]), createElementVNode("button", {
2267
+ }, toDisplayString(getFileType(file.name).label), 5), createElementVNode("div", _hoisted_15, [createElementVNode("span", _hoisted_16, toDisplayString(file.name), 1), createElementVNode("span", _hoisted_17, toDisplayString(formatFileSize(file.size)), 1)])]), createElementVNode("button", {
2042
2268
  type: "button",
2043
2269
  "aria-label": `Remove ${file.name}`,
2044
2270
  class: "mint-file-uploader__remove-btn",
@@ -2169,10 +2395,19 @@ function useAppExperiment(options = {}) {
2169
2395
  const showDetach = computed(() => experimentId.value !== null);
2170
2396
  const saveDisabled = computed(() => toValue(options.saveDisabled) ?? false);
2171
2397
  const saveDisabledMessage = computed(() => toValue(options.saveDisabledMessage));
2398
+ const dirty = computed(() => toValue(options.dirty) ?? false);
2399
+ const experimentOwner = computed(() => {
2400
+ const owner = store.current?.created_by_user;
2401
+ return owner ? [owner.first_name, owner.last_name].filter(Boolean).join(" ") || owner.username : void 0;
2402
+ });
2172
2403
  const popover = computed(() => ({
2173
2404
  experimentName: experimentName.value,
2174
2405
  experimentCode: experimentCode.value,
2175
2406
  experimentStatus: experimentStatus.value,
2407
+ experimentId: experimentId.value,
2408
+ experimentProject: store.current?.project_name || store.current?.project || void 0,
2409
+ experimentOwner: experimentOwner.value,
2410
+ experimentUpdatedAt: store.current?.updated_at,
2176
2411
  isResolving: isResolving.value,
2177
2412
  error: error.value ?? void 0,
2178
2413
  showSave: showSave.value,
@@ -2180,7 +2415,8 @@ function useAppExperiment(options = {}) {
2180
2415
  saveDisabled: saveDisabled.value,
2181
2416
  saveDisabledMessage: saveDisabledMessage.value,
2182
2417
  saveLoading: saveLoading.value,
2183
- saveSuccessMessage: saveSuccessMessage.value
2418
+ saveSuccessMessage: saveSuccessMessage.value,
2419
+ dirty: dirty.value
2184
2420
  }));
2185
2421
  const selectorModal = computed(() => ({
2186
2422
  open: showModal.value,
@@ -2200,6 +2436,7 @@ function useAppExperiment(options = {}) {
2200
2436
  saveLoading.value = true;
2201
2437
  try {
2202
2438
  const message = await options.onSave();
2439
+ await store.refresh();
2203
2440
  if (message) {
2204
2441
  saveSuccessMessage.value = message;
2205
2442
  if (successTimer) clearTimeout(successTimer);
@@ -2846,31 +3083,28 @@ var _hoisted_3 = {
2846
3083
  role: "alert"
2847
3084
  };
2848
3085
  var _hoisted_4 = ["aria-label"];
2849
- var _hoisted_5 = ["aria-expanded", "onClick"];
2850
- var _hoisted_6 = { class: "mint-resource-picker__group-label" };
2851
- var _hoisted_7 = { class: "mint-resource-picker__group-count" };
2852
- var _hoisted_8 = [
3086
+ var _hoisted_5 = [
2853
3087
  "id",
2854
3088
  "aria-selected",
2855
3089
  "onClick",
2856
3090
  "onMouseenter"
2857
3091
  ];
2858
- var _hoisted_9 = { class: "mint-resource-picker__text" };
2859
- var _hoisted_10 = { class: "mint-resource-picker__title" };
2860
- var _hoisted_11 = {
3092
+ var _hoisted_6 = { class: "mint-resource-picker__text" };
3093
+ var _hoisted_7 = { class: "mint-resource-picker__title" };
3094
+ var _hoisted_8 = {
2861
3095
  key: 0,
2862
3096
  class: "mint-resource-picker__meta"
2863
3097
  };
2864
- var _hoisted_12 = {
3098
+ var _hoisted_9 = {
2865
3099
  key: 0,
2866
3100
  class: "mint-resource-picker__code mint-exp-code mint-exp-code--sm"
2867
3101
  };
2868
- var _hoisted_13 = { key: 1 };
2869
- var _hoisted_14 = {
3102
+ var _hoisted_10 = { key: 1 };
3103
+ var _hoisted_11 = {
2870
3104
  key: 0,
2871
3105
  class: "mint-resource-picker__aside"
2872
3106
  };
2873
- var _hoisted_15 = {
3107
+ var _hoisted_12 = {
2874
3108
  key: 1,
2875
3109
  class: "mint-resource-picker__date"
2876
3110
  };
@@ -2880,7 +3114,6 @@ var ResourcePickerListInternal_default = /* @__PURE__ */ defineComponent({
2880
3114
  __name: "ResourcePickerListInternal",
2881
3115
  props: {
2882
3116
  items: {},
2883
- groups: { default: null },
2884
3117
  itemKey: {},
2885
3118
  describe: {},
2886
3119
  selectedKey: { default: null },
@@ -2893,12 +3126,13 @@ var ResourcePickerListInternal_default = /* @__PURE__ */ defineComponent({
2893
3126
  },
2894
3127
  error: { default: null },
2895
3128
  emptyTitle: { default: "Nothing found" },
2896
- emptyDescription: { default: "Try adjusting your search or filters." }
3129
+ emptyDescription: { default: "Try adjusting your search or filters." },
3130
+ autofocusSearch: { type: Boolean }
2897
3131
  },
2898
3132
  emits: ["select", "update:search"],
2899
3133
  setup(__props, { emit: __emit }) {
2900
3134
  /**
2901
- * Searchable, optionally grouped single-select list shared by the experiment and
3135
+ * Searchable single-select list shared by the experiment and
2902
3136
  * artifact selector modals: two-line rows (title, then code + meta) with status and date
2903
3137
  * in a right-hand column, a filled selected row, skeleton,
2904
3138
  * error and empty states, and the combobox keyboard model (↑ ↓ Enter).
@@ -2906,35 +3140,24 @@ var ResourcePickerListInternal_default = /* @__PURE__ */ defineComponent({
2906
3140
  const props = __props;
2907
3141
  const emit = __emit;
2908
3142
  const listId = `mint-resource-picker-${useId().replace(/:/g, "")}`;
2909
- const collapsed = reactive(/* @__PURE__ */ new Set());
2910
3143
  const activeIndex = ref(-1);
2911
3144
  const listRef = ref(null);
2912
- const visibleGroups = computed(() => props.groups?.map((group) => ({
2913
- ...group,
2914
- rows: collapsed.has(group.label) ? [] : group.items
2915
- })));
2916
- /** Keyboard order: the rows on screen, top to bottom. */
2917
- const flat = computed(() => visibleGroups.value ? visibleGroups.value.flatMap((group) => group.rows) : props.items);
2918
- const indexByKey = computed(() => new Map(flat.value.map((item, i) => [props.itemKey(item), i])));
3145
+ const indexByKey = computed(() => new Map(props.items.map((item, i) => [props.itemKey(item), i])));
2919
3146
  const showList = computed(() => !props.loading && !props.error && props.items.length > 0);
2920
3147
  function optionId(item) {
2921
3148
  return `${listId}-${props.itemKey(item)}`;
2922
3149
  }
2923
3150
  const activeDescendant = computed(() => {
2924
- const item = flat.value[activeIndex.value];
3151
+ const item = props.items[activeIndex.value];
2925
3152
  return item === void 0 ? void 0 : optionId(item);
2926
3153
  });
2927
3154
  function indexOf(item) {
2928
3155
  return indexByKey.value.get(props.itemKey(item)) ?? -1;
2929
3156
  }
2930
- function toggleGroup(label) {
2931
- if (collapsed.has(label)) collapsed.delete(label);
2932
- else collapsed.add(label);
2933
- }
2934
3157
  function keydown(event) {
2935
3158
  const target = event.target;
2936
3159
  if (target !== event.currentTarget && !target?.closest(".mint-resource-picker__search")) return;
2937
- const rows = flat.value;
3160
+ const rows = props.items;
2938
3161
  if (!rows.length) return;
2939
3162
  if (event.key === "ArrowDown" || event.key === "ArrowUp") {
2940
3163
  event.preventDefault();
@@ -2945,116 +3168,91 @@ var ResourcePickerListInternal_default = /* @__PURE__ */ defineComponent({
2945
3168
  emit("select", rows[activeIndex.value]);
2946
3169
  }
2947
3170
  }
2948
- watch(() => [props.items, props.groups], () => {
3171
+ watch(() => props.items, () => {
2949
3172
  activeIndex.value = -1;
2950
3173
  });
2951
3174
  return (_ctx, _cache) => {
2952
3175
  return openBlock(), createElementBlock("div", {
2953
3176
  class: "mint-resource-picker",
2954
3177
  onKeydown: keydown
2955
- }, [
2956
- createElementVNode("div", _hoisted_1, [createVNode(BaseInput_default, {
2957
- class: "mint-resource-picker__search",
2958
- "model-value": __props.search,
2959
- placeholder: __props.placeholder,
2960
- size: "sm",
2961
- type: "search",
2962
- role: "combobox",
2963
- "aria-label": `Search ${__props.label.toLowerCase()}`,
2964
- "aria-expanded": showList.value,
2965
- "aria-controls": listId,
2966
- "aria-activedescendant": activeDescendant.value,
2967
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => emit("update:search", String($event ?? "")))
2968
- }, {
2969
- prefix: withCtx(() => [..._cache[2] || (_cache[2] = [createElementVNode("svg", {
2970
- viewBox: "0 0 16 16",
2971
- fill: "none",
2972
- stroke: "currentColor",
2973
- "stroke-width": "1.5",
2974
- "aria-hidden": "true"
2975
- }, [createElementVNode("path", { d: "M7 11.5a4.5 4.5 0 1 1 0-9 4.5 4.5 0 0 1 0 9zM10.5 10.5L14 14" })], -1)])]),
2976
- _: 1
2977
- }, 8, [
2978
- "model-value",
2979
- "placeholder",
2980
- "aria-label",
2981
- "aria-expanded",
2982
- "aria-activedescendant"
2983
- ]), renderSlot(_ctx.$slots, "filters")]),
2984
- renderSlot(_ctx.$slots, "advanced"),
2985
- __props.loading ? (openBlock(), createElementBlock("div", _hoisted_2, [(openBlock(), createElementBlock(Fragment, null, renderList(4, (n) => {
2986
- return createElementVNode("div", {
2987
- key: n,
2988
- class: "mint-resource-picker__skeleton-row"
2989
- }, [createVNode(Skeleton_default, {
2990
- width: `${40 + n * 10}%`,
2991
- height: "0.75rem"
2992
- }, null, 8, ["width"]), createVNode(Skeleton_default, {
2993
- width: "30%",
2994
- height: "0.625rem"
2995
- })]);
2996
- }), 64))])) : __props.error ? (openBlock(), createElementBlock("div", _hoisted_3, toDisplayString(__props.error), 1)) : !__props.items.length ? (openBlock(), createBlock(EmptyState_default, {
2997
- key: 2,
2998
- title: __props.emptyTitle,
2999
- description: __props.emptyDescription,
3000
- size: "sm"
3001
- }, null, 8, ["title", "description"])) : (openBlock(), createElementBlock("div", {
3002
- key: 3,
3003
- id: listId,
3004
- ref_key: "listRef",
3005
- ref: listRef,
3006
- class: "mint-resource-picker__frame mint-resource-picker__list",
3007
- role: "listbox",
3008
- "aria-label": __props.label
3009
- }, [(openBlock(true), createElementBlock(Fragment, null, renderList(visibleGroups.value ?? [{
3010
- label: "",
3011
- items: __props.items,
3012
- rows: __props.items
3013
- }], (group) => {
3014
- return openBlock(), createElementBlock(Fragment, { key: group.label }, [visibleGroups.value ? (openBlock(), createElementBlock("button", {
3178
+ }, [createElementVNode("div", _hoisted_1, [createVNode(BaseInput_default, {
3179
+ class: "mint-resource-picker__search",
3180
+ "model-value": __props.search,
3181
+ placeholder: __props.placeholder,
3182
+ size: "sm",
3183
+ type: "search",
3184
+ autofocus: __props.autofocusSearch,
3185
+ role: "combobox",
3186
+ "aria-label": `Search ${__props.label.toLowerCase()}`,
3187
+ "aria-expanded": showList.value,
3188
+ "aria-controls": listId,
3189
+ "aria-activedescendant": activeDescendant.value,
3190
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => emit("update:search", String($event ?? "")))
3191
+ }, {
3192
+ prefix: withCtx(() => [..._cache[2] || (_cache[2] = [createElementVNode("svg", {
3193
+ viewBox: "0 0 16 16",
3194
+ fill: "none",
3195
+ stroke: "currentColor",
3196
+ "stroke-width": "1.5",
3197
+ "aria-hidden": "true"
3198
+ }, [createElementVNode("path", { d: "M7 11.5a4.5 4.5 0 1 1 0-9 4.5 4.5 0 0 1 0 9zM10.5 10.5L14 14" })], -1)])]),
3199
+ _: 1
3200
+ }, 8, [
3201
+ "model-value",
3202
+ "placeholder",
3203
+ "autofocus",
3204
+ "aria-label",
3205
+ "aria-expanded",
3206
+ "aria-activedescendant"
3207
+ ]), renderSlot(_ctx.$slots, "filters")]), __props.loading ? (openBlock(), createElementBlock("div", _hoisted_2, [(openBlock(), createElementBlock(Fragment, null, renderList(4, (n) => {
3208
+ return createElementVNode("div", {
3209
+ key: n,
3210
+ class: "mint-resource-picker__skeleton-row"
3211
+ }, [createVNode(Skeleton_default, {
3212
+ width: `${40 + n * 10}%`,
3213
+ height: "0.75rem"
3214
+ }, null, 8, ["width"]), createVNode(Skeleton_default, {
3215
+ width: "30%",
3216
+ height: "0.625rem"
3217
+ })]);
3218
+ }), 64))])) : __props.error ? (openBlock(), createElementBlock("div", _hoisted_3, toDisplayString(__props.error), 1)) : !__props.items.length ? (openBlock(), createBlock(EmptyState_default, {
3219
+ key: 2,
3220
+ title: __props.emptyTitle,
3221
+ description: __props.emptyDescription,
3222
+ size: "sm"
3223
+ }, null, 8, ["title", "description"])) : (openBlock(), createElementBlock("div", {
3224
+ key: 3,
3225
+ id: listId,
3226
+ ref_key: "listRef",
3227
+ ref: listRef,
3228
+ class: "mint-resource-picker__frame mint-resource-picker__list",
3229
+ role: "listbox",
3230
+ "aria-label": __props.label
3231
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.items, (item) => {
3232
+ return openBlock(), createElementBlock("div", {
3233
+ id: optionId(item),
3234
+ key: __props.itemKey(item),
3235
+ role: "option",
3236
+ "aria-selected": __props.itemKey(item) === __props.selectedKey,
3237
+ class: normalizeClass(["mint-resource-picker__row", {
3238
+ "mint-resource-picker__row--selected": __props.itemKey(item) === __props.selectedKey,
3239
+ "mint-resource-picker__row--active": indexOf(item) === activeIndex.value
3240
+ }]),
3241
+ onClick: ($event) => emit("select", item),
3242
+ onMouseenter: ($event) => activeIndex.value = indexOf(item)
3243
+ }, [
3244
+ createElementVNode("span", _hoisted_6, [createElementVNode("span", _hoisted_7, toDisplayString(__props.describe(item).title), 1), __props.describe(item).code || __props.describe(item).meta?.length ? (openBlock(), createElementBlock("span", _hoisted_8, [__props.describe(item).code ? (openBlock(), createElementBlock("span", _hoisted_9, toDisplayString(__props.describe(item).code), 1)) : createCommentVNode("", true), __props.describe(item).meta?.length ? (openBlock(), createElementBlock("span", _hoisted_10, toDisplayString(__props.describe(item).meta.join(" · ")), 1)) : createCommentVNode("", true)])) : createCommentVNode("", true)]),
3245
+ __props.describe(item).status || __props.describe(item).date ? (openBlock(), createElementBlock("span", _hoisted_11, [__props.describe(item).status ? (openBlock(), createElementBlock("span", {
3015
3246
  key: 0,
3016
- type: "button",
3017
- class: "mint-resource-picker__group",
3018
- "aria-expanded": !collapsed.has(group.label),
3019
- onClick: ($event) => toggleGroup(group.label)
3020
- }, [
3021
- _cache[3] || (_cache[3] = createElementVNode("svg", {
3022
- class: "mint-resource-picker__chevron",
3023
- viewBox: "0 0 16 16",
3024
- fill: "none",
3025
- stroke: "currentColor",
3026
- "stroke-width": "1.5",
3027
- "aria-hidden": "true"
3028
- }, [createElementVNode("path", { d: "M4 6l4 4 4-4" })], -1)),
3029
- createElementVNode("span", _hoisted_6, toDisplayString(group.label), 1),
3030
- createElementVNode("span", _hoisted_7, toDisplayString(group.items.length), 1)
3031
- ], 8, _hoisted_5)) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(group.rows, (item) => {
3032
- return openBlock(), createElementBlock("div", {
3033
- id: optionId(item),
3034
- key: __props.itemKey(item),
3035
- role: "option",
3036
- "aria-selected": __props.itemKey(item) === __props.selectedKey,
3037
- class: normalizeClass(["mint-resource-picker__row", {
3038
- "mint-resource-picker__row--selected": __props.itemKey(item) === __props.selectedKey,
3039
- "mint-resource-picker__row--active": indexOf(item) === activeIndex.value
3040
- }]),
3041
- onClick: ($event) => emit("select", item),
3042
- onMouseenter: ($event) => activeIndex.value = indexOf(item)
3043
- }, [
3044
- createElementVNode("span", _hoisted_9, [createElementVNode("span", _hoisted_10, toDisplayString(__props.describe(item).title), 1), __props.describe(item).code || __props.describe(item).meta?.length ? (openBlock(), createElementBlock("span", _hoisted_11, [__props.describe(item).code ? (openBlock(), createElementBlock("span", _hoisted_12, toDisplayString(__props.describe(item).code), 1)) : createCommentVNode("", true), __props.describe(item).meta?.length ? (openBlock(), createElementBlock("span", _hoisted_13, toDisplayString(__props.describe(item).meta.join(" · ")), 1)) : createCommentVNode("", true)])) : createCommentVNode("", true)]),
3045
- __props.describe(item).status || __props.describe(item).date ? (openBlock(), createElementBlock("span", _hoisted_14, [__props.describe(item).status ? (openBlock(), createElementBlock("span", {
3046
- key: 0,
3047
- class: normalizeClass(["mint-resource-picker__status", `mint-resource-picker__status--${__props.describe(item).status.tone}`])
3048
- }, toDisplayString(__props.describe(item).status.label), 3)) : createCommentVNode("", true), __props.describe(item).date ? (openBlock(), createElementBlock("span", _hoisted_15, toDisplayString(__props.describe(item).date), 1)) : createCommentVNode("", true)])) : createCommentVNode("", true),
3049
- _ctx.$slots.actions ? (openBlock(), createElementBlock("span", {
3050
- key: 1,
3051
- class: "mint-resource-picker__actions",
3052
- onClick: _cache[1] || (_cache[1] = withModifiers(() => {}, ["stop"]))
3053
- }, [renderSlot(_ctx.$slots, "actions", { item })])) : createCommentVNode("", true)
3054
- ], 42, _hoisted_8);
3055
- }), 128))], 64);
3056
- }), 128))], 8, _hoisted_4))
3057
- ], 32);
3247
+ class: normalizeClass(["mint-resource-picker__status", `mint-resource-picker__status--${__props.describe(item).status.tone}`])
3248
+ }, toDisplayString(__props.describe(item).status.label), 3)) : createCommentVNode("", true), __props.describe(item).date ? (openBlock(), createElementBlock("span", _hoisted_12, toDisplayString(__props.describe(item).date), 1)) : createCommentVNode("", true)])) : createCommentVNode("", true),
3249
+ _ctx.$slots.actions ? (openBlock(), createElementBlock("span", {
3250
+ key: 1,
3251
+ class: "mint-resource-picker__actions",
3252
+ onClick: _cache[1] || (_cache[1] = withModifiers(() => {}, ["stop"]))
3253
+ }, [renderSlot(_ctx.$slots, "actions", { item })])) : createCommentVNode("", true)
3254
+ ], 42, _hoisted_5);
3255
+ }), 128))], 8, _hoisted_4))], 32);
3058
3256
  };
3059
3257
  }
3060
3258
  });
@@ -3065,6 +3263,6 @@ function isRecord(value) {
3065
3263
  return typeof value === "object" && value !== null && !Array.isArray(value);
3066
3264
  }
3067
3265
  //#endregion
3068
- export { useRovingFocus as A, formatExperimentDate as C, useDropdownState as D, useMenuKeyboard as E, useSelectionLimit as F, normalizeOptionInput as I, BaseInput_default as L, Tooltip_default as M, BaseSelect_default as N, FormField_default as O, useListSelection as P, experimentIdFromRoute as S, FileUploader_default as T, APP_EXPERIMENT_KEY as _, parseExperimentId as a, SORT_OPTIONS as b, isTerminalJobStatus as c, normalizeJobState as d, resolveJobCapabilities as f, pluginSecrets_exports as g, FORMAT_KEY as h, getInjectedPlatformContext as i, BaseCheckbox_default as j, EmptyState_default as k, jobStatusLabel as l, SecretInput_default as m, ResourcePickerListInternal_default as n, resolveCurrentPluginId as o, TagsInput_default as p, Skeleton_default as r, isActiveJobStatus as s, isRecord as t, normalizeJobPercent as u, useAppExperiment as v, resolveExperimentCode as w, datePresetToISO as x, DATE_PRESET_OPTIONS as y };
3266
+ export { formatRelativeTime as A, Tooltip_default as B, formatExperimentDate as C, compareTime as D, useMenuKeyboard as E, toMinutes as F, BaseInput_default as G, useListSelection as H, FormField_default as I, EmptyState_default as L, formatTimeSlot as M, generateTimeSlots as N, durationMinutes as O, time_exports as P, useRovingFocus as R, experimentIdFromRoute as S, FileUploader_default as T, useSelectionLimit as U, BaseSelect_default as V, normalizeOptionInput as W, APP_EXPERIMENT_KEY as _, parseExperimentId as a, SORT_OPTIONS as b, isTerminalJobStatus as c, normalizeJobState as d, resolveJobCapabilities as f, pluginSecrets_exports as g, FORMAT_KEY as h, getInjectedPlatformContext as i, formatTime as j, findNearestTimeSlotIndex as k, jobStatusLabel as l, SecretInput_default as m, ResourcePickerListInternal_default as n, resolveCurrentPluginId as o, TagsInput_default as p, Skeleton_default as r, isActiveJobStatus as s, isRecord as t, normalizeJobPercent as u, useAppExperiment as v, resolveExperimentCode as w, datePresetToISO as x, DATE_PRESET_OPTIONS as y, BaseCheckbox_default as z };
3069
3267
 
3070
- //# sourceMappingURL=records-BzTcxekG.js.map
3268
+ //# sourceMappingURL=records-B6gpM_3e.js.map