@morscherlab/mint-sdk 1.4.0-beta.1 → 1.4.0-beta.10
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.
- package/dist/{ActionMenu-CScINahU.js → AlertBox-B2Bgr3ei.js} +40 -209
- package/dist/AlertBox-B2Bgr3ei.js.map +1 -0
- package/dist/{AppSidebar-BmiiPfz9.js → AppSidebar-mvm--GxN.js} +161 -110
- package/dist/AppSidebar-mvm--GxN.js.map +1 -0
- package/dist/{ConfirmDialog-CJ7hqYUP.js → ConfirmDialog-nbJj51is.js} +2 -2
- package/dist/{ConfirmDialog-CJ7hqYUP.js.map → ConfirmDialog-nbJj51is.js.map} +1 -1
- package/dist/ExperimentPopover-5T1fAq2L.js +337 -0
- package/dist/ExperimentPopover-5T1fAq2L.js.map +1 -0
- package/dist/{ExperimentSelectorModal-D-9z7cNx.js → ExperimentSelectorModal-65peG4Up.js} +198 -181
- package/dist/ExperimentSelectorModal-65peG4Up.js.map +1 -0
- package/dist/{SegmentedControl-DERBN-Xd.js → SegmentedControl-BtnnjWzs.js} +2 -2
- package/dist/{SegmentedControl-DERBN-Xd.js.map → SegmentedControl-BtnnjWzs.js.map} +1 -1
- package/dist/{SettingsModal-CSLE31yg.js → SettingsModal-DO3IZ7qz.js} +9 -9
- package/dist/SettingsModal-DO3IZ7qz.js.map +1 -0
- package/dist/components/AppSidebar.vue.d.ts +1 -1
- package/dist/components/ArtifactSaveDialog.vue.d.ts +9 -1
- package/dist/components/AuditTrail.vue.d.ts +1 -1
- package/dist/components/BaseSelect.vue.d.ts +2 -2
- package/dist/components/ChartContainer.vue.d.ts +2 -0
- package/dist/components/DatePicker.vue.d.ts +1 -1
- package/dist/components/ExperimentPopover.vue.d.ts +18 -0
- package/dist/components/ExperimentSelectorModal.vue.d.ts +0 -4
- package/dist/components/FilePicker.vue.d.ts +1 -1
- package/dist/components/FileUploader.vue.d.ts +2 -2
- package/dist/components/PluginIcon.vue.d.ts +2 -2
- package/dist/components/SampleSelector.vue.d.ts +6 -6
- package/dist/components/SequenceProgressBar.vue.d.ts +3 -0
- package/dist/components/StepWizard.vue.d.ts +3 -0
- package/dist/components/internal/AutoGroupModalInternal.vue.d.ts +1 -1
- package/dist/components/internal/DatePickerTimeInternal.vue.d.ts +1 -1
- package/dist/components/internal/ResourcePickerListInternal.vue.d.ts +2 -7
- package/dist/components/internal/SelectMultipleInternal.vue.d.ts +4 -0
- package/dist/composables/createClient.d.ts +2 -0
- package/dist/composables/index.d.ts +1 -0
- package/dist/composables/pluginIdentity.d.ts +24 -0
- package/dist/composables/pluginWorkspaceModel.d.ts +2 -2
- package/dist/composables/useAppExperiment.d.ts +8 -0
- package/dist/composables/useCalendarGrid.d.ts +1 -1
- package/dist/composables/useExperimentSelector.d.ts +6 -2
- package/dist/composables/usePlatform.d.ts +1 -0
- package/dist/{controlSchemaModel-CP5-_nAj.js → controlSchemaModel-B8CTXagP.js} +2 -2
- package/dist/{controlSchemaModel-CP5-_nAj.js.map → controlSchemaModel-B8CTXagP.js.map} +1 -1
- package/dist/{data-C2PwI_dn.js → data-CgILxDLW.js} +178 -124
- package/dist/data-CgILxDLW.js.map +1 -0
- package/dist/data.js +8 -8
- package/dist/{experimentStatus-BZmU4czV.js → experimentStatus-Cqp6qNrR.js} +3 -3
- package/dist/{experimentStatus-BZmU4czV.js.map → experimentStatus-Cqp6qNrR.js.map} +1 -1
- package/dist/index.js +19 -19
- package/dist/{install-DAID6c2-.js → install-CsPFJSx3.js} +15 -14
- package/dist/{install-DAID6c2-.js.map → install-CsPFJSx3.js.map} +1 -1
- package/dist/install.js +1 -1
- package/dist/{lab-DLwRl_Ql.js → lab-MHzp-_J8.js} +128 -147
- package/dist/lab-MHzp-_J8.js.map +1 -0
- package/dist/lab.js +4 -3
- package/dist/{records-BzTcxekG.js → records-B6gpM_3e.js} +472 -274
- package/dist/records-B6gpM_3e.js.map +1 -0
- package/dist/{runtime-D6gVat6r.js → runtime-8bs8EogX.js} +27 -31
- package/dist/runtime-8bs8EogX.js.map +1 -0
- package/dist/runtime.js +6 -6
- package/dist/{shell-5ju97nOS.js → shell-CywENwBT.js} +5 -5
- package/dist/{shell-5ju97nOS.js.map → shell-CywENwBT.js.map} +1 -1
- package/dist/shell.js +5 -5
- package/dist/styles.css +1606 -1666
- package/dist/types/componentWorkflowTypes.d.ts +2 -0
- package/dist/types/generated/platformContext.d.ts +1 -0
- package/dist/types/generated-ui.d.ts +4 -0
- package/dist/{BaseModal-DfRIuVoj.js → useDropdownState-8yWMu-7_.js} +60 -2
- package/dist/useDropdownState-8yWMu-7_.js.map +1 -0
- package/dist/{useExperimentSamples-CxcnxZ8h.js → useExperimentSamples-DHnxKFAF.js} +3 -3
- package/dist/{useExperimentSamples-CxcnxZ8h.js.map → useExperimentSamples-DHnxKFAF.js.map} +1 -1
- package/dist/{useListReorder-CcbEYxX-.js → useListReorder-BitdUhxn.js} +109 -277
- package/dist/useListReorder-BitdUhxn.js.map +1 -0
- package/dist/{useRackEditor-BD5NIo5s.js → useRackEditor-DiwCt77M.js} +71 -57
- package/dist/useRackEditor-DiwCt77M.js.map +1 -0
- package/dist/{useRealtime-PalKue84.js → useRealtime-C3iy9QkU.js} +7 -4
- package/dist/useRealtime-C3iy9QkU.js.map +1 -0
- package/dist/useRequest-D506eHi8.js +244 -0
- package/dist/useRequest-D506eHi8.js.map +1 -0
- package/dist/utils/time.d.ts +7 -0
- package/package.json +1 -1
- package/src/__tests__/components/AppTopBar.test.ts +51 -2
- package/src/__tests__/components/AppTopBarPillNav.test.ts +35 -0
- package/src/__tests__/components/ArtifactSaveDialog.test.ts +78 -0
- package/src/__tests__/components/BaseSelect.multiple.test.ts +87 -32
- package/src/__tests__/components/BaseSelect.test.ts +2 -1
- package/src/__tests__/components/BatchProgressList.test.ts +16 -0
- package/src/__tests__/components/CalendarGridPanel.test.ts +2 -2
- package/src/__tests__/components/ChartContainer.test.ts +11 -0
- package/src/__tests__/components/ChemicalFormula.test.ts +6 -3
- package/src/__tests__/components/DatePicker.datetime.test.ts +6 -0
- package/src/__tests__/components/DatePicker.test.ts +21 -0
- package/src/__tests__/components/DatePicker.time.test.ts +2 -2
- package/src/__tests__/components/EmptyState.test.ts +1 -1
- package/src/__tests__/components/ExperimentPopover.test.ts +125 -16
- package/src/__tests__/components/ExperimentSelectorModal.test.ts +119 -13
- package/src/__tests__/components/GeneratedPluginView.test.ts +22 -1
- package/src/__tests__/components/InstrumentStateBadge.test.ts +4 -4
- package/src/__tests__/components/PluginWorkspaceView.test.ts +7 -0
- package/src/__tests__/components/ResourcePickerListInternal.test.ts +0 -20
- package/src/__tests__/components/SampleSelector.test.ts +13 -8
- package/src/__tests__/components/SequenceProgressBar.test.ts +12 -0
- package/src/__tests__/components/StepWizard.test.ts +11 -0
- package/src/__tests__/components/WellPlate.decoration.test.ts +11 -4
- package/src/__tests__/components/deprecationTags.test.ts +1 -1
- package/src/__tests__/composables/useAppExperiment.test.ts +27 -1
- package/src/__tests__/composables/useCalendarGrid.test.ts +4 -2
- package/src/__tests__/composables/useExperimentSelector.test.ts +111 -0
- package/src/__tests__/styles/baseControlsRules.test.ts +6 -2
- package/src/__tests__/styles/controlRefreshRules.test.ts +0 -6
- package/src/__tests__/styles/cssTokens.test.ts +2 -2
- package/src/__tests__/styles/menusShellRefresh.test.ts +14 -10
- package/src/__tests__/utils/plotlyTemplate.test.ts +4 -4
- package/src/__tests__/utils/time.test.ts +18 -1
- package/src/components/AdductText.story.vue +7 -0
- package/src/components/AdductText.vue +1 -1
- package/src/components/AlertBox.story.vue +2 -2
- package/src/components/AlertBox.vue +18 -16
- package/src/components/AppSidebar.story.vue +0 -28
- package/src/components/AppTopBar.story.vue +47 -12
- package/src/components/AppTopBar.vue +118 -114
- package/src/components/ArtifactSaveDialog.story.vue +23 -0
- package/src/components/ArtifactSaveDialog.vue +102 -12
- package/src/components/AuditTrail.story.vue +2 -1
- package/src/components/AuditTrail.vue +2 -21
- package/src/components/Avatar.vue +10 -14
- package/src/components/BaseSelect.multiple.story.vue +13 -2
- package/src/components/BaseSelect.vue +4 -3
- package/src/components/BatchProgressList.vue +35 -25
- package/src/components/ChartContainer.story.vue +2 -1
- package/src/components/ChartContainer.vue +8 -6
- package/src/components/ConfirmDialog.story.vue +1 -1
- package/src/components/EmptyState.vue +1 -1
- package/src/components/ExperimentPopover.story.vue +165 -53
- package/src/components/ExperimentPopover.vue +169 -187
- package/src/components/ExperimentSelectorModal.story.vue +40 -36
- package/src/components/ExperimentSelectorModal.vue +124 -110
- package/src/components/FormField.story.vue +8 -48
- package/src/components/GeneratedPluginView.vue +7 -1
- package/src/components/InstrumentStateBadge.vue +1 -1
- package/src/components/JobsStatusTray.vue +1 -1
- package/src/components/LoadingSpinner.vue +1 -1
- package/src/components/NumberInput.vue +3 -6
- package/src/components/PluginIcon.story.vue +2 -10
- package/src/components/PluginIcon.vue +2 -2
- package/src/components/PluginWorkspaceView.story.vue +1 -1
- package/src/components/RuntimeUpdateNotice.vue +1 -1
- package/src/components/SampleSelector.story.vue +1 -1
- package/src/components/SampleSelector.vue +27 -37
- package/src/components/SampleSelectorGroupNode.vue +1 -1
- package/src/components/SectionCard.story.vue +2 -2
- package/src/components/SequenceProgressBar.story.vue +9 -0
- package/src/components/SequenceProgressBar.vue +6 -1
- package/src/components/SettingsModal.schema.ts +1 -1
- package/src/components/SettingsModal.vue +2 -2
- package/src/components/SmartGroupFieldRecipe.story.vue +1 -1
- package/src/components/SmartGroupManual.story.vue +1 -1
- package/src/components/StepWizard.story.vue +33 -0
- package/src/components/StepWizard.vue +8 -1
- package/src/components/WellPlate.story.vue +3 -1
- package/src/components/WellPlate.vue +7 -0
- package/src/components/internal/AppTopBarPillNavInternal.vue +33 -2
- package/src/components/internal/DatePickerDateInternal.vue +16 -40
- package/src/components/internal/DatePickerDateTimeInternal.vue +3 -13
- package/src/components/internal/DatePickerTimeInternal.vue +5 -8
- package/src/components/internal/ResourcePickerListInternal.vue +45 -85
- package/src/components/internal/SelectMultipleInternal.vue +182 -65
- package/src/components/internal/SelectSearchableInternal.vue +2 -3
- package/src/composables/createClient.ts +2 -0
- package/src/composables/index.ts +1 -0
- package/src/composables/pluginIdentity.ts +31 -0
- package/src/composables/pluginWorkspaceModel.ts +2 -2
- package/src/composables/useAppExperiment.ts +20 -0
- package/src/composables/useCalendarGrid.ts +4 -3
- package/src/composables/useExperimentSelector.ts +77 -31
- package/src/composables/usePluginWorkspace.ts +1 -1
- package/src/styles/components/adduct-text.css +13 -5
- package/src/styles/components/alert-box.css +39 -58
- package/src/styles/components/app-layout.css +6 -5
- package/src/styles/components/app-page-selector.css +3 -1
- package/src/styles/components/app-pill-nav.css +11 -12
- package/src/styles/components/app-sidebar.css +9 -18
- package/src/styles/components/app-top-bar.css +57 -55
- package/src/styles/components/artifact-save-dialog.css +153 -2
- package/src/styles/components/audit-trail.css +16 -19
- package/src/styles/components/avatar.css +6 -4
- package/src/styles/components/batch-progress-list.css +38 -36
- package/src/styles/components/button.css +28 -59
- package/src/styles/components/calendar.css +12 -12
- package/src/styles/components/chart-container.css +34 -23
- package/src/styles/components/checkbox.css +2 -12
- package/src/styles/components/collapsible-card.css +27 -29
- package/src/styles/components/confirm-dialog.css +13 -14
- package/src/styles/components/dataframe.css +12 -4
- package/src/styles/components/date-picker.css +80 -92
- package/src/styles/components/datetime-picker.css +31 -43
- package/src/styles/components/divider.css +20 -20
- package/src/styles/components/dose-calculator.css +3 -3
- package/src/styles/components/empty-state.css +20 -17
- package/src/styles/components/experiment-code-badge.css +2 -0
- package/src/styles/components/experiment-popover.css +174 -329
- package/src/styles/components/experiment-selector-modal.css +75 -56
- package/src/styles/components/file-picker.css +3 -3
- package/src/styles/components/file-uploader.css +38 -49
- package/src/styles/components/form-builder.css +3 -3
- package/src/styles/components/formula-input.css +1 -1
- package/src/styles/components/icon-button.css +18 -24
- package/src/styles/components/input.css +5 -4
- package/src/styles/components/instrument-monitor.css +13 -15
- package/src/styles/components/jobs-status-tray.css +31 -25
- package/src/styles/components/modal.css +2 -4
- package/src/styles/components/molecule-input.css +2 -2
- package/src/styles/components/multi-select.css +65 -117
- package/src/styles/components/number-input.css +26 -19
- package/src/styles/components/pill.css +3 -2
- package/src/styles/components/plate-editor.css +0 -1
- package/src/styles/components/plugin-icon.css +26 -23
- package/src/styles/components/popover.css +2 -2
- package/src/styles/components/presence-avatars.css +1 -1
- package/src/styles/components/protocol-step-editor.css +1 -3
- package/src/styles/components/resource-card.css +2 -2
- package/src/styles/components/resource-picker-list.css +6 -57
- package/src/styles/components/sample-hierarchy-tree.css +4 -4
- package/src/styles/components/sample-selector.css +95 -79
- package/src/styles/components/schedule-calendar.css +8 -8
- package/src/styles/components/searchable-select.css +12 -12
- package/src/styles/components/section-card.css +28 -47
- package/src/styles/components/segmented-control.css +18 -15
- package/src/styles/components/select.css +3 -3
- package/src/styles/components/sequence-input.css +2 -2
- package/src/styles/components/sequence-progress-bar.css +17 -8
- package/src/styles/components/smart-group.css +18 -18
- package/src/styles/components/step-wizard.css +52 -16
- package/src/styles/components/tabs.css +2 -2
- package/src/styles/components/textarea.css +3 -3
- package/src/styles/components/time-picker.css +36 -21
- package/src/styles/components/toast.css +12 -10
- package/src/styles/components/toggle.css +1 -11
- package/src/styles/components/tooltip.css +10 -9
- package/src/styles/components/unit-input.css +8 -7
- package/src/styles/components/well-plate.css +9 -2
- package/src/styles/variables.css +106 -75
- package/src/types/componentWorkflowTypes.ts +2 -0
- package/src/types/generated/platformContext.ts +1 -0
- package/src/types/generated-ui.ts +4 -0
- package/src/utils/time.ts +21 -0
- package/dist/ActionMenu-CScINahU.js.map +0 -1
- package/dist/AppSidebar-BmiiPfz9.js.map +0 -1
- package/dist/BaseModal-DfRIuVoj.js.map +0 -1
- package/dist/ExperimentPopover-C4sGw-is.js +0 -359
- package/dist/ExperimentPopover-C4sGw-is.js.map +0 -1
- package/dist/ExperimentSelectorModal-D-9z7cNx.js.map +0 -1
- package/dist/SettingsModal-CSLE31yg.js.map +0 -1
- package/dist/data-C2PwI_dn.js.map +0 -1
- package/dist/lab-DLwRl_Ql.js.map +0 -1
- package/dist/records-BzTcxekG.js.map +0 -1
- package/dist/runtime-D6gVat6r.js.map +0 -1
- package/dist/useListReorder-CcbEYxX-.js.map +0 -1
- package/dist/useRackEditor-BD5NIo5s.js.map +0 -1
- package/dist/useRealtime-PalKue84.js.map +0 -1
- package/dist/useRequest-D5JDfsgZ.js +0 -76
- package/dist/useRequest-D5JDfsgZ.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as BaseButton_default, n as BaseModal_default } from "./useDropdownState-8yWMu-7_.js";
|
|
2
2
|
import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, renderSlot, toDisplayString, withCtx } from "vue";
|
|
3
3
|
//#region src/components/ConfirmDialog.vue?vue&type=script&setup=true&lang.ts
|
|
4
4
|
var _hoisted_1 = { class: "mint-confirm" };
|
|
@@ -99,4 +99,4 @@ var ConfirmDialog_default = /* @__PURE__ */ defineComponent({
|
|
|
99
99
|
//#endregion
|
|
100
100
|
export { ConfirmDialog_default as t };
|
|
101
101
|
|
|
102
|
-
//# sourceMappingURL=ConfirmDialog-
|
|
102
|
+
//# sourceMappingURL=ConfirmDialog-nbJj51is.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfirmDialog-
|
|
1
|
+
{"version":3,"file":"ConfirmDialog-nbJj51is.js","names":["$slots"],"sources":["../src/components/ConfirmDialog.vue","../src/components/ConfirmDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/** Confirm/cancel dialog whose `tone` colors the confirm button; blocks close while loading. */\nimport { computed } from 'vue'\nimport type { ButtonVariant, Tone } from '../types'\nimport BaseModal from './BaseModal.vue'\nimport BaseButton from './BaseButton.vue'\n\ninterface Props {\n open: boolean\n title?: string\n subtitle?: string\n message?: string\n tone?: Tone\n confirmLabel?: string\n cancelLabel?: string\n loading?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: 'Confirm',\n tone: 'error',\n confirmLabel: 'Confirm',\n cancelLabel: 'Cancel',\n loading: false,\n})\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean]\n confirm: []\n cancel: []\n}>()\n\nfunction handleCancel() {\n emit('update:open', false)\n emit('cancel')\n}\n\nfunction handleConfirm() {\n emit('confirm')\n}\n\nconst confirmVariant = computed<ButtonVariant>(() => {\n if (props.tone === 'error') return 'danger'\n if (props.tone === 'warning' || props.tone === 'cta') return 'cta'\n if (props.tone === 'success') return 'success'\n return 'primary'\n})\n</script>\n\n<template>\n <BaseModal\n :open=\"open\"\n :title=\"title\"\n :subtitle=\"subtitle\"\n size=\"sm\"\n :closable=\"!loading\"\n :close-on-overlay=\"!loading\"\n :close-on-escape=\"!loading\"\n @update:open=\"emit('update:open', $event)\"\n >\n <div class=\"mint-confirm\">\n <!-- Icon is now opt-in via slot. Refresh design keeps the body focused on\n the message; tone is carried by the confirm button's color. -->\n <div\n v-if=\"$slots.icon\"\n :class=\"['mint-confirm__icon', `mint-confirm__icon--${tone}`]\"\n >\n <slot name=\"icon\" />\n </div>\n <p v-if=\"message\" class=\"mint-confirm__message\">{{ message }}</p>\n <slot />\n </div>\n\n <template #footer>\n <div class=\"mint-confirm__footer\">\n <BaseButton\n type=\"button\"\n variant=\"secondary\"\n size=\"md\"\n :disabled=\"loading\"\n @click=\"handleCancel\"\n >\n {{ cancelLabel }}\n </BaseButton>\n <BaseButton\n type=\"button\"\n :variant=\"confirmVariant\"\n size=\"md\"\n :loading=\"loading\"\n @click=\"handleConfirm\"\n >\n {{ confirmLabel }}\n </BaseButton>\n </div>\n </template>\n </BaseModal>\n</template>\n","<script setup lang=\"ts\">\n/** Confirm/cancel dialog whose `tone` colors the confirm button; blocks close while loading. */\nimport { computed } from 'vue'\nimport type { ButtonVariant, Tone } from '../types'\nimport BaseModal from './BaseModal.vue'\nimport BaseButton from './BaseButton.vue'\n\ninterface Props {\n open: boolean\n title?: string\n subtitle?: string\n message?: string\n tone?: Tone\n confirmLabel?: string\n cancelLabel?: string\n loading?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: 'Confirm',\n tone: 'error',\n confirmLabel: 'Confirm',\n cancelLabel: 'Cancel',\n loading: false,\n})\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean]\n confirm: []\n cancel: []\n}>()\n\nfunction handleCancel() {\n emit('update:open', false)\n emit('cancel')\n}\n\nfunction handleConfirm() {\n emit('confirm')\n}\n\nconst confirmVariant = computed<ButtonVariant>(() => {\n if (props.tone === 'error') return 'danger'\n if (props.tone === 'warning' || props.tone === 'cta') return 'cta'\n if (props.tone === 'success') return 'success'\n return 'primary'\n})\n</script>\n\n<template>\n <BaseModal\n :open=\"open\"\n :title=\"title\"\n :subtitle=\"subtitle\"\n size=\"sm\"\n :closable=\"!loading\"\n :close-on-overlay=\"!loading\"\n :close-on-escape=\"!loading\"\n @update:open=\"emit('update:open', $event)\"\n >\n <div class=\"mint-confirm\">\n <!-- Icon is now opt-in via slot. Refresh design keeps the body focused on\n the message; tone is carried by the confirm button's color. -->\n <div\n v-if=\"$slots.icon\"\n :class=\"['mint-confirm__icon', `mint-confirm__icon--${tone}`]\"\n >\n <slot name=\"icon\" />\n </div>\n <p v-if=\"message\" class=\"mint-confirm__message\">{{ message }}</p>\n <slot />\n </div>\n\n <template #footer>\n <div class=\"mint-confirm__footer\">\n <BaseButton\n type=\"button\"\n variant=\"secondary\"\n size=\"md\"\n :disabled=\"loading\"\n @click=\"handleCancel\"\n >\n {{ cancelLabel }}\n </BaseButton>\n <BaseButton\n type=\"button\"\n :variant=\"confirmVariant\"\n size=\"md\"\n :loading=\"loading\"\n @click=\"handleConfirm\"\n >\n {{ confirmLabel }}\n </BaseButton>\n </div>\n </template>\n </BaseModal>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBA,MAAM,QAAQ;EAQd,MAAM,OAAO;EAMb,SAAS,eAAe;GACtB,KAAK,eAAe,KAAK;GACzB,KAAK,QAAQ;EACf;EAEA,SAAS,gBAAgB;GACvB,KAAK,SAAS;EAChB;EAEA,MAAM,iBAAiB,eAA8B;GACnD,IAAI,MAAM,SAAS,SAAS,OAAO;GACnC,IAAI,MAAM,SAAS,aAAa,MAAM,SAAS,OAAO,OAAO;GAC7D,IAAI,MAAM,SAAS,WAAW,OAAO;GACrC,OAAO;EACT,CAAC;;GAIC,OAAA,UAAA,GAAA,YA6CY,mBAAA;IA5CT,MAAM,QAAA;IACN,OAAO,QAAA;IACP,UAAU,QAAA;IACX,MAAK;IACJ,UAAQ,CAAG,QAAA;IACX,oBAAgB,CAAG,QAAA;IACnB,mBAAe,CAAG,QAAA;IAClB,iBAAW,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,eAAgB,MAAM;;IAe7B,QAAM,cAoBT,CAnBN,mBAmBM,OAnBN,YAmBM,CAlBJ,YAQa,oBAAA;KAPX,MAAK;KACL,SAAQ;KACR,MAAK;KACJ,UAAU,QAAA;KACV,SAAO;;KAER,SAAA,cAAiB,CAAd,gBAAA,gBAAA,QAAA,WAAW,GAAA,CAAA,CAAA,CAAA;;IAEhB,GAAA,GAAA,CAAA,UAAA,CAAA,GAAA,YAQa,oBAAA;KAPX,MAAK;KACJ,SAAS,eAAA;KACV,MAAK;KACJ,SAAS,QAAA;KACT,SAAO;;KAER,SAAA,cAAkB,CAAf,gBAAA,gBAAA,QAAA,YAAY,GAAA,CAAA,CAAA,CAAA;;;IA/BrB,SAAA,cAWM,CAXN,mBAWM,OAXN,YAWM;KAPIA,KAAAA,OAAO,QADf,UAAA,GAAA,mBAKM,OAAA;;MAHH,OAAK,eAAA,CAAA,sBAAA,uBAAgD,QAAA,MAAI,CAAA;KAE1D,GAAA,CAAA,WAAoB,KAAA,QAAA,MAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;KAEb,QAAA,WAAT,UAAA,GAAA,mBAAiE,KAAjE,YAAiE,gBAAd,QAAA,OAAO,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;KAC1D,WAAQ,KAAA,QAAA,SAAA"}
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import { o as __exportAll, t as useDropdownState } from "./useDropdownState-8yWMu-7_.js";
|
|
2
|
+
import { A as formatRelativeTime } from "./records-B6gpM_3e.js";
|
|
3
|
+
import { t as ConfirmDialog_default } from "./ConfirmDialog-nbJj51is.js";
|
|
4
|
+
import { n as format } from "./experimentStatus-Cqp6qNrR.js";
|
|
5
|
+
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, nextTick, normalizeClass, normalizeStyle, onUnmounted, openBlock, ref, renderList, toDisplayString, unref, useTemplateRef, watch, withModifiers } from "vue";
|
|
6
|
+
import { ArrowLeftRight, Check, ChevronDown, CircleAlert, CloudUpload, ExternalLink, Link, LoaderCircle, Unlink } from "lucide-vue-next";
|
|
7
|
+
//#region src/components/ExperimentPopover.vue?vue&type=script&setup=true&lang.ts
|
|
8
|
+
var _hoisted_1 = [
|
|
9
|
+
"title",
|
|
10
|
+
"aria-label",
|
|
11
|
+
"aria-busy",
|
|
12
|
+
"aria-expanded"
|
|
13
|
+
];
|
|
14
|
+
var _hoisted_2 = {
|
|
15
|
+
key: 0,
|
|
16
|
+
class: "mint-experiment-popover__trigger-skeleton",
|
|
17
|
+
"aria-hidden": "true"
|
|
18
|
+
};
|
|
19
|
+
var _hoisted_3 = {
|
|
20
|
+
key: 0,
|
|
21
|
+
class: "mint-exp-code mint-exp-code--sm"
|
|
22
|
+
};
|
|
23
|
+
var _hoisted_4 = { class: "mint-experiment-popover__trigger-text" };
|
|
24
|
+
var _hoisted_5 = [
|
|
25
|
+
"disabled",
|
|
26
|
+
"title",
|
|
27
|
+
"aria-label"
|
|
28
|
+
];
|
|
29
|
+
var _hoisted_6 = {
|
|
30
|
+
key: 3,
|
|
31
|
+
class: "mint-experiment-popover__dirty",
|
|
32
|
+
"aria-hidden": "true"
|
|
33
|
+
};
|
|
34
|
+
var _hoisted_7 = {
|
|
35
|
+
key: 0,
|
|
36
|
+
class: "mint-experiment-popover__head",
|
|
37
|
+
"aria-busy": "true"
|
|
38
|
+
};
|
|
39
|
+
var _hoisted_8 = {
|
|
40
|
+
key: 1,
|
|
41
|
+
class: "mint-experiment-popover__head mint-experiment-popover__head--error",
|
|
42
|
+
role: "alert"
|
|
43
|
+
};
|
|
44
|
+
var _hoisted_9 = { class: "mint-experiment-popover__name" };
|
|
45
|
+
var _hoisted_10 = { class: "mint-experiment-popover__message" };
|
|
46
|
+
var _hoisted_11 = { class: "mint-experiment-popover__head" };
|
|
47
|
+
var _hoisted_12 = {
|
|
48
|
+
key: 0,
|
|
49
|
+
class: "mint-exp-code mint-exp-code--sm"
|
|
50
|
+
};
|
|
51
|
+
var _hoisted_13 = {
|
|
52
|
+
key: 1,
|
|
53
|
+
class: "mint-experiment-popover__name"
|
|
54
|
+
};
|
|
55
|
+
var _hoisted_14 = {
|
|
56
|
+
key: 0,
|
|
57
|
+
class: "mint-experiment-popover__meta"
|
|
58
|
+
};
|
|
59
|
+
var _hoisted_15 = ["href"];
|
|
60
|
+
var ExperimentPopover_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
|
|
61
|
+
__name: "ExperimentPopover",
|
|
62
|
+
props: {
|
|
63
|
+
experimentName: {},
|
|
64
|
+
experimentCode: {},
|
|
65
|
+
experimentStatus: {},
|
|
66
|
+
experimentId: { default: null },
|
|
67
|
+
experimentProject: {},
|
|
68
|
+
experimentOwner: {},
|
|
69
|
+
experimentUpdatedAt: {},
|
|
70
|
+
isResolving: {
|
|
71
|
+
type: Boolean,
|
|
72
|
+
default: false
|
|
73
|
+
},
|
|
74
|
+
error: {},
|
|
75
|
+
showSave: {
|
|
76
|
+
type: Boolean,
|
|
77
|
+
default: false
|
|
78
|
+
},
|
|
79
|
+
showDetach: {
|
|
80
|
+
type: Boolean,
|
|
81
|
+
default: false
|
|
82
|
+
},
|
|
83
|
+
saveDisabled: {
|
|
84
|
+
type: Boolean,
|
|
85
|
+
default: false
|
|
86
|
+
},
|
|
87
|
+
saveLoading: {
|
|
88
|
+
type: Boolean,
|
|
89
|
+
default: false
|
|
90
|
+
},
|
|
91
|
+
saveSuccessMessage: {},
|
|
92
|
+
saveDisabledMessage: {},
|
|
93
|
+
saveLabel: { default: "Save" },
|
|
94
|
+
dirty: {
|
|
95
|
+
type: Boolean,
|
|
96
|
+
default: false
|
|
97
|
+
},
|
|
98
|
+
confirmSave: {
|
|
99
|
+
type: Boolean,
|
|
100
|
+
default: true
|
|
101
|
+
},
|
|
102
|
+
confirmTitle: {},
|
|
103
|
+
confirmMessage: {},
|
|
104
|
+
placeholder: { default: "Attach experiment" },
|
|
105
|
+
maxNameWidth: { default: 200 }
|
|
106
|
+
},
|
|
107
|
+
emits: [
|
|
108
|
+
"select",
|
|
109
|
+
"save",
|
|
110
|
+
"detach"
|
|
111
|
+
],
|
|
112
|
+
setup(__props, { emit: __emit }) {
|
|
113
|
+
/** Top-bar control for the attached experiment: a trigger joined to an optional Save button, with a summary panel (change, open, detach). */
|
|
114
|
+
const props = __props;
|
|
115
|
+
const isUnresolved = computed(() => props.isResolving || !!props.error);
|
|
116
|
+
const hasExperiment = computed(() => !!props.experimentName || !!props.experimentCode);
|
|
117
|
+
const isEmpty = computed(() => !isUnresolved.value && !hasExperiment.value);
|
|
118
|
+
const hasSave = computed(() => props.showSave && !isUnresolved.value && hasExperiment.value);
|
|
119
|
+
const triggerLabel = computed(() => {
|
|
120
|
+
if (props.isResolving) return "Loading experiment";
|
|
121
|
+
if (props.error) return "Experiment unavailable";
|
|
122
|
+
return [props.experimentCode, props.experimentName].filter(Boolean).join(" · ") || props.placeholder;
|
|
123
|
+
});
|
|
124
|
+
const emit = __emit;
|
|
125
|
+
const { isOpen, close, toggle } = useDropdownState({
|
|
126
|
+
rootRef: useTemplateRef("popover"),
|
|
127
|
+
triggerRef: useTemplateRef("trigger"),
|
|
128
|
+
closeOnEscape: false
|
|
129
|
+
});
|
|
130
|
+
const showSuccess = ref(false);
|
|
131
|
+
const showConfirm = ref(false);
|
|
132
|
+
const panel = useTemplateRef("panel");
|
|
133
|
+
const panelAlignEnd = ref(false);
|
|
134
|
+
watch(isOpen, async (open) => {
|
|
135
|
+
if (!open) return;
|
|
136
|
+
panelAlignEnd.value = false;
|
|
137
|
+
await nextTick();
|
|
138
|
+
const right = panel.value?.getBoundingClientRect().right ?? 0;
|
|
139
|
+
panelAlignEnd.value = right > document.documentElement.clientWidth;
|
|
140
|
+
});
|
|
141
|
+
const saveTitle = computed(() => {
|
|
142
|
+
if (props.saveDisabled && props.saveDisabledMessage) return props.saveDisabledMessage;
|
|
143
|
+
if (showSuccess.value && props.saveSuccessMessage) return props.saveSuccessMessage;
|
|
144
|
+
return `${props.saveLabel} to experiment`;
|
|
145
|
+
});
|
|
146
|
+
function metaRows() {
|
|
147
|
+
return [
|
|
148
|
+
["Project", props.experimentProject],
|
|
149
|
+
["Status", props.experimentStatus && format(props.experimentStatus)],
|
|
150
|
+
["Owner", props.experimentOwner],
|
|
151
|
+
["Updated", props.experimentUpdatedAt && formatRelativeTime(props.experimentUpdatedAt)]
|
|
152
|
+
].filter((row) => !!row[1]);
|
|
153
|
+
}
|
|
154
|
+
function handleTriggerClick() {
|
|
155
|
+
if (isEmpty.value) {
|
|
156
|
+
emit("select");
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
toggle();
|
|
160
|
+
}
|
|
161
|
+
function handleSelect() {
|
|
162
|
+
emit("select");
|
|
163
|
+
close();
|
|
164
|
+
}
|
|
165
|
+
function handleSave() {
|
|
166
|
+
if (props.saveDisabled || props.saveLoading) return;
|
|
167
|
+
close();
|
|
168
|
+
if (props.confirmSave) showConfirm.value = true;
|
|
169
|
+
else emit("save");
|
|
170
|
+
}
|
|
171
|
+
function handleConfirmSave() {
|
|
172
|
+
showConfirm.value = false;
|
|
173
|
+
emit("save");
|
|
174
|
+
}
|
|
175
|
+
function handleDetach() {
|
|
176
|
+
emit("detach");
|
|
177
|
+
close();
|
|
178
|
+
}
|
|
179
|
+
let successTimer = null;
|
|
180
|
+
watch(() => props.saveSuccessMessage, (msg) => {
|
|
181
|
+
if (successTimer) clearTimeout(successTimer);
|
|
182
|
+
if (msg) {
|
|
183
|
+
showSuccess.value = true;
|
|
184
|
+
successTimer = setTimeout(() => {
|
|
185
|
+
showSuccess.value = false;
|
|
186
|
+
successTimer = null;
|
|
187
|
+
}, 3e3);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
onUnmounted(() => {
|
|
191
|
+
if (successTimer) clearTimeout(successTimer);
|
|
192
|
+
});
|
|
193
|
+
return (_ctx, _cache) => {
|
|
194
|
+
return openBlock(), createElementBlock("div", {
|
|
195
|
+
ref: "popover",
|
|
196
|
+
class: normalizeClass(["mint-experiment-popover", { "mint-experiment-popover--save": hasSave.value }])
|
|
197
|
+
}, [
|
|
198
|
+
createElementVNode("button", {
|
|
199
|
+
ref: "trigger",
|
|
200
|
+
type: "button",
|
|
201
|
+
class: normalizeClass([
|
|
202
|
+
"mint-experiment-popover__trigger",
|
|
203
|
+
{ "mint-experiment-popover__trigger--active": unref(isOpen) },
|
|
204
|
+
{ "mint-experiment-popover__trigger--empty": isEmpty.value },
|
|
205
|
+
{ "mint-experiment-popover__trigger--loading": __props.isResolving },
|
|
206
|
+
{ "mint-experiment-popover__trigger--error": !__props.isResolving && !!__props.error }
|
|
207
|
+
]),
|
|
208
|
+
title: triggerLabel.value,
|
|
209
|
+
"aria-label": isUnresolved.value ? triggerLabel.value : void 0,
|
|
210
|
+
"aria-busy": __props.isResolving || void 0,
|
|
211
|
+
"aria-expanded": isEmpty.value ? void 0 : unref(isOpen),
|
|
212
|
+
onClick: withModifiers(handleTriggerClick, ["stop"])
|
|
213
|
+
}, [__props.isResolving ? (openBlock(), createElementBlock("span", _hoisted_2)) : __props.error ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [createVNode(unref(CircleAlert), {
|
|
214
|
+
class: "mint-experiment-popover__trigger-icon",
|
|
215
|
+
size: 14,
|
|
216
|
+
"aria-hidden": "true"
|
|
217
|
+
}), _cache[2] || (_cache[2] = createElementVNode("span", { class: "mint-experiment-popover__trigger-text" }, "Experiment unavailable", -1))], 64)) : hasExperiment.value ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [__props.experimentCode ? (openBlock(), createElementBlock("span", _hoisted_3, toDisplayString(__props.experimentCode), 1)) : createCommentVNode("", true), __props.experimentName ? (openBlock(), createElementBlock("span", {
|
|
218
|
+
key: 1,
|
|
219
|
+
class: "mint-experiment-popover__trigger-text",
|
|
220
|
+
style: normalizeStyle({ maxWidth: `${__props.maxNameWidth}px` })
|
|
221
|
+
}, toDisplayString(__props.experimentName), 5)) : createCommentVNode("", true)], 64)) : (openBlock(), createElementBlock(Fragment, { key: 3 }, [createVNode(unref(Link), {
|
|
222
|
+
class: "mint-experiment-popover__trigger-icon",
|
|
223
|
+
size: 14,
|
|
224
|
+
"aria-hidden": "true"
|
|
225
|
+
}), createElementVNode("span", _hoisted_4, toDisplayString(__props.placeholder), 1)], 64)), !isEmpty.value ? (openBlock(), createBlock(unref(ChevronDown), {
|
|
226
|
+
key: 4,
|
|
227
|
+
class: "mint-experiment-popover__trigger-chevron",
|
|
228
|
+
size: 13,
|
|
229
|
+
"aria-hidden": "true"
|
|
230
|
+
})) : createCommentVNode("", true)], 10, _hoisted_1),
|
|
231
|
+
hasSave.value ? (openBlock(), createElementBlock("button", {
|
|
232
|
+
key: 0,
|
|
233
|
+
type: "button",
|
|
234
|
+
class: normalizeClass([
|
|
235
|
+
"mint-experiment-popover__save",
|
|
236
|
+
{ "mint-experiment-popover__save--loading": __props.saveLoading },
|
|
237
|
+
{ "mint-experiment-popover__save--success": showSuccess.value },
|
|
238
|
+
{ "mint-experiment-popover__save--disabled": __props.saveDisabled && !showSuccess.value }
|
|
239
|
+
]),
|
|
240
|
+
disabled: __props.saveLoading || __props.saveDisabled && !showSuccess.value,
|
|
241
|
+
title: saveTitle.value,
|
|
242
|
+
"aria-label": __props.dirty ? `${saveTitle.value} (unsaved changes)` : saveTitle.value,
|
|
243
|
+
onClick: withModifiers(handleSave, ["stop"])
|
|
244
|
+
}, [
|
|
245
|
+
__props.saveLoading ? (openBlock(), createBlock(unref(LoaderCircle), {
|
|
246
|
+
key: 0,
|
|
247
|
+
class: "mint-experiment-popover__save-spinner",
|
|
248
|
+
size: 14,
|
|
249
|
+
"aria-hidden": "true"
|
|
250
|
+
})) : showSuccess.value ? (openBlock(), createBlock(unref(Check), {
|
|
251
|
+
key: 1,
|
|
252
|
+
size: 14,
|
|
253
|
+
"aria-hidden": "true"
|
|
254
|
+
})) : (openBlock(), createBlock(unref(CloudUpload), {
|
|
255
|
+
key: 2,
|
|
256
|
+
size: 14,
|
|
257
|
+
"aria-hidden": "true"
|
|
258
|
+
})),
|
|
259
|
+
createElementVNode("span", null, toDisplayString(__props.saveLoading ? "Saving…" : __props.saveLabel), 1),
|
|
260
|
+
__props.dirty && !__props.saveLoading ? (openBlock(), createElementBlock("span", _hoisted_6)) : createCommentVNode("", true)
|
|
261
|
+
], 10, _hoisted_5)) : createCommentVNode("", true),
|
|
262
|
+
unref(isOpen) ? (openBlock(), createElementBlock("div", {
|
|
263
|
+
key: 1,
|
|
264
|
+
ref_key: "panel",
|
|
265
|
+
ref: panel,
|
|
266
|
+
class: normalizeClass(["mint-experiment-popover__panel", { "mint-experiment-popover__panel--end": panelAlignEnd.value }])
|
|
267
|
+
}, [
|
|
268
|
+
__props.isResolving ? (openBlock(), createElementBlock("div", _hoisted_7, [..._cache[3] || (_cache[3] = [createElementVNode("span", { class: "mint-experiment-popover__skeleton-line mint-experiment-popover__skeleton-line--code" }, null, -1), createElementVNode("span", { class: "mint-experiment-popover__skeleton-line mint-experiment-popover__skeleton-line--name" }, null, -1)])])) : __props.error ? (openBlock(), createElementBlock("div", _hoisted_8, [createElementVNode("b", _hoisted_9, [createVNode(unref(CircleAlert), {
|
|
269
|
+
size: 14,
|
|
270
|
+
"aria-hidden": "true"
|
|
271
|
+
}), _cache[4] || (_cache[4] = createTextVNode(" Experiment unavailable ", -1))]), createElementVNode("span", _hoisted_10, toDisplayString(__props.error), 1)])) : (openBlock(), createElementBlock(Fragment, { key: 2 }, [createElementVNode("div", _hoisted_11, [__props.experimentCode ? (openBlock(), createElementBlock("span", _hoisted_12, toDisplayString(__props.experimentCode), 1)) : createCommentVNode("", true), __props.experimentName ? (openBlock(), createElementBlock("b", _hoisted_13, toDisplayString(__props.experimentName), 1)) : createCommentVNode("", true)]), metaRows().length ? (openBlock(), createElementBlock("dl", _hoisted_14, [(openBlock(true), createElementBlock(Fragment, null, renderList(metaRows(), ([label, value]) => {
|
|
272
|
+
return openBlock(), createElementBlock(Fragment, { key: label }, [createElementVNode("dt", null, toDisplayString(label), 1), createElementVNode("dd", null, toDisplayString(value), 1)], 64);
|
|
273
|
+
}), 128))])) : createCommentVNode("", true)], 64)),
|
|
274
|
+
_cache[8] || (_cache[8] = createElementVNode("div", {
|
|
275
|
+
class: "mint-experiment-popover__separator",
|
|
276
|
+
role: "separator"
|
|
277
|
+
}, null, -1)),
|
|
278
|
+
createElementVNode("button", {
|
|
279
|
+
type: "button",
|
|
280
|
+
class: "mint-experiment-popover__option",
|
|
281
|
+
onClick: handleSelect
|
|
282
|
+
}, [createVNode(unref(ArrowLeftRight), {
|
|
283
|
+
class: "mint-experiment-popover__option-icon",
|
|
284
|
+
size: 14,
|
|
285
|
+
"aria-hidden": "true"
|
|
286
|
+
}), _cache[5] || (_cache[5] = createTextVNode(" Change experiment… ", -1))]),
|
|
287
|
+
__props.experimentId != null ? (openBlock(), createElementBlock("a", {
|
|
288
|
+
key: 3,
|
|
289
|
+
class: "mint-experiment-popover__option",
|
|
290
|
+
href: `/experiments/${__props.experimentId}`,
|
|
291
|
+
target: "_blank",
|
|
292
|
+
rel: "noopener",
|
|
293
|
+
onClick: _cache[0] || (_cache[0] = ($event) => unref(close)())
|
|
294
|
+
}, [createVNode(unref(ExternalLink), {
|
|
295
|
+
class: "mint-experiment-popover__option-icon",
|
|
296
|
+
size: 14,
|
|
297
|
+
"aria-hidden": "true"
|
|
298
|
+
}), _cache[6] || (_cache[6] = createTextVNode(" Open in MINT ", -1))], 8, _hoisted_15)) : createCommentVNode("", true),
|
|
299
|
+
__props.showDetach ? (openBlock(), createElementBlock("button", {
|
|
300
|
+
key: 4,
|
|
301
|
+
type: "button",
|
|
302
|
+
class: "mint-experiment-popover__option mint-experiment-popover__option--danger",
|
|
303
|
+
onClick: handleDetach
|
|
304
|
+
}, [createVNode(unref(Unlink), {
|
|
305
|
+
class: "mint-experiment-popover__option-icon",
|
|
306
|
+
size: 14,
|
|
307
|
+
"aria-hidden": "true"
|
|
308
|
+
}), _cache[7] || (_cache[7] = createTextVNode(" Detach ", -1))])) : createCommentVNode("", true)
|
|
309
|
+
], 2)) : createCommentVNode("", true),
|
|
310
|
+
createVNode(ConfirmDialog_default, {
|
|
311
|
+
open: showConfirm.value,
|
|
312
|
+
"onUpdate:open": _cache[1] || (_cache[1] = ($event) => showConfirm.value = $event),
|
|
313
|
+
title: __props.confirmTitle ?? "Save to Experiment",
|
|
314
|
+
message: __props.confirmMessage ?? `Save current data to ${__props.experimentName ?? __props.experimentCode}?`,
|
|
315
|
+
tone: "info",
|
|
316
|
+
"confirm-label": __props.saveLabel,
|
|
317
|
+
loading: __props.saveLoading,
|
|
318
|
+
onConfirm: handleConfirmSave
|
|
319
|
+
}, null, 8, [
|
|
320
|
+
"open",
|
|
321
|
+
"title",
|
|
322
|
+
"message",
|
|
323
|
+
"confirm-label",
|
|
324
|
+
"loading"
|
|
325
|
+
])
|
|
326
|
+
], 2);
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
//#endregion
|
|
331
|
+
//#region src/components/ExperimentPopover.vue
|
|
332
|
+
var ExperimentPopover_exports = /* @__PURE__ */ __exportAll({ default: () => ExperimentPopover_default });
|
|
333
|
+
var ExperimentPopover_default = ExperimentPopover_vue_vue_type_script_setup_true_lang_default;
|
|
334
|
+
//#endregion
|
|
335
|
+
export { ExperimentPopover_exports as n, ExperimentPopover_default as t };
|
|
336
|
+
|
|
337
|
+
//# sourceMappingURL=ExperimentPopover-5T1fAq2L.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExperimentPopover-5T1fAq2L.js","names":[],"sources":["../src/components/ExperimentPopover.vue","../src/components/ExperimentPopover.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/** Top-bar control for the attached experiment: a trigger joined to an optional Save button, with a summary panel (change, open, detach). */\nimport { ref, computed, watch, nextTick, onUnmounted, useTemplateRef } from 'vue'\nimport { ArrowLeftRight, Check, ChevronDown, CircleAlert, CloudUpload, ExternalLink, Link, LoaderCircle, Unlink } from 'lucide-vue-next'\nimport { useDropdownState } from '../composables/useDropdownState'\nimport { format as formatStatus } from '../utils/experimentStatus'\nimport { formatRelativeTime } from '../utils/time'\nimport ConfirmDialog from './ConfirmDialog.vue'\n\ninterface Props {\n experimentName?: string\n experimentCode?: string\n experimentStatus?: string\n /** Platform id of the bound experiment; enables \"Open in MINT\". */\n experimentId?: number | null\n experimentProject?: string\n experimentOwner?: string\n /** ISO timestamp of the last update, shown as relative time. */\n experimentUpdatedAt?: string\n /** An experiment is bound but the platform has not returned its record yet. */\n isResolving?: boolean\n /** Message explaining why the bound experiment could not be resolved. */\n error?: string\n showSave?: boolean\n showDetach?: boolean\n saveDisabled?: boolean\n saveLoading?: boolean\n saveSuccessMessage?: string\n saveDisabledMessage?: string\n saveLabel?: string\n /** Unsaved changes: marks the Save button with a dot. */\n dirty?: boolean\n confirmSave?: boolean\n confirmTitle?: string\n confirmMessage?: string\n /** Empty-state trigger label. */\n placeholder?: string\n /** The trigger name truncates at this width (px); its title shows code and name in full. */\n maxNameWidth?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n experimentId: null,\n isResolving: false,\n showSave: false,\n showDetach: false,\n saveDisabled: false,\n saveLoading: false,\n saveLabel: 'Save',\n dirty: false,\n confirmSave: true,\n placeholder: 'Attach experiment',\n maxNameWidth: 200,\n})\n\n// An experiment is bound but has no name to show — either still resolving or\n// resolution failed. The id is never substituted: a name may only come from the\n// platform, so these states say what is happening instead of inventing a label.\nconst isUnresolved = computed(() => props.isResolving || !!props.error)\nconst hasExperiment = computed(() => !!props.experimentName || !!props.experimentCode)\nconst isEmpty = computed(() => !isUnresolved.value && !hasExperiment.value)\nconst hasSave = computed(() => props.showSave && !isUnresolved.value && hasExperiment.value)\n\nconst triggerLabel = computed(() => {\n if (props.isResolving) return 'Loading experiment'\n if (props.error) return 'Experiment unavailable'\n return [props.experimentCode, props.experimentName].filter(Boolean).join(' · ') || props.placeholder\n})\n\nconst emit = defineEmits<{\n select: []\n save: []\n detach: []\n}>()\n\nconst { isOpen, close, toggle } = useDropdownState({\n rootRef: useTemplateRef<HTMLElement>('popover'),\n triggerRef: useTemplateRef<HTMLElement>('trigger'),\n closeOnEscape: false,\n})\nconst showSuccess = ref(false)\nconst showConfirm = ref(false)\n\n// The panel hangs from the group's left edge; when that would cross the\n// viewport's right edge (a control at the end of the top bar) it hangs from the right.\nconst panel = useTemplateRef<HTMLElement>('panel')\nconst panelAlignEnd = ref(false)\nwatch(isOpen, async (open) => {\n if (!open) return\n panelAlignEnd.value = false\n await nextTick()\n const right = panel.value?.getBoundingClientRect().right ?? 0\n panelAlignEnd.value = right > document.documentElement.clientWidth\n})\n\nconst saveTitle = computed(() => {\n if (props.saveDisabled && props.saveDisabledMessage) return props.saveDisabledMessage\n if (showSuccess.value && props.saveSuccessMessage) return props.saveSuccessMessage\n return `${props.saveLabel} to experiment`\n})\n\n// A function, not a computed: \"Updated\" is relative to now, so it is\n// re-evaluated each time the panel renders.\nfunction metaRows(): [string, string][] {\n return ([\n ['Project', props.experimentProject],\n ['Status', props.experimentStatus && formatStatus(props.experimentStatus)],\n ['Owner', props.experimentOwner],\n ['Updated', props.experimentUpdatedAt && formatRelativeTime(props.experimentUpdatedAt)],\n ] as [string, string | undefined][]).filter((row): row is [string, string] => !!row[1])\n}\n\nfunction handleTriggerClick() {\n if (isEmpty.value) {\n emit('select')\n return\n }\n toggle()\n}\n\nfunction handleSelect() {\n emit('select')\n close()\n}\n\nfunction handleSave() {\n if (props.saveDisabled || props.saveLoading) return\n close()\n if (props.confirmSave) {\n showConfirm.value = true\n } else {\n emit('save')\n }\n}\n\nfunction handleConfirmSave() {\n showConfirm.value = false\n emit('save')\n}\n\nfunction handleDetach() {\n emit('detach')\n close()\n}\n\nlet successTimer: ReturnType<typeof setTimeout> | null = null\n\n// Show success state when saveSuccessMessage changes from empty to a value\nwatch(() => props.saveSuccessMessage, (msg) => {\n if (successTimer) clearTimeout(successTimer)\n if (msg) {\n showSuccess.value = true\n successTimer = setTimeout(() => {\n showSuccess.value = false\n successTimer = null\n }, 3000)\n }\n})\n\nonUnmounted(() => {\n if (successTimer) clearTimeout(successTimer)\n})\n</script>\n\n<template>\n <div ref=\"popover\" :class=\"['mint-experiment-popover', { 'mint-experiment-popover--save': hasSave }]\">\n <!-- Trigger: code + name when attached, opens the panel; the empty state selects directly. -->\n <button\n ref=\"trigger\"\n type=\"button\"\n :class=\"[\n 'mint-experiment-popover__trigger',\n { 'mint-experiment-popover__trigger--active': isOpen },\n { 'mint-experiment-popover__trigger--empty': isEmpty },\n { 'mint-experiment-popover__trigger--loading': isResolving },\n { 'mint-experiment-popover__trigger--error': !isResolving && !!error },\n ]\"\n :title=\"triggerLabel\"\n :aria-label=\"isUnresolved ? triggerLabel : undefined\"\n :aria-busy=\"isResolving || undefined\"\n :aria-expanded=\"isEmpty ? undefined : isOpen\"\n @click.stop=\"handleTriggerClick\"\n >\n <!-- Resolving and error come first: with an experiment bound but no name\n yet, the empty placeholder would be a lie. -->\n <span v-if=\"isResolving\" class=\"mint-experiment-popover__trigger-skeleton\" aria-hidden=\"true\" />\n <template v-else-if=\"error\">\n <CircleAlert class=\"mint-experiment-popover__trigger-icon\" :size=\"14\" aria-hidden=\"true\" />\n <span class=\"mint-experiment-popover__trigger-text\">Experiment unavailable</span>\n </template>\n <template v-else-if=\"hasExperiment\">\n <span v-if=\"experimentCode\" class=\"mint-exp-code mint-exp-code--sm\">{{ experimentCode }}</span>\n <span\n v-if=\"experimentName\"\n class=\"mint-experiment-popover__trigger-text\"\n :style=\"{ maxWidth: `${maxNameWidth}px` }\"\n >{{ experimentName }}</span>\n </template>\n <template v-else>\n <Link class=\"mint-experiment-popover__trigger-icon\" :size=\"14\" aria-hidden=\"true\" />\n <span class=\"mint-experiment-popover__trigger-text\">{{ placeholder }}</span>\n </template>\n <ChevronDown v-if=\"!isEmpty\" class=\"mint-experiment-popover__trigger-chevron\" :size=\"13\" aria-hidden=\"true\" />\n </button>\n\n <!-- Save: joined to the trigger at top-bar level, never inside the panel. -->\n <button\n v-if=\"hasSave\"\n type=\"button\"\n :class=\"[\n 'mint-experiment-popover__save',\n { 'mint-experiment-popover__save--loading': saveLoading },\n { 'mint-experiment-popover__save--success': showSuccess },\n { 'mint-experiment-popover__save--disabled': saveDisabled && !showSuccess },\n ]\"\n :disabled=\"saveLoading || (saveDisabled && !showSuccess)\"\n :title=\"saveTitle\"\n :aria-label=\"dirty ? `${saveTitle} (unsaved changes)` : saveTitle\"\n @click.stop=\"handleSave\"\n >\n <LoaderCircle v-if=\"saveLoading\" class=\"mint-experiment-popover__save-spinner\" :size=\"14\" aria-hidden=\"true\" />\n <Check v-else-if=\"showSuccess\" :size=\"14\" aria-hidden=\"true\" />\n <CloudUpload v-else :size=\"14\" aria-hidden=\"true\" />\n <span>{{ saveLoading ? 'Saving…' : saveLabel }}</span>\n <span v-if=\"dirty && !saveLoading\" class=\"mint-experiment-popover__dirty\" aria-hidden=\"true\" />\n </button>\n\n <!-- Summary panel: header, meta, then menu rows. No buttons inside. -->\n <div\n v-if=\"isOpen\"\n ref=\"panel\"\n :class=\"['mint-experiment-popover__panel', { 'mint-experiment-popover__panel--end': panelAlignEnd }]\"\n >\n <!-- Bound, still resolving — placeholders stand in for the record. -->\n <div v-if=\"isResolving\" class=\"mint-experiment-popover__head\" aria-busy=\"true\">\n <span class=\"mint-experiment-popover__skeleton-line mint-experiment-popover__skeleton-line--code\" />\n <span class=\"mint-experiment-popover__skeleton-line mint-experiment-popover__skeleton-line--name\" />\n </div>\n\n <!-- Bound, resolution failed — Detach stays reachable below. -->\n <div v-else-if=\"error\" class=\"mint-experiment-popover__head mint-experiment-popover__head--error\" role=\"alert\">\n <b class=\"mint-experiment-popover__name\">\n <CircleAlert :size=\"14\" aria-hidden=\"true\" />\n Experiment unavailable\n </b>\n <span class=\"mint-experiment-popover__message\">{{ error }}</span>\n </div>\n\n <template v-else>\n <div class=\"mint-experiment-popover__head\">\n <span v-if=\"experimentCode\" class=\"mint-exp-code mint-exp-code--sm\">{{ experimentCode }}</span>\n <b v-if=\"experimentName\" class=\"mint-experiment-popover__name\">{{ experimentName }}</b>\n </div>\n <dl v-if=\"metaRows().length\" class=\"mint-experiment-popover__meta\">\n <template v-for=\"[label, value] in metaRows()\" :key=\"label\">\n <dt>{{ label }}</dt>\n <dd>{{ value }}</dd>\n </template>\n </dl>\n </template>\n\n <div class=\"mint-experiment-popover__separator\" role=\"separator\" />\n\n <button type=\"button\" class=\"mint-experiment-popover__option\" @click=\"handleSelect\">\n <ArrowLeftRight class=\"mint-experiment-popover__option-icon\" :size=\"14\" aria-hidden=\"true\" />\n Change experiment…\n </button>\n <a\n v-if=\"experimentId != null\"\n class=\"mint-experiment-popover__option\"\n :href=\"`/experiments/${experimentId}`\"\n target=\"_blank\"\n rel=\"noopener\"\n @click=\"close()\"\n >\n <ExternalLink class=\"mint-experiment-popover__option-icon\" :size=\"14\" aria-hidden=\"true\" />\n Open in MINT\n </a>\n <button\n v-if=\"showDetach\"\n type=\"button\"\n class=\"mint-experiment-popover__option mint-experiment-popover__option--danger\"\n @click=\"handleDetach\"\n >\n <Unlink class=\"mint-experiment-popover__option-icon\" :size=\"14\" aria-hidden=\"true\" />\n Detach\n </button>\n </div>\n\n <!-- Save confirmation dialog -->\n <ConfirmDialog\n v-model:open=\"showConfirm\"\n :title=\"confirmTitle ?? 'Save to Experiment'\"\n :message=\"confirmMessage ?? `Save current data to ${experimentName ?? experimentCode}?`\"\n tone=\"info\"\n :confirm-label=\"saveLabel\"\n :loading=\"saveLoading\"\n @confirm=\"handleConfirmSave\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\n/** Top-bar control for the attached experiment: a trigger joined to an optional Save button, with a summary panel (change, open, detach). */\nimport { ref, computed, watch, nextTick, onUnmounted, useTemplateRef } from 'vue'\nimport { ArrowLeftRight, Check, ChevronDown, CircleAlert, CloudUpload, ExternalLink, Link, LoaderCircle, Unlink } from 'lucide-vue-next'\nimport { useDropdownState } from '../composables/useDropdownState'\nimport { format as formatStatus } from '../utils/experimentStatus'\nimport { formatRelativeTime } from '../utils/time'\nimport ConfirmDialog from './ConfirmDialog.vue'\n\ninterface Props {\n experimentName?: string\n experimentCode?: string\n experimentStatus?: string\n /** Platform id of the bound experiment; enables \"Open in MINT\". */\n experimentId?: number | null\n experimentProject?: string\n experimentOwner?: string\n /** ISO timestamp of the last update, shown as relative time. */\n experimentUpdatedAt?: string\n /** An experiment is bound but the platform has not returned its record yet. */\n isResolving?: boolean\n /** Message explaining why the bound experiment could not be resolved. */\n error?: string\n showSave?: boolean\n showDetach?: boolean\n saveDisabled?: boolean\n saveLoading?: boolean\n saveSuccessMessage?: string\n saveDisabledMessage?: string\n saveLabel?: string\n /** Unsaved changes: marks the Save button with a dot. */\n dirty?: boolean\n confirmSave?: boolean\n confirmTitle?: string\n confirmMessage?: string\n /** Empty-state trigger label. */\n placeholder?: string\n /** The trigger name truncates at this width (px); its title shows code and name in full. */\n maxNameWidth?: number\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n experimentId: null,\n isResolving: false,\n showSave: false,\n showDetach: false,\n saveDisabled: false,\n saveLoading: false,\n saveLabel: 'Save',\n dirty: false,\n confirmSave: true,\n placeholder: 'Attach experiment',\n maxNameWidth: 200,\n})\n\n// An experiment is bound but has no name to show — either still resolving or\n// resolution failed. The id is never substituted: a name may only come from the\n// platform, so these states say what is happening instead of inventing a label.\nconst isUnresolved = computed(() => props.isResolving || !!props.error)\nconst hasExperiment = computed(() => !!props.experimentName || !!props.experimentCode)\nconst isEmpty = computed(() => !isUnresolved.value && !hasExperiment.value)\nconst hasSave = computed(() => props.showSave && !isUnresolved.value && hasExperiment.value)\n\nconst triggerLabel = computed(() => {\n if (props.isResolving) return 'Loading experiment'\n if (props.error) return 'Experiment unavailable'\n return [props.experimentCode, props.experimentName].filter(Boolean).join(' · ') || props.placeholder\n})\n\nconst emit = defineEmits<{\n select: []\n save: []\n detach: []\n}>()\n\nconst { isOpen, close, toggle } = useDropdownState({\n rootRef: useTemplateRef<HTMLElement>('popover'),\n triggerRef: useTemplateRef<HTMLElement>('trigger'),\n closeOnEscape: false,\n})\nconst showSuccess = ref(false)\nconst showConfirm = ref(false)\n\n// The panel hangs from the group's left edge; when that would cross the\n// viewport's right edge (a control at the end of the top bar) it hangs from the right.\nconst panel = useTemplateRef<HTMLElement>('panel')\nconst panelAlignEnd = ref(false)\nwatch(isOpen, async (open) => {\n if (!open) return\n panelAlignEnd.value = false\n await nextTick()\n const right = panel.value?.getBoundingClientRect().right ?? 0\n panelAlignEnd.value = right > document.documentElement.clientWidth\n})\n\nconst saveTitle = computed(() => {\n if (props.saveDisabled && props.saveDisabledMessage) return props.saveDisabledMessage\n if (showSuccess.value && props.saveSuccessMessage) return props.saveSuccessMessage\n return `${props.saveLabel} to experiment`\n})\n\n// A function, not a computed: \"Updated\" is relative to now, so it is\n// re-evaluated each time the panel renders.\nfunction metaRows(): [string, string][] {\n return ([\n ['Project', props.experimentProject],\n ['Status', props.experimentStatus && formatStatus(props.experimentStatus)],\n ['Owner', props.experimentOwner],\n ['Updated', props.experimentUpdatedAt && formatRelativeTime(props.experimentUpdatedAt)],\n ] as [string, string | undefined][]).filter((row): row is [string, string] => !!row[1])\n}\n\nfunction handleTriggerClick() {\n if (isEmpty.value) {\n emit('select')\n return\n }\n toggle()\n}\n\nfunction handleSelect() {\n emit('select')\n close()\n}\n\nfunction handleSave() {\n if (props.saveDisabled || props.saveLoading) return\n close()\n if (props.confirmSave) {\n showConfirm.value = true\n } else {\n emit('save')\n }\n}\n\nfunction handleConfirmSave() {\n showConfirm.value = false\n emit('save')\n}\n\nfunction handleDetach() {\n emit('detach')\n close()\n}\n\nlet successTimer: ReturnType<typeof setTimeout> | null = null\n\n// Show success state when saveSuccessMessage changes from empty to a value\nwatch(() => props.saveSuccessMessage, (msg) => {\n if (successTimer) clearTimeout(successTimer)\n if (msg) {\n showSuccess.value = true\n successTimer = setTimeout(() => {\n showSuccess.value = false\n successTimer = null\n }, 3000)\n }\n})\n\nonUnmounted(() => {\n if (successTimer) clearTimeout(successTimer)\n})\n</script>\n\n<template>\n <div ref=\"popover\" :class=\"['mint-experiment-popover', { 'mint-experiment-popover--save': hasSave }]\">\n <!-- Trigger: code + name when attached, opens the panel; the empty state selects directly. -->\n <button\n ref=\"trigger\"\n type=\"button\"\n :class=\"[\n 'mint-experiment-popover__trigger',\n { 'mint-experiment-popover__trigger--active': isOpen },\n { 'mint-experiment-popover__trigger--empty': isEmpty },\n { 'mint-experiment-popover__trigger--loading': isResolving },\n { 'mint-experiment-popover__trigger--error': !isResolving && !!error },\n ]\"\n :title=\"triggerLabel\"\n :aria-label=\"isUnresolved ? triggerLabel : undefined\"\n :aria-busy=\"isResolving || undefined\"\n :aria-expanded=\"isEmpty ? undefined : isOpen\"\n @click.stop=\"handleTriggerClick\"\n >\n <!-- Resolving and error come first: with an experiment bound but no name\n yet, the empty placeholder would be a lie. -->\n <span v-if=\"isResolving\" class=\"mint-experiment-popover__trigger-skeleton\" aria-hidden=\"true\" />\n <template v-else-if=\"error\">\n <CircleAlert class=\"mint-experiment-popover__trigger-icon\" :size=\"14\" aria-hidden=\"true\" />\n <span class=\"mint-experiment-popover__trigger-text\">Experiment unavailable</span>\n </template>\n <template v-else-if=\"hasExperiment\">\n <span v-if=\"experimentCode\" class=\"mint-exp-code mint-exp-code--sm\">{{ experimentCode }}</span>\n <span\n v-if=\"experimentName\"\n class=\"mint-experiment-popover__trigger-text\"\n :style=\"{ maxWidth: `${maxNameWidth}px` }\"\n >{{ experimentName }}</span>\n </template>\n <template v-else>\n <Link class=\"mint-experiment-popover__trigger-icon\" :size=\"14\" aria-hidden=\"true\" />\n <span class=\"mint-experiment-popover__trigger-text\">{{ placeholder }}</span>\n </template>\n <ChevronDown v-if=\"!isEmpty\" class=\"mint-experiment-popover__trigger-chevron\" :size=\"13\" aria-hidden=\"true\" />\n </button>\n\n <!-- Save: joined to the trigger at top-bar level, never inside the panel. -->\n <button\n v-if=\"hasSave\"\n type=\"button\"\n :class=\"[\n 'mint-experiment-popover__save',\n { 'mint-experiment-popover__save--loading': saveLoading },\n { 'mint-experiment-popover__save--success': showSuccess },\n { 'mint-experiment-popover__save--disabled': saveDisabled && !showSuccess },\n ]\"\n :disabled=\"saveLoading || (saveDisabled && !showSuccess)\"\n :title=\"saveTitle\"\n :aria-label=\"dirty ? `${saveTitle} (unsaved changes)` : saveTitle\"\n @click.stop=\"handleSave\"\n >\n <LoaderCircle v-if=\"saveLoading\" class=\"mint-experiment-popover__save-spinner\" :size=\"14\" aria-hidden=\"true\" />\n <Check v-else-if=\"showSuccess\" :size=\"14\" aria-hidden=\"true\" />\n <CloudUpload v-else :size=\"14\" aria-hidden=\"true\" />\n <span>{{ saveLoading ? 'Saving…' : saveLabel }}</span>\n <span v-if=\"dirty && !saveLoading\" class=\"mint-experiment-popover__dirty\" aria-hidden=\"true\" />\n </button>\n\n <!-- Summary panel: header, meta, then menu rows. No buttons inside. -->\n <div\n v-if=\"isOpen\"\n ref=\"panel\"\n :class=\"['mint-experiment-popover__panel', { 'mint-experiment-popover__panel--end': panelAlignEnd }]\"\n >\n <!-- Bound, still resolving — placeholders stand in for the record. -->\n <div v-if=\"isResolving\" class=\"mint-experiment-popover__head\" aria-busy=\"true\">\n <span class=\"mint-experiment-popover__skeleton-line mint-experiment-popover__skeleton-line--code\" />\n <span class=\"mint-experiment-popover__skeleton-line mint-experiment-popover__skeleton-line--name\" />\n </div>\n\n <!-- Bound, resolution failed — Detach stays reachable below. -->\n <div v-else-if=\"error\" class=\"mint-experiment-popover__head mint-experiment-popover__head--error\" role=\"alert\">\n <b class=\"mint-experiment-popover__name\">\n <CircleAlert :size=\"14\" aria-hidden=\"true\" />\n Experiment unavailable\n </b>\n <span class=\"mint-experiment-popover__message\">{{ error }}</span>\n </div>\n\n <template v-else>\n <div class=\"mint-experiment-popover__head\">\n <span v-if=\"experimentCode\" class=\"mint-exp-code mint-exp-code--sm\">{{ experimentCode }}</span>\n <b v-if=\"experimentName\" class=\"mint-experiment-popover__name\">{{ experimentName }}</b>\n </div>\n <dl v-if=\"metaRows().length\" class=\"mint-experiment-popover__meta\">\n <template v-for=\"[label, value] in metaRows()\" :key=\"label\">\n <dt>{{ label }}</dt>\n <dd>{{ value }}</dd>\n </template>\n </dl>\n </template>\n\n <div class=\"mint-experiment-popover__separator\" role=\"separator\" />\n\n <button type=\"button\" class=\"mint-experiment-popover__option\" @click=\"handleSelect\">\n <ArrowLeftRight class=\"mint-experiment-popover__option-icon\" :size=\"14\" aria-hidden=\"true\" />\n Change experiment…\n </button>\n <a\n v-if=\"experimentId != null\"\n class=\"mint-experiment-popover__option\"\n :href=\"`/experiments/${experimentId}`\"\n target=\"_blank\"\n rel=\"noopener\"\n @click=\"close()\"\n >\n <ExternalLink class=\"mint-experiment-popover__option-icon\" :size=\"14\" aria-hidden=\"true\" />\n Open in MINT\n </a>\n <button\n v-if=\"showDetach\"\n type=\"button\"\n class=\"mint-experiment-popover__option mint-experiment-popover__option--danger\"\n @click=\"handleDetach\"\n >\n <Unlink class=\"mint-experiment-popover__option-icon\" :size=\"14\" aria-hidden=\"true\" />\n Detach\n </button>\n </div>\n\n <!-- Save confirmation dialog -->\n <ConfirmDialog\n v-model:open=\"showConfirm\"\n :title=\"confirmTitle ?? 'Save to Experiment'\"\n :message=\"confirmMessage ?? `Save current data to ${experimentName ?? experimentCode}?`\"\n tone=\"info\"\n :confirm-label=\"saveLabel\"\n :loading=\"saveLoading\"\n @confirm=\"handleConfirmSave\"\n />\n </div>\n</template>\n"],"mappings":"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"}
|