@morscherlab/mld-sdk 0.9.8 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/composables/useAppExperiment.test.d.ts +1 -0
- package/dist/components/AppTopBar.vue.js +61 -28
- package/dist/components/AppTopBar.vue.js.map +1 -1
- package/dist/components/AuditTrail.vue.d.ts +1 -1
- package/dist/components/ExperimentSelectorModal.vue.d.ts +1 -1
- package/dist/components/ScientificNumber.vue.d.ts +1 -1
- package/dist/composables/index.d.ts +1 -0
- package/dist/composables/index.js +3 -0
- package/dist/composables/index.js.map +1 -1
- package/dist/composables/useAppExperiment.d.ts +34 -0
- package/dist/composables/useAppExperiment.js +91 -0
- package/dist/composables/useAppExperiment.js.map +1 -0
- package/dist/composables/usePlatformContext.js +8 -1
- package/dist/composables/usePlatformContext.js.map +1 -1
- package/dist/composables/useTheme.js +23 -25
- package/dist/composables/useTheme.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/stores/auth.d.ts +1 -1
- package/dist/stores/settings.d.ts +1 -1
- package/dist/styles.css +6926 -6926
- package/package.json +1 -1
- package/src/__tests__/composables/useAppExperiment.test.ts +560 -0
- package/src/components/AppTopBar.vue +38 -2
- package/src/composables/index.ts +7 -0
- package/src/composables/useAppExperiment.ts +143 -0
- package/src/composables/usePlatformContext.ts +7 -1
- package/src/composables/useTheme.ts +33 -28
- package/src/index.ts +5 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { defineComponent, ref, computed, onMounted, onUnmounted, resolveComponent, openBlock, createElementBlock, Fragment, createElementVNode, normalizeClass, renderSlot, createCommentVNode, createBlock, withCtx, toDisplayString, withModifiers, createTextVNode, withDirectives, renderList, vShow, createSlots } from "vue";
|
|
2
|
-
import _sfc_main$
|
|
1
|
+
import { defineComponent, ref, computed, inject, onMounted, onUnmounted, resolveComponent, openBlock, createElementBlock, Fragment, createElementVNode, normalizeClass, renderSlot, createCommentVNode, createBlock, withCtx, toDisplayString, withModifiers, createTextVNode, withDirectives, renderList, vShow, unref, createSlots } from "vue";
|
|
2
|
+
import _sfc_main$2 from "./ThemeToggle.vue.js";
|
|
3
3
|
/* empty css */
|
|
4
|
-
import _sfc_main$
|
|
4
|
+
import _sfc_main$3 from "./SettingsModal.vue.js";
|
|
5
5
|
/* empty css */
|
|
6
|
+
import _sfc_main$1 from "./ExperimentPopover.vue.js";
|
|
7
|
+
/* empty css */
|
|
8
|
+
import _sfc_main$4 from "./ExperimentSelectorModal.vue.js";
|
|
9
|
+
/* empty css */
|
|
6
10
|
import { usePlatformContext } from "../composables/usePlatformContext.js";
|
|
11
|
+
import { APP_EXPERIMENT_KEY } from "../composables/useAppExperiment.js";
|
|
7
12
|
const _hoisted_1 = { class: "mld-topbar__container" };
|
|
8
13
|
const _hoisted_2 = { class: "mld-topbar__left" };
|
|
9
14
|
const _hoisted_3 = ["href"];
|
|
@@ -105,8 +110,12 @@ const _hoisted_39 = {
|
|
|
105
110
|
key: 0,
|
|
106
111
|
class: "mld-topbar__standalone-badge"
|
|
107
112
|
};
|
|
108
|
-
const _hoisted_40 = {
|
|
109
|
-
|
|
113
|
+
const _hoisted_40 = {
|
|
114
|
+
key: 2,
|
|
115
|
+
class: "mld-topbar__standalone-badge"
|
|
116
|
+
};
|
|
117
|
+
const _hoisted_41 = { class: "mld-topbar__profile-avatar" };
|
|
118
|
+
const _hoisted_42 = {
|
|
110
119
|
key: 0,
|
|
111
120
|
class: "mld-topbar__profile-name"
|
|
112
121
|
};
|
|
@@ -140,6 +149,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
140
149
|
const settingsOpen = ref(false);
|
|
141
150
|
const { isIntegrated } = usePlatformContext();
|
|
142
151
|
const isStandalone = computed(() => !isIntegrated.value);
|
|
152
|
+
const appExperiment = inject(APP_EXPERIMENT_KEY, null);
|
|
143
153
|
const profileInitial = computed(() => {
|
|
144
154
|
if (props.userInitial) return props.userInitial;
|
|
145
155
|
if (props.userName) return props.userName.charAt(0).toUpperCase();
|
|
@@ -222,7 +232,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
222
232
|
}, [
|
|
223
233
|
renderSlot(_ctx.$slots, "icon", {}, () => [
|
|
224
234
|
renderSlot(_ctx.$slots, "logo", {}, () => [
|
|
225
|
-
__props.showLogo ? (openBlock(), createElementBlock("div", _hoisted_4, [..._cache[
|
|
235
|
+
__props.showLogo ? (openBlock(), createElementBlock("div", _hoisted_4, [..._cache[14] || (_cache[14] = [
|
|
226
236
|
createElementVNode("div", { class: "mld-topbar__logo-icon" }, [
|
|
227
237
|
createElementVNode("span", { class: "mld-topbar__logo-text" }, "M")
|
|
228
238
|
], -1)
|
|
@@ -236,7 +246,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
236
246
|
}, [
|
|
237
247
|
renderSlot(_ctx.$slots, "icon", {}, () => [
|
|
238
248
|
renderSlot(_ctx.$slots, "logo", {}, () => [
|
|
239
|
-
__props.showLogo ? (openBlock(), createElementBlock("div", _hoisted_6, [..._cache[
|
|
249
|
+
__props.showLogo ? (openBlock(), createElementBlock("div", _hoisted_6, [..._cache[15] || (_cache[15] = [
|
|
240
250
|
createElementVNode("div", { class: "mld-topbar__logo-icon" }, [
|
|
241
251
|
createElementVNode("span", { class: "mld-topbar__logo-text" }, "M")
|
|
242
252
|
], -1)
|
|
@@ -251,7 +261,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
251
261
|
default: withCtx(() => [
|
|
252
262
|
renderSlot(_ctx.$slots, "icon", {}, () => [
|
|
253
263
|
renderSlot(_ctx.$slots, "logo", {}, () => [
|
|
254
|
-
__props.showLogo ? (openBlock(), createElementBlock("div", _hoisted_7, [..._cache[
|
|
264
|
+
__props.showLogo ? (openBlock(), createElementBlock("div", _hoisted_7, [..._cache[16] || (_cache[16] = [
|
|
255
265
|
createElementVNode("div", { class: "mld-topbar__logo-icon" }, [
|
|
256
266
|
createElementVNode("span", { class: "mld-topbar__logo-text" }, "M")
|
|
257
267
|
], -1)
|
|
@@ -262,7 +272,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
262
272
|
_: 3
|
|
263
273
|
}, 8, ["to"])) : renderSlot(_ctx.$slots, "icon", { key: 3 }, () => [
|
|
264
274
|
renderSlot(_ctx.$slots, "logo", {}, () => [
|
|
265
|
-
__props.showLogo ? (openBlock(), createElementBlock("div", _hoisted_8, [..._cache[
|
|
275
|
+
__props.showLogo ? (openBlock(), createElementBlock("div", _hoisted_8, [..._cache[17] || (_cache[17] = [
|
|
266
276
|
createElementVNode("div", { class: "mld-topbar__logo-icon" }, [
|
|
267
277
|
createElementVNode("span", { class: "mld-topbar__logo-text" }, "M")
|
|
268
278
|
], -1)
|
|
@@ -295,11 +305,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
295
305
|
"stroke-width": "2",
|
|
296
306
|
"stroke-linecap": "round",
|
|
297
307
|
"stroke-linejoin": "round"
|
|
298
|
-
}, [..._cache[
|
|
308
|
+
}, [..._cache[18] || (_cache[18] = [
|
|
299
309
|
createElementVNode("path", { d: "m6 9 6 6 6-6" }, null, -1)
|
|
300
310
|
])], 2))
|
|
301
311
|
])) : (openBlock(), createElementBlock("span", _hoisted_12, toDisplayString(__props.pluginName), 1)),
|
|
302
|
-
__props.title ? (openBlock(), createElementBlock("svg", _hoisted_13, [..._cache[
|
|
312
|
+
__props.title ? (openBlock(), createElementBlock("svg", _hoisted_13, [..._cache[19] || (_cache[19] = [
|
|
303
313
|
createElementVNode("path", { d: "m9 18 6-6-6-6" }, null, -1)
|
|
304
314
|
])])) : createCommentVNode("", true),
|
|
305
315
|
__props.title ? (openBlock(), createElementBlock("span", _hoisted_14, toDisplayString(__props.title), 1)) : createCommentVNode("", true),
|
|
@@ -377,7 +387,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
377
387
|
"stroke-width": "2",
|
|
378
388
|
"stroke-linecap": "round",
|
|
379
389
|
"stroke-linejoin": "round"
|
|
380
|
-
}, [..._cache[
|
|
390
|
+
}, [..._cache[20] || (_cache[20] = [
|
|
381
391
|
createElementVNode("path", { d: "m6 9 6 6 6-6" }, null, -1)
|
|
382
392
|
])], 2))
|
|
383
393
|
], 10, _hoisted_26)) : tab.href ? (openBlock(), createElementBlock("a", {
|
|
@@ -465,19 +475,34 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
465
475
|
}), 128))
|
|
466
476
|
])) : createCommentVNode("", true),
|
|
467
477
|
createElementVNode("div", _hoisted_38, [
|
|
468
|
-
__props.showStandaloneLabel && isStandalone.value ? (openBlock(), createElementBlock("span", _hoisted_39, toDisplayString(__props.standaloneLabel), 1)) : createCommentVNode("", true),
|
|
469
|
-
|
|
470
|
-
__props.showThemeToggle ? (openBlock(), createBlock(_sfc_main$1, {
|
|
478
|
+
__props.showStandaloneLabel && isStandalone.value && !unref(appExperiment) ? (openBlock(), createElementBlock("span", _hoisted_39, toDisplayString(__props.standaloneLabel), 1)) : createCommentVNode("", true),
|
|
479
|
+
unref(appExperiment) && !isStandalone.value ? (openBlock(), createBlock(_sfc_main$1, {
|
|
471
480
|
key: 1,
|
|
481
|
+
"experiment-name": unref(appExperiment).experimentName.value,
|
|
482
|
+
"experiment-status": unref(appExperiment).experimentStatus.value,
|
|
483
|
+
"show-save": unref(appExperiment).showSave.value,
|
|
484
|
+
"show-detach": unref(appExperiment).showDetach.value,
|
|
485
|
+
"save-disabled": unref(appExperiment).saveDisabled.value,
|
|
486
|
+
"save-disabled-message": unref(appExperiment).saveDisabledMessage.value,
|
|
487
|
+
"save-loading": unref(appExperiment).saveLoading.value,
|
|
488
|
+
"save-success-message": unref(appExperiment).saveSuccessMessage.value,
|
|
489
|
+
onSelect: _cache[4] || (_cache[4] = ($event) => unref(appExperiment).openModal()),
|
|
490
|
+
onSave: _cache[5] || (_cache[5] = ($event) => unref(appExperiment).handleSave()),
|
|
491
|
+
onDetach: _cache[6] || (_cache[6] = ($event) => unref(appExperiment).handleDetach())
|
|
492
|
+
}, null, 8, ["experiment-name", "experiment-status", "show-save", "show-detach", "save-disabled", "save-disabled-message", "save-loading", "save-success-message"])) : createCommentVNode("", true),
|
|
493
|
+
unref(appExperiment) && isStandalone.value ? (openBlock(), createElementBlock("span", _hoisted_40, toDisplayString(__props.standaloneLabel), 1)) : createCommentVNode("", true),
|
|
494
|
+
renderSlot(_ctx.$slots, "actions"),
|
|
495
|
+
__props.showThemeToggle ? (openBlock(), createBlock(_sfc_main$2, {
|
|
496
|
+
key: 3,
|
|
472
497
|
size: "sm"
|
|
473
498
|
})) : createCommentVNode("", true),
|
|
474
499
|
__props.showSettings ? (openBlock(), createElementBlock("button", {
|
|
475
|
-
key:
|
|
500
|
+
key: 4,
|
|
476
501
|
type: "button",
|
|
477
502
|
class: "mld-topbar__settings-btn",
|
|
478
503
|
"aria-label": "Open settings",
|
|
479
|
-
onClick: _cache[
|
|
480
|
-
}, [..._cache[
|
|
504
|
+
onClick: _cache[7] || (_cache[7] = ($event) => settingsOpen.value = true)
|
|
505
|
+
}, [..._cache[21] || (_cache[21] = [
|
|
481
506
|
createElementVNode("svg", {
|
|
482
507
|
class: "mld-topbar__settings-icon",
|
|
483
508
|
viewBox: "0 0 24 24",
|
|
@@ -496,13 +521,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
496
521
|
], -1)
|
|
497
522
|
])])) : createCommentVNode("", true),
|
|
498
523
|
__props.showAdmin ? (openBlock(), createBlock(_component_router_link, {
|
|
499
|
-
key:
|
|
524
|
+
key: 5,
|
|
500
525
|
to: __props.adminPath,
|
|
501
526
|
class: "mld-topbar__admin-btn",
|
|
502
527
|
"aria-label": "Admin Dashboard",
|
|
503
|
-
onClick: _cache[
|
|
528
|
+
onClick: _cache[8] || (_cache[8] = ($event) => emit("admin-click"))
|
|
504
529
|
}, {
|
|
505
|
-
default: withCtx(() => [..._cache[
|
|
530
|
+
default: withCtx(() => [..._cache[22] || (_cache[22] = [
|
|
506
531
|
createElementVNode("svg", {
|
|
507
532
|
class: "mld-topbar__admin-icon",
|
|
508
533
|
viewBox: "0 0 24 24",
|
|
@@ -519,22 +544,22 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
519
544
|
_: 1
|
|
520
545
|
}, 8, ["to"])) : createCommentVNode("", true),
|
|
521
546
|
__props.showProfile ? (openBlock(), createElementBlock("button", {
|
|
522
|
-
key:
|
|
547
|
+
key: 6,
|
|
523
548
|
type: "button",
|
|
524
549
|
class: "mld-topbar__profile-btn",
|
|
525
550
|
"aria-label": "Edit profile",
|
|
526
|
-
onClick: _cache[
|
|
551
|
+
onClick: _cache[9] || (_cache[9] = ($event) => emit("profile-click"))
|
|
527
552
|
}, [
|
|
528
|
-
createElementVNode("div",
|
|
529
|
-
__props.userName ? (openBlock(), createElementBlock("span",
|
|
553
|
+
createElementVNode("div", _hoisted_41, toDisplayString(profileInitial.value), 1),
|
|
554
|
+
__props.userName ? (openBlock(), createElementBlock("span", _hoisted_42, toDisplayString(__props.userName), 1)) : createCommentVNode("", true)
|
|
530
555
|
])) : createCommentVNode("", true)
|
|
531
556
|
])
|
|
532
557
|
])
|
|
533
558
|
], 2),
|
|
534
|
-
__props.showSettings ? (openBlock(), createBlock(_sfc_main$
|
|
559
|
+
__props.showSettings ? (openBlock(), createBlock(_sfc_main$3, {
|
|
535
560
|
key: 0,
|
|
536
561
|
modelValue: settingsOpen.value,
|
|
537
|
-
"onUpdate:modelValue": _cache[
|
|
562
|
+
"onUpdate:modelValue": _cache[10] || (_cache[10] = ($event) => settingsOpen.value = $event),
|
|
538
563
|
title: (_e = __props.settingsConfig) == null ? void 0 : _e.title,
|
|
539
564
|
tabs: (_f = __props.settingsConfig) == null ? void 0 : _f.tabs,
|
|
540
565
|
"show-appearance": ((_g = __props.settingsConfig) == null ? void 0 : _g.showAppearance) ?? true,
|
|
@@ -553,7 +578,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
553
578
|
])
|
|
554
579
|
};
|
|
555
580
|
})
|
|
556
|
-
]), 1032, ["modelValue", "title", "tabs", "show-appearance", "size"])) : createCommentVNode("", true)
|
|
581
|
+
]), 1032, ["modelValue", "title", "tabs", "show-appearance", "size"])) : createCommentVNode("", true),
|
|
582
|
+
unref(appExperiment) && !isStandalone.value ? (openBlock(), createBlock(_sfc_main$4, {
|
|
583
|
+
key: 1,
|
|
584
|
+
"model-value": unref(appExperiment).showModal.value,
|
|
585
|
+
"current-experiment-id": unref(appExperiment).experimentId.value,
|
|
586
|
+
"onUpdate:modelValue": _cache[11] || (_cache[11] = ($event) => $event ? unref(appExperiment).openModal() : unref(appExperiment).closeModal()),
|
|
587
|
+
onSelect: _cache[12] || (_cache[12] = ($event) => unref(appExperiment).handleSelect($event)),
|
|
588
|
+
onDeselect: _cache[13] || (_cache[13] = ($event) => unref(appExperiment).handleDetach())
|
|
589
|
+
}, null, 8, ["model-value", "current-experiment-id"])) : createCommentVNode("", true)
|
|
557
590
|
], 64);
|
|
558
591
|
};
|
|
559
592
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppTopBar.vue.js","sources":["../../src/components/AppTopBar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onUnmounted } from 'vue'\nimport type { TopBarPage, TopBarTab, TopBarTabOption, TopBarSettingsConfig, TopBarVariant } from '../types/components'\nimport ThemeToggle from './ThemeToggle.vue'\nimport SettingsModal from './SettingsModal.vue'\nimport { usePlatformContext } from '../composables/usePlatformContext'\n\ninterface Props {\n title?: string\n subtitle?: string\n showLogo?: boolean\n variant?: TopBarVariant\n pluginName?: string\n pages?: TopBarPage[]\n currentPageId?: string\n tabs?: TopBarTab[]\n currentTabId?: string\n homePath?: string\n showThemeToggle?: boolean\n showSettings?: boolean\n settingsConfig?: TopBarSettingsConfig\n showStandaloneLabel?: boolean\n standaloneLabel?: string\n showAdmin?: boolean\n adminPath?: string\n showProfile?: boolean\n userName?: string\n userInitial?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n showLogo: true,\n variant: 'card',\n homePath: '/',\n showThemeToggle: false,\n showSettings: false,\n showStandaloneLabel: true,\n standaloneLabel: 'Standalone',\n showAdmin: false,\n adminPath: '/admin',\n showProfile: false,\n})\n\nconst settingsOpen = ref(false)\nconst { isIntegrated } = usePlatformContext()\nconst isStandalone = computed(() => !isIntegrated.value)\n\nconst profileInitial = computed(() => {\n if (props.userInitial) return props.userInitial\n if (props.userName) return props.userName.charAt(0).toUpperCase()\n return 'U'\n})\n\nconst emit = defineEmits<{\n 'page-select': [page: TopBarPage]\n 'tab-select': [tab: TopBarTab]\n 'tab-option-select': [option: TopBarTabOption, tab: TopBarTab]\n 'profile-click': []\n 'admin-click': []\n}>()\n\nconst showPagesDropdown = ref(false)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst openTabDropdown = ref<string | null>(null)\nconst tabDropdownRefs = ref<Map<string, HTMLElement>>(new Map())\n\nfunction togglePagesDropdown() {\n showPagesDropdown.value = !showPagesDropdown.value\n openTabDropdown.value = null\n}\n\nfunction handlePageClick(page: TopBarPage) {\n if (page.disabled) return\n emit('page-select', page)\n showPagesDropdown.value = false\n}\n\nfunction toggleTabDropdown(tabId: string) {\n showPagesDropdown.value = false\n openTabDropdown.value = openTabDropdown.value === tabId ? null : tabId\n}\n\nfunction handleTabClick(tab: TopBarTab) {\n if (tab.disabled) return\n if (tab.children?.length) {\n toggleTabDropdown(tab.id)\n } else {\n emit('tab-select', tab)\n openTabDropdown.value = null\n }\n}\n\nfunction handleTabOptionClick(option: TopBarTabOption, tab: TopBarTab) {\n if (option.disabled) return\n emit('tab-option-select', option, tab)\n openTabDropdown.value = null\n}\n\nfunction setTabDropdownRef(el: HTMLElement | null, tabId: string) {\n if (el) {\n tabDropdownRefs.value.set(tabId, el)\n } else {\n tabDropdownRefs.value.delete(tabId)\n }\n}\n\nfunction handleClickOutside(event: MouseEvent) {\n const target = event.target as Node\n\n if (showPagesDropdown.value && dropdownRef.value && !dropdownRef.value.contains(target)) {\n showPagesDropdown.value = false\n }\n\n if (openTabDropdown.value !== null) {\n const clickedInside = Array.from(tabDropdownRefs.value.values()).some((el) => el.contains(target))\n if (!clickedInside) {\n openTabDropdown.value = null\n }\n }\n}\n\nonMounted(() => {\n document.addEventListener('click', handleClickOutside)\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', handleClickOutside)\n})\n</script>\n\n<template>\n <header\n :class=\"[\n 'mld-topbar',\n `mld-topbar--${props.variant}`,\n ]\"\n >\n <div class=\"mld-topbar__container\">\n <!-- Left section: Icon/Logo + Title/Subtitle or Breadcrumb -->\n <div class=\"mld-topbar__left\">\n <!-- Icon/Logo with external home link (absolute URL) -->\n <a v-if=\"homePath && homePath.startsWith('http')\" :href=\"homePath\" class=\"mld-topbar-home-link\">\n <slot name=\"icon\">\n <slot name=\"logo\">\n <div v-if=\"showLogo\" class=\"mld-topbar__logo\">\n <div class=\"mld-topbar__logo-icon\">\n <span class=\"mld-topbar__logo-text\">M</span>\n </div>\n </div>\n </slot>\n </slot>\n </a>\n <!-- Icon/Logo with platform home link (absolute path goes to parent app) -->\n <a v-else-if=\"homePath && homePath.startsWith('/')\" :href=\"homePath\" class=\"mld-topbar-home-link\">\n <slot name=\"icon\">\n <slot name=\"logo\">\n <div v-if=\"showLogo\" class=\"mld-topbar__logo\">\n <div class=\"mld-topbar__logo-icon\">\n <span class=\"mld-topbar__logo-text\">M</span>\n </div>\n </div>\n </slot>\n </slot>\n </a>\n <!-- Icon/Logo with router link (relative path within app) -->\n <router-link v-else-if=\"homePath\" :to=\"homePath\" class=\"mld-topbar-home-link\">\n <slot name=\"icon\">\n <slot name=\"logo\">\n <div v-if=\"showLogo\" class=\"mld-topbar__logo\">\n <div class=\"mld-topbar__logo-icon\">\n <span class=\"mld-topbar__logo-text\">M</span>\n </div>\n </div>\n </slot>\n </slot>\n </router-link>\n <!-- Icon/Logo without link (homePath is empty) -->\n <template v-else>\n <slot name=\"icon\">\n <slot name=\"logo\">\n <div v-if=\"showLogo\" class=\"mld-topbar__logo\">\n <div class=\"mld-topbar__logo-icon\">\n <span class=\"mld-topbar__logo-text\">M</span>\n </div>\n </div>\n </slot>\n </slot>\n </template>\n\n <!-- Title with subtitle (no breadcrumb) -->\n <div v-if=\"title && subtitle && !pluginName && !pages?.length\" class=\"mld-topbar-title-group\">\n <span class=\"mld-topbar-title\">{{ title }}</span>\n <span class=\"mld-topbar-subtitle\">{{ subtitle }}</span>\n </div>\n\n <!-- Breadcrumb: Plugin Name > Current Page -->\n <div v-else-if=\"pluginName || pages?.length\" ref=\"dropdownRef\" class=\"mld-topbar-breadcrumb\">\n <!-- Plugin name with dropdown trigger -->\n <button\n v-if=\"pages?.length\"\n type=\"button\"\n class=\"mld-topbar-plugin-name\"\n @click.stop=\"togglePagesDropdown\"\n >\n {{ pluginName }}\n <svg\n class=\"mld-topbar-chevron\"\n :class=\"{ 'mld-topbar-chevron--open': showPagesDropdown }\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n <span v-else class=\"mld-topbar-plugin-name--static\">{{ pluginName }}</span>\n\n <!-- Separator -->\n <svg\n v-if=\"title\"\n class=\"mld-topbar-separator\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n\n <!-- Current page title -->\n <span v-if=\"title\" class=\"mld-topbar-current-page\">{{ title }}</span>\n\n <!-- Pages dropdown -->\n <div v-show=\"showPagesDropdown\" class=\"mld-topbar-dropdown\">\n <template v-for=\"page in pages\" :key=\"page.id\">\n <a\n v-if=\"page.href\"\n :href=\"page.href\"\n :class=\"['mld-topbar-dropdown-item', { 'mld-topbar-dropdown-item--active': page.id === currentPageId, 'mld-topbar-dropdown-item--disabled': page.disabled }]\"\n @click=\"showPagesDropdown = false\"\n >\n <span class=\"mld-topbar-dropdown-item__label\">{{ page.label }}</span>\n <span v-if=\"page.description\" class=\"mld-topbar-dropdown-item__description\">{{ page.description }}</span>\n </a>\n <router-link\n v-else-if=\"page.to\"\n :to=\"page.to\"\n :class=\"['mld-topbar-dropdown-item', { 'mld-topbar-dropdown-item--active': page.id === currentPageId, 'mld-topbar-dropdown-item--disabled': page.disabled }]\"\n @click=\"showPagesDropdown = false\"\n >\n <span class=\"mld-topbar-dropdown-item__label\">{{ page.label }}</span>\n <span v-if=\"page.description\" class=\"mld-topbar-dropdown-item__description\">{{ page.description }}</span>\n </router-link>\n <button\n v-else\n type=\"button\"\n :class=\"['mld-topbar-dropdown-item', { 'mld-topbar-dropdown-item--active': page.id === currentPageId, 'mld-topbar-dropdown-item--disabled': page.disabled }]\"\n @click=\"handlePageClick(page)\"\n >\n <span class=\"mld-topbar-dropdown-item__label\">{{ page.label }}</span>\n <span v-if=\"page.description\" class=\"mld-topbar-dropdown-item__description\">{{ page.description }}</span>\n </button>\n </template>\n </div>\n </div>\n\n <!-- Title only (backward compat when no pluginName and no subtitle) -->\n <span v-else-if=\"title\" class=\"mld-topbar__title-only\">{{ title }}</span>\n\n <!-- Navigation slot -->\n <slot name=\"nav\" />\n </div>\n\n <!-- Center section: Tabs -->\n <div v-if=\"tabs?.length\" class=\"mld-topbar__tabs\">\n <template v-for=\"tab in tabs\" :key=\"tab.id\">\n <div\n :ref=\"(el) => tab.children?.length ? setTabDropdownRef(el as HTMLElement, tab.id) : null\"\n class=\"mld-topbar-tab-wrapper\"\n >\n <!-- Tab with children (dropdown) -->\n <button\n v-if=\"tab.children?.length\"\n type=\"button\"\n :class=\"[\n 'mld-topbar-tab',\n { 'mld-topbar-tab--active': tab.id === currentTabId || tab.children.some(c => c.id === currentTabId) },\n { 'mld-topbar-tab--disabled': tab.disabled }\n ]\"\n @click.stop=\"handleTabClick(tab)\"\n >\n {{ tab.label }}\n <svg\n class=\"mld-topbar-tab-chevron\"\n :class=\"{ 'mld-topbar-tab-chevron--open': openTabDropdown === tab.id }\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n\n <!-- Simple tab (no children) -->\n <a\n v-else-if=\"tab.href\"\n :href=\"tab.href\"\n :class=\"[\n 'mld-topbar-tab',\n { 'mld-topbar-tab--active': tab.id === currentTabId },\n { 'mld-topbar-tab--disabled': tab.disabled }\n ]\"\n >\n {{ tab.label }}\n </a>\n <router-link\n v-else-if=\"tab.to\"\n :to=\"tab.to\"\n :class=\"[\n 'mld-topbar-tab',\n { 'mld-topbar-tab--active': tab.id === currentTabId },\n { 'mld-topbar-tab--disabled': tab.disabled }\n ]\"\n >\n {{ tab.label }}\n </router-link>\n <button\n v-else\n type=\"button\"\n :class=\"[\n 'mld-topbar-tab',\n { 'mld-topbar-tab--active': tab.id === currentTabId },\n { 'mld-topbar-tab--disabled': tab.disabled }\n ]\"\n @click=\"handleTabClick(tab)\"\n >\n {{ tab.label }}\n </button>\n\n <!-- Tab dropdown -->\n <div v-if=\"tab.children?.length\" v-show=\"openTabDropdown === tab.id\" class=\"mld-topbar-tab-dropdown\">\n <template v-for=\"option in tab.children\" :key=\"option.id\">\n <a\n v-if=\"option.href\"\n :href=\"option.href\"\n :class=\"[\n 'mld-topbar-dropdown-item',\n { 'mld-topbar-dropdown-item--active': option.id === currentTabId },\n { 'mld-topbar-dropdown-item--disabled': option.disabled }\n ]\"\n @click=\"openTabDropdown = null\"\n >\n <span class=\"mld-topbar-dropdown-item__label\">{{ option.label }}</span>\n <span v-if=\"option.description\" class=\"mld-topbar-dropdown-item__description\">{{ option.description }}</span>\n </a>\n <router-link\n v-else-if=\"option.to\"\n :to=\"option.to\"\n :class=\"[\n 'mld-topbar-dropdown-item',\n { 'mld-topbar-dropdown-item--active': option.id === currentTabId },\n { 'mld-topbar-dropdown-item--disabled': option.disabled }\n ]\"\n @click=\"openTabDropdown = null\"\n >\n <span class=\"mld-topbar-dropdown-item__label\">{{ option.label }}</span>\n <span v-if=\"option.description\" class=\"mld-topbar-dropdown-item__description\">{{ option.description }}</span>\n </router-link>\n <button\n v-else\n type=\"button\"\n :class=\"[\n 'mld-topbar-dropdown-item',\n { 'mld-topbar-dropdown-item--active': option.id === currentTabId },\n { 'mld-topbar-dropdown-item--disabled': option.disabled }\n ]\"\n @click=\"handleTabOptionClick(option, tab)\"\n >\n <span class=\"mld-topbar-dropdown-item__label\">{{ option.label }}</span>\n <span v-if=\"option.description\" class=\"mld-topbar-dropdown-item__description\">{{ option.description }}</span>\n </button>\n </template>\n </div>\n </div>\n </template>\n </div>\n\n <!-- Right section: Actions -->\n <div class=\"mld-topbar__right\">\n <span v-if=\"showStandaloneLabel && isStandalone\" class=\"mld-topbar__standalone-badge\">\n {{ standaloneLabel }}\n </span>\n <!-- Actions slot (right side) -->\n <slot name=\"actions\" />\n <!-- Theme toggle -->\n <ThemeToggle v-if=\"showThemeToggle\" size=\"sm\" />\n <!-- Settings gear -->\n <button\n v-if=\"showSettings\"\n type=\"button\"\n class=\"mld-topbar__settings-btn\"\n aria-label=\"Open settings\"\n @click=\"settingsOpen = true\"\n >\n <svg class=\"mld-topbar__settings-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915\" /><circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n </button>\n <!-- Admin link -->\n <router-link\n v-if=\"showAdmin\"\n :to=\"adminPath\"\n class=\"mld-topbar__admin-btn\"\n aria-label=\"Admin Dashboard\"\n @click=\"emit('admin-click')\"\n >\n <svg class=\"mld-topbar__admin-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\" /><path d=\"m9 12 2 2 4-4\" />\n </svg>\n </router-link>\n <!-- Profile button -->\n <button\n v-if=\"showProfile\"\n type=\"button\"\n class=\"mld-topbar__profile-btn\"\n aria-label=\"Edit profile\"\n @click=\"emit('profile-click')\"\n >\n <div class=\"mld-topbar__profile-avatar\">\n {{ profileInitial }}\n </div>\n <span v-if=\"userName\" class=\"mld-topbar__profile-name\">{{ userName }}</span>\n </button>\n </div>\n </div>\n </header>\n\n <SettingsModal\n v-if=\"showSettings\"\n v-model=\"settingsOpen\"\n :title=\"settingsConfig?.title\"\n :tabs=\"settingsConfig?.tabs\"\n :show-appearance=\"settingsConfig?.showAppearance ?? true\"\n :size=\"settingsConfig?.size\"\n >\n <template v-for=\"tab in (settingsConfig?.tabs ?? [])\" :key=\"tab.id\" #[`tab-${tab.id}`]>\n <slot :name=\"`settings-tab-${tab.id}`\" />\n </template>\n <template #appearance>\n <slot name=\"settings-appearance\" />\n </template>\n </SettingsModal>\n</template>\n\n<style>\n@import '../styles/components/app-top-bar.css';\n</style>\n"],"names":["_createElementVNode","_normalizeClass","_createElementBlock","_renderSlot","_openBlock","_createBlock","_toDisplayString","_createTextVNode","_withDirectives","_Fragment","_renderList","_a","_withModifiers","_b","ThemeToggle","SettingsModal"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AppTopBar.vue.js","sources":["../../src/components/AppTopBar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, inject, onMounted, onUnmounted } from 'vue'\nimport type { TopBarPage, TopBarTab, TopBarTabOption, TopBarSettingsConfig, TopBarVariant } from '../types/components'\nimport ThemeToggle from './ThemeToggle.vue'\nimport SettingsModal from './SettingsModal.vue'\nimport ExperimentPopover from './ExperimentPopover.vue'\nimport ExperimentSelectorModal from './ExperimentSelectorModal.vue'\nimport { usePlatformContext } from '../composables/usePlatformContext'\nimport { APP_EXPERIMENT_KEY } from '../composables/useAppExperiment'\n\ninterface Props {\n title?: string\n subtitle?: string\n showLogo?: boolean\n variant?: TopBarVariant\n pluginName?: string\n pages?: TopBarPage[]\n currentPageId?: string\n tabs?: TopBarTab[]\n currentTabId?: string\n homePath?: string\n showThemeToggle?: boolean\n showSettings?: boolean\n settingsConfig?: TopBarSettingsConfig\n showStandaloneLabel?: boolean\n standaloneLabel?: string\n showAdmin?: boolean\n adminPath?: string\n showProfile?: boolean\n userName?: string\n userInitial?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n showLogo: true,\n variant: 'card',\n homePath: '/',\n showThemeToggle: false,\n showSettings: false,\n showStandaloneLabel: true,\n standaloneLabel: 'Standalone',\n showAdmin: false,\n adminPath: '/admin',\n showProfile: false,\n})\n\nconst settingsOpen = ref(false)\nconst { isIntegrated } = usePlatformContext()\nconst isStandalone = computed(() => !isIntegrated.value)\nconst appExperiment = inject(APP_EXPERIMENT_KEY, null)\n\nconst profileInitial = computed(() => {\n if (props.userInitial) return props.userInitial\n if (props.userName) return props.userName.charAt(0).toUpperCase()\n return 'U'\n})\n\nconst emit = defineEmits<{\n 'page-select': [page: TopBarPage]\n 'tab-select': [tab: TopBarTab]\n 'tab-option-select': [option: TopBarTabOption, tab: TopBarTab]\n 'profile-click': []\n 'admin-click': []\n}>()\n\nconst showPagesDropdown = ref(false)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst openTabDropdown = ref<string | null>(null)\nconst tabDropdownRefs = ref<Map<string, HTMLElement>>(new Map())\n\nfunction togglePagesDropdown() {\n showPagesDropdown.value = !showPagesDropdown.value\n openTabDropdown.value = null\n}\n\nfunction handlePageClick(page: TopBarPage) {\n if (page.disabled) return\n emit('page-select', page)\n showPagesDropdown.value = false\n}\n\nfunction toggleTabDropdown(tabId: string) {\n showPagesDropdown.value = false\n openTabDropdown.value = openTabDropdown.value === tabId ? null : tabId\n}\n\nfunction handleTabClick(tab: TopBarTab) {\n if (tab.disabled) return\n if (tab.children?.length) {\n toggleTabDropdown(tab.id)\n } else {\n emit('tab-select', tab)\n openTabDropdown.value = null\n }\n}\n\nfunction handleTabOptionClick(option: TopBarTabOption, tab: TopBarTab) {\n if (option.disabled) return\n emit('tab-option-select', option, tab)\n openTabDropdown.value = null\n}\n\nfunction setTabDropdownRef(el: HTMLElement | null, tabId: string) {\n if (el) {\n tabDropdownRefs.value.set(tabId, el)\n } else {\n tabDropdownRefs.value.delete(tabId)\n }\n}\n\nfunction handleClickOutside(event: MouseEvent) {\n const target = event.target as Node\n\n if (showPagesDropdown.value && dropdownRef.value && !dropdownRef.value.contains(target)) {\n showPagesDropdown.value = false\n }\n\n if (openTabDropdown.value !== null) {\n const clickedInside = Array.from(tabDropdownRefs.value.values()).some((el) => el.contains(target))\n if (!clickedInside) {\n openTabDropdown.value = null\n }\n }\n}\n\nonMounted(() => {\n document.addEventListener('click', handleClickOutside)\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', handleClickOutside)\n})\n</script>\n\n<template>\n <header\n :class=\"[\n 'mld-topbar',\n `mld-topbar--${props.variant}`,\n ]\"\n >\n <div class=\"mld-topbar__container\">\n <!-- Left section: Icon/Logo + Title/Subtitle or Breadcrumb -->\n <div class=\"mld-topbar__left\">\n <!-- Icon/Logo with external home link (absolute URL) -->\n <a v-if=\"homePath && homePath.startsWith('http')\" :href=\"homePath\" class=\"mld-topbar-home-link\">\n <slot name=\"icon\">\n <slot name=\"logo\">\n <div v-if=\"showLogo\" class=\"mld-topbar__logo\">\n <div class=\"mld-topbar__logo-icon\">\n <span class=\"mld-topbar__logo-text\">M</span>\n </div>\n </div>\n </slot>\n </slot>\n </a>\n <!-- Icon/Logo with platform home link (absolute path goes to parent app) -->\n <a v-else-if=\"homePath && homePath.startsWith('/')\" :href=\"homePath\" class=\"mld-topbar-home-link\">\n <slot name=\"icon\">\n <slot name=\"logo\">\n <div v-if=\"showLogo\" class=\"mld-topbar__logo\">\n <div class=\"mld-topbar__logo-icon\">\n <span class=\"mld-topbar__logo-text\">M</span>\n </div>\n </div>\n </slot>\n </slot>\n </a>\n <!-- Icon/Logo with router link (relative path within app) -->\n <router-link v-else-if=\"homePath\" :to=\"homePath\" class=\"mld-topbar-home-link\">\n <slot name=\"icon\">\n <slot name=\"logo\">\n <div v-if=\"showLogo\" class=\"mld-topbar__logo\">\n <div class=\"mld-topbar__logo-icon\">\n <span class=\"mld-topbar__logo-text\">M</span>\n </div>\n </div>\n </slot>\n </slot>\n </router-link>\n <!-- Icon/Logo without link (homePath is empty) -->\n <template v-else>\n <slot name=\"icon\">\n <slot name=\"logo\">\n <div v-if=\"showLogo\" class=\"mld-topbar__logo\">\n <div class=\"mld-topbar__logo-icon\">\n <span class=\"mld-topbar__logo-text\">M</span>\n </div>\n </div>\n </slot>\n </slot>\n </template>\n\n <!-- Title with subtitle (no breadcrumb) -->\n <div v-if=\"title && subtitle && !pluginName && !pages?.length\" class=\"mld-topbar-title-group\">\n <span class=\"mld-topbar-title\">{{ title }}</span>\n <span class=\"mld-topbar-subtitle\">{{ subtitle }}</span>\n </div>\n\n <!-- Breadcrumb: Plugin Name > Current Page -->\n <div v-else-if=\"pluginName || pages?.length\" ref=\"dropdownRef\" class=\"mld-topbar-breadcrumb\">\n <!-- Plugin name with dropdown trigger -->\n <button\n v-if=\"pages?.length\"\n type=\"button\"\n class=\"mld-topbar-plugin-name\"\n @click.stop=\"togglePagesDropdown\"\n >\n {{ pluginName }}\n <svg\n class=\"mld-topbar-chevron\"\n :class=\"{ 'mld-topbar-chevron--open': showPagesDropdown }\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n <span v-else class=\"mld-topbar-plugin-name--static\">{{ pluginName }}</span>\n\n <!-- Separator -->\n <svg\n v-if=\"title\"\n class=\"mld-topbar-separator\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n\n <!-- Current page title -->\n <span v-if=\"title\" class=\"mld-topbar-current-page\">{{ title }}</span>\n\n <!-- Pages dropdown -->\n <div v-show=\"showPagesDropdown\" class=\"mld-topbar-dropdown\">\n <template v-for=\"page in pages\" :key=\"page.id\">\n <a\n v-if=\"page.href\"\n :href=\"page.href\"\n :class=\"['mld-topbar-dropdown-item', { 'mld-topbar-dropdown-item--active': page.id === currentPageId, 'mld-topbar-dropdown-item--disabled': page.disabled }]\"\n @click=\"showPagesDropdown = false\"\n >\n <span class=\"mld-topbar-dropdown-item__label\">{{ page.label }}</span>\n <span v-if=\"page.description\" class=\"mld-topbar-dropdown-item__description\">{{ page.description }}</span>\n </a>\n <router-link\n v-else-if=\"page.to\"\n :to=\"page.to\"\n :class=\"['mld-topbar-dropdown-item', { 'mld-topbar-dropdown-item--active': page.id === currentPageId, 'mld-topbar-dropdown-item--disabled': page.disabled }]\"\n @click=\"showPagesDropdown = false\"\n >\n <span class=\"mld-topbar-dropdown-item__label\">{{ page.label }}</span>\n <span v-if=\"page.description\" class=\"mld-topbar-dropdown-item__description\">{{ page.description }}</span>\n </router-link>\n <button\n v-else\n type=\"button\"\n :class=\"['mld-topbar-dropdown-item', { 'mld-topbar-dropdown-item--active': page.id === currentPageId, 'mld-topbar-dropdown-item--disabled': page.disabled }]\"\n @click=\"handlePageClick(page)\"\n >\n <span class=\"mld-topbar-dropdown-item__label\">{{ page.label }}</span>\n <span v-if=\"page.description\" class=\"mld-topbar-dropdown-item__description\">{{ page.description }}</span>\n </button>\n </template>\n </div>\n </div>\n\n <!-- Title only (backward compat when no pluginName and no subtitle) -->\n <span v-else-if=\"title\" class=\"mld-topbar__title-only\">{{ title }}</span>\n\n <!-- Navigation slot -->\n <slot name=\"nav\" />\n </div>\n\n <!-- Center section: Tabs -->\n <div v-if=\"tabs?.length\" class=\"mld-topbar__tabs\">\n <template v-for=\"tab in tabs\" :key=\"tab.id\">\n <div\n :ref=\"(el) => tab.children?.length ? setTabDropdownRef(el as HTMLElement, tab.id) : null\"\n class=\"mld-topbar-tab-wrapper\"\n >\n <!-- Tab with children (dropdown) -->\n <button\n v-if=\"tab.children?.length\"\n type=\"button\"\n :class=\"[\n 'mld-topbar-tab',\n { 'mld-topbar-tab--active': tab.id === currentTabId || tab.children.some(c => c.id === currentTabId) },\n { 'mld-topbar-tab--disabled': tab.disabled }\n ]\"\n @click.stop=\"handleTabClick(tab)\"\n >\n {{ tab.label }}\n <svg\n class=\"mld-topbar-tab-chevron\"\n :class=\"{ 'mld-topbar-tab-chevron--open': openTabDropdown === tab.id }\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n\n <!-- Simple tab (no children) -->\n <a\n v-else-if=\"tab.href\"\n :href=\"tab.href\"\n :class=\"[\n 'mld-topbar-tab',\n { 'mld-topbar-tab--active': tab.id === currentTabId },\n { 'mld-topbar-tab--disabled': tab.disabled }\n ]\"\n >\n {{ tab.label }}\n </a>\n <router-link\n v-else-if=\"tab.to\"\n :to=\"tab.to\"\n :class=\"[\n 'mld-topbar-tab',\n { 'mld-topbar-tab--active': tab.id === currentTabId },\n { 'mld-topbar-tab--disabled': tab.disabled }\n ]\"\n >\n {{ tab.label }}\n </router-link>\n <button\n v-else\n type=\"button\"\n :class=\"[\n 'mld-topbar-tab',\n { 'mld-topbar-tab--active': tab.id === currentTabId },\n { 'mld-topbar-tab--disabled': tab.disabled }\n ]\"\n @click=\"handleTabClick(tab)\"\n >\n {{ tab.label }}\n </button>\n\n <!-- Tab dropdown -->\n <div v-if=\"tab.children?.length\" v-show=\"openTabDropdown === tab.id\" class=\"mld-topbar-tab-dropdown\">\n <template v-for=\"option in tab.children\" :key=\"option.id\">\n <a\n v-if=\"option.href\"\n :href=\"option.href\"\n :class=\"[\n 'mld-topbar-dropdown-item',\n { 'mld-topbar-dropdown-item--active': option.id === currentTabId },\n { 'mld-topbar-dropdown-item--disabled': option.disabled }\n ]\"\n @click=\"openTabDropdown = null\"\n >\n <span class=\"mld-topbar-dropdown-item__label\">{{ option.label }}</span>\n <span v-if=\"option.description\" class=\"mld-topbar-dropdown-item__description\">{{ option.description }}</span>\n </a>\n <router-link\n v-else-if=\"option.to\"\n :to=\"option.to\"\n :class=\"[\n 'mld-topbar-dropdown-item',\n { 'mld-topbar-dropdown-item--active': option.id === currentTabId },\n { 'mld-topbar-dropdown-item--disabled': option.disabled }\n ]\"\n @click=\"openTabDropdown = null\"\n >\n <span class=\"mld-topbar-dropdown-item__label\">{{ option.label }}</span>\n <span v-if=\"option.description\" class=\"mld-topbar-dropdown-item__description\">{{ option.description }}</span>\n </router-link>\n <button\n v-else\n type=\"button\"\n :class=\"[\n 'mld-topbar-dropdown-item',\n { 'mld-topbar-dropdown-item--active': option.id === currentTabId },\n { 'mld-topbar-dropdown-item--disabled': option.disabled }\n ]\"\n @click=\"handleTabOptionClick(option, tab)\"\n >\n <span class=\"mld-topbar-dropdown-item__label\">{{ option.label }}</span>\n <span v-if=\"option.description\" class=\"mld-topbar-dropdown-item__description\">{{ option.description }}</span>\n </button>\n </template>\n </div>\n </div>\n </template>\n </div>\n\n <!-- Right section: Actions -->\n <div class=\"mld-topbar__right\">\n <!-- Standalone badge (only when useAppExperiment is NOT active) -->\n <span v-if=\"showStandaloneLabel && isStandalone && !appExperiment\" class=\"mld-topbar__standalone-badge\">\n {{ standaloneLabel }}\n </span>\n\n <!-- Experiment popover (integrated + useAppExperiment active) -->\n <ExperimentPopover\n v-if=\"appExperiment && !isStandalone\"\n :experiment-name=\"appExperiment.experimentName.value\"\n :experiment-status=\"appExperiment.experimentStatus.value\"\n :show-save=\"appExperiment.showSave.value\"\n :show-detach=\"appExperiment.showDetach.value\"\n :save-disabled=\"appExperiment.saveDisabled.value\"\n :save-disabled-message=\"appExperiment.saveDisabledMessage.value\"\n :save-loading=\"appExperiment.saveLoading.value\"\n :save-success-message=\"appExperiment.saveSuccessMessage.value\"\n @select=\"appExperiment.openModal()\"\n @save=\"appExperiment.handleSave()\"\n @detach=\"appExperiment.handleDetach()\"\n />\n\n <!-- Standalone pill (standalone + useAppExperiment active) -->\n <span v-if=\"appExperiment && isStandalone\" class=\"mld-topbar__standalone-badge\">\n {{ standaloneLabel }}\n </span>\n\n <!-- Actions slot (right side) -->\n <slot name=\"actions\" />\n <!-- Theme toggle -->\n <ThemeToggle v-if=\"showThemeToggle\" size=\"sm\" />\n <!-- Settings gear -->\n <button\n v-if=\"showSettings\"\n type=\"button\"\n class=\"mld-topbar__settings-btn\"\n aria-label=\"Open settings\"\n @click=\"settingsOpen = true\"\n >\n <svg class=\"mld-topbar__settings-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915\" /><circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n </button>\n <!-- Admin link -->\n <router-link\n v-if=\"showAdmin\"\n :to=\"adminPath\"\n class=\"mld-topbar__admin-btn\"\n aria-label=\"Admin Dashboard\"\n @click=\"emit('admin-click')\"\n >\n <svg class=\"mld-topbar__admin-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\" /><path d=\"m9 12 2 2 4-4\" />\n </svg>\n </router-link>\n <!-- Profile button -->\n <button\n v-if=\"showProfile\"\n type=\"button\"\n class=\"mld-topbar__profile-btn\"\n aria-label=\"Edit profile\"\n @click=\"emit('profile-click')\"\n >\n <div class=\"mld-topbar__profile-avatar\">\n {{ profileInitial }}\n </div>\n <span v-if=\"userName\" class=\"mld-topbar__profile-name\">{{ userName }}</span>\n </button>\n </div>\n </div>\n </header>\n\n <SettingsModal\n v-if=\"showSettings\"\n v-model=\"settingsOpen\"\n :title=\"settingsConfig?.title\"\n :tabs=\"settingsConfig?.tabs\"\n :show-appearance=\"settingsConfig?.showAppearance ?? true\"\n :size=\"settingsConfig?.size\"\n >\n <template v-for=\"tab in (settingsConfig?.tabs ?? [])\" :key=\"tab.id\" #[`tab-${tab.id}`]>\n <slot :name=\"`settings-tab-${tab.id}`\" />\n </template>\n <template #appearance>\n <slot name=\"settings-appearance\" />\n </template>\n </SettingsModal>\n\n <ExperimentSelectorModal\n v-if=\"appExperiment && !isStandalone\"\n :model-value=\"appExperiment.showModal.value\"\n :current-experiment-id=\"appExperiment.experimentId.value\"\n @update:model-value=\"$event ? appExperiment.openModal() : appExperiment.closeModal()\"\n @select=\"appExperiment.handleSelect($event)\"\n @deselect=\"appExperiment.handleDetach()\"\n />\n</template>\n\n<style>\n@import '../styles/components/app-top-bar.css';\n</style>\n"],"names":["_createElementVNode","_normalizeClass","_createElementBlock","_renderSlot","_openBlock","_createBlock","_toDisplayString","_createTextVNode","_withDirectives","_Fragment","_renderList","_a","_withModifiers","_b","_unref","ExperimentPopover","ThemeToggle","SettingsModal","ExperimentSelectorModal"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,UAAM,QAAQ;AAad,UAAM,eAAe,IAAI,KAAK;AAC9B,UAAM,EAAE,aAAA,IAAiB,mBAAA;AACzB,UAAM,eAAe,SAAS,MAAM,CAAC,aAAa,KAAK;AACvD,UAAM,gBAAgB,OAAO,oBAAoB,IAAI;AAErD,UAAM,iBAAiB,SAAS,MAAM;AACpC,UAAI,MAAM,YAAa,QAAO,MAAM;AACpC,UAAI,MAAM,SAAU,QAAO,MAAM,SAAS,OAAO,CAAC,EAAE,YAAA;AACpD,aAAO;AAAA,IACT,CAAC;AAED,UAAM,OAAO;AAQb,UAAM,oBAAoB,IAAI,KAAK;AACnC,UAAM,cAAc,IAAwB,IAAI;AAChD,UAAM,kBAAkB,IAAmB,IAAI;AAC/C,UAAM,kBAAkB,IAA8B,oBAAI,KAAK;AAE/D,aAAS,sBAAsB;AAC7B,wBAAkB,QAAQ,CAAC,kBAAkB;AAC7C,sBAAgB,QAAQ;AAAA,IAC1B;AAEA,aAAS,gBAAgB,MAAkB;AACzC,UAAI,KAAK,SAAU;AACnB,WAAK,eAAe,IAAI;AACxB,wBAAkB,QAAQ;AAAA,IAC5B;AAEA,aAAS,kBAAkB,OAAe;AACxC,wBAAkB,QAAQ;AAC1B,sBAAgB,QAAQ,gBAAgB,UAAU,QAAQ,OAAO;AAAA,IACnE;AAEA,aAAS,eAAe,KAAgB;;AACtC,UAAI,IAAI,SAAU;AAClB,WAAI,SAAI,aAAJ,mBAAc,QAAQ;AACxB,0BAAkB,IAAI,EAAE;AAAA,MAC1B,OAAO;AACL,aAAK,cAAc,GAAG;AACtB,wBAAgB,QAAQ;AAAA,MAC1B;AAAA,IACF;AAEA,aAAS,qBAAqB,QAAyB,KAAgB;AACrE,UAAI,OAAO,SAAU;AACrB,WAAK,qBAAqB,QAAQ,GAAG;AACrC,sBAAgB,QAAQ;AAAA,IAC1B;AAEA,aAAS,kBAAkB,IAAwB,OAAe;AAChE,UAAI,IAAI;AACN,wBAAgB,MAAM,IAAI,OAAO,EAAE;AAAA,MACrC,OAAO;AACL,wBAAgB,MAAM,OAAO,KAAK;AAAA,MACpC;AAAA,IACF;AAEA,aAAS,mBAAmB,OAAmB;AAC7C,YAAM,SAAS,MAAM;AAErB,UAAI,kBAAkB,SAAS,YAAY,SAAS,CAAC,YAAY,MAAM,SAAS,MAAM,GAAG;AACvF,0BAAkB,QAAQ;AAAA,MAC5B;AAEA,UAAI,gBAAgB,UAAU,MAAM;AAClC,cAAM,gBAAgB,MAAM,KAAK,gBAAgB,MAAM,OAAA,CAAQ,EAAE,KAAK,CAAC,OAAO,GAAG,SAAS,MAAM,CAAC;AACjG,YAAI,CAAC,eAAe;AAClB,0BAAgB,QAAQ;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA,cAAU,MAAM;AACd,eAAS,iBAAiB,SAAS,kBAAkB;AAAA,IACvD,CAAC;AAED,gBAAY,MAAM;AAChB,eAAS,oBAAoB,SAAS,kBAAkB;AAAA,IAC1D,CAAC;;;;;QAICA,mBAqVS,UAAA;AAAA,UApVN,OAAKC,eAAA;AAAA;YAA6C,eAAA,MAAM,OAAO;AAAA,UAAA;;UAKhED,mBA8UM,OA9UN,YA8UM;AAAA,YA5UJA,mBA6IM,OA7IN,YA6IM;AAAA,cA3IK,QAAA,YAAY,QAAA,SAAS,WAAU,MAAA,kBAAxCE,mBAUI,KAAA;AAAA;gBAV+C,MAAM,QAAA;AAAA,gBAAU,OAAM;AAAA,cAAA;gBACvEC,WAQO,yBARP,MAQO;AAAA,kBAPLA,WAMO,yBANP,MAMO;AAAA,oBALM,QAAA,YAAXC,aAAAF,mBAIM,OAJN,YAIM,CAAA,GAAA,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA;AAAA,sBAHJF,mBAEM,OAAA,EAFD,OAAM,2BAAuB;AAAA,wBAChCA,mBAA4C,QAAA,EAAtC,OAAM,wBAAA,GAAwB,GAAC;AAAA,sBAAA;;;;mCAOjC,QAAA,YAAY,QAAA,SAAS,WAAU,GAAA,kBAA7CE,mBAUI,KAAA;AAAA;gBAViD,MAAM,QAAA;AAAA,gBAAU,OAAM;AAAA,cAAA;gBACzEC,WAQO,yBARP,MAQO;AAAA,kBAPLA,WAMO,yBANP,MAMO;AAAA,oBALM,QAAA,YAAXC,aAAAF,mBAIM,OAJN,YAIM,CAAA,GAAA,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA;AAAA,sBAHJF,mBAEM,OAAA,EAFD,OAAM,2BAAuB;AAAA,wBAChCA,mBAA4C,QAAA,EAAtC,OAAM,wBAAA,GAAwB,GAAC;AAAA,sBAAA;;;;mCAOvB,QAAA,yBAAxBK,YAUc,wBAAA;AAAA;gBAVqB,IAAI,QAAA;AAAA,gBAAU,OAAM;AAAA,cAAA;iCACrD,MAQO;AAAA,kBARPF,WAQO,yBARP,MAQO;AAAA,oBAPLA,WAMO,yBANP,MAMO;AAAA,sBALM,QAAA,YAAXC,aAAAF,mBAIM,OAJN,YAIM,CAAA,GAAA,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA;AAAA,wBAHJF,mBAEM,OAAA,EAFD,OAAM,2BAAuB;AAAA,0BAChCA,mBAA4C,QAAA,EAAtC,OAAM,wBAAA,GAAwB,GAAC;AAAA,wBAAA;;;;;;+BAQ7CG,WAQO,iCARP,MAQO;AAAA,gBAPLA,WAMO,yBANP,MAMO;AAAA,kBALM,QAAA,YAAXC,aAAAF,mBAIM,OAJN,YAIM,CAAA,GAAA,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA;AAAA,oBAHJF,mBAEM,OAAA,EAFD,OAAM,2BAAuB;AAAA,sBAChCA,mBAA4C,QAAA,EAAtC,OAAM,wBAAA,GAAwB,GAAC;AAAA,oBAAA;;;;cAQpC,QAAA,SAAS,QAAA,YAAQ,CAAK,sBAAU,GAAK,aAAA,UAAA,mBAAO,WAAvDI,UAAA,GAAAF,mBAGM,OAHN,YAGM;AAAA,gBAFJF,mBAAiD,QAAjD,aAAiDM,gBAAf,QAAA,KAAK,GAAA,CAAA;AAAA,gBACvCN,mBAAuD,QAAvD,aAAuDM,gBAAlB,QAAA,QAAQ,GAAA,CAAA;AAAA,cAAA,MAI/B,QAAA,gBAAc,aAAA,UAAA,mBAAO,wBAArCJ,mBA6EM,OAAA;AAAA;yBA7E2C;AAAA,gBAAJ,KAAI;AAAA,gBAAc,OAAM;AAAA,cAAA;kBAG3D,aAAA,UAAA,mBAAO,wBADfA,mBAqBS,UAAA;AAAA;kBAnBP,MAAK;AAAA,kBACL,OAAM;AAAA,kBACL,uBAAY,qBAAmB,CAAA,MAAA,CAAA;AAAA,gBAAA;kBAE7BK,gBAAAD,gBAAA,QAAA,UAAU,IAAG,KAChB,CAAA;AAAA,gCAAAJ,mBAaM,OAAA;AAAA,oBAZJ,OAAKD,eAAA,CAAC,sBAAoB,EAAA,4BACY,kBAAA,MAAA,CAAiB,CAAA;AAAA,oBACvD,OAAM;AAAA,oBACN,QAAO;AAAA,oBACP,SAAQ;AAAA,oBACR,MAAK;AAAA,oBACL,QAAO;AAAA,oBACP,gBAAa;AAAA,oBACb,kBAAe;AAAA,oBACf,mBAAgB;AAAA,kBAAA;oBAEhBD,mBAAyB,QAAA,EAAnB,GAAE,eAAA,GAAc,MAAA,EAAA;AAAA,kBAAA;oCAG1BE,mBAA2E,QAA3E,aAA2EI,gBAApB,QAAA,UAAU,GAAA,CAAA;AAAA,gBAIzD,QAAA,SADRF,aAAAF,mBAaM,OAbN,aAaM,CAAA,GAAA,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA;AAAA,kBADJF,mBAA0B,QAAA,EAApB,GAAE,gBAAA,GAAe,MAAA,EAAA;AAAA,gBAAA;gBAIb,QAAA,sBAAZE,mBAAqE,QAArE,aAAqEI,gBAAf,QAAA,KAAK,GAAA,CAAA;gBAG3DE,eAAAR,mBA8BM,OA9BN,aA8BM;AAAA,oCA7BJE,mBA4BWO,UAAA,MAAAC,WA5Bc,QAAA,OAAK,CAAb,SAAI;;sBAAiB,KAAA,KAAK;AAAA,oBAAA;sBAEjC,KAAK,qBADbR,mBAQI,KAAA;AAAA;wBAND,MAAM,KAAK;AAAA,wBACX,OAAKD,eAAA,CAAA,4BAAA,EAAA,oCAAqE,KAAK,OAAO,QAAA,eAAa,sCAAwC,KAAK,SAAA,CAAQ,CAAA;AAAA,wBACxJ,+CAAO,kBAAA,QAAiB;AAAA,sBAAA;wBAEzBD,mBAAqE,QAArE,aAAqEM,gBAApB,KAAK,KAAK,GAAA,CAAA;AAAA,wBAC/C,KAAK,eAAjBF,UAAA,GAAAF,mBAAyG,QAAzG,aAAyGI,gBAA1B,KAAK,WAAW,GAAA,CAAA;6CAGpF,KAAK,mBADlBD,YAQc,wBAAA;AAAA;wBANX,IAAI,KAAK;AAAA,wBACT,OAAKJ,eAAA,CAAA,4BAAA,EAAA,oCAAqE,KAAK,OAAO,QAAA,eAAa,sCAAwC,KAAK,SAAA,CAAQ,CAAA;AAAA,wBACxJ,+CAAO,kBAAA,QAAiB;AAAA,sBAAA;yCAEzB,MAAqE;AAAA,0BAArED,mBAAqE,QAArE,aAAqEM,gBAApB,KAAK,KAAK,GAAA,CAAA;AAAA,0BAC/C,KAAK,eAAjBF,UAAA,GAAAF,mBAAyG,QAAzG,aAAyGI,gBAA1B,KAAK,WAAW,GAAA,CAAA;;;iEAEjGJ,mBAQS,UAAA;AAAA;wBANP,MAAK;AAAA,wBACJ,OAAKD,eAAA,CAAA,4BAAA,EAAA,oCAAqE,KAAK,OAAO,QAAA,eAAa,sCAAwC,KAAK,SAAA,CAAQ,CAAA;AAAA,wBACxJ,SAAK,CAAA,WAAE,gBAAgB,IAAI;AAAA,sBAAA;wBAE5BD,mBAAqE,QAArE,aAAqEM,gBAApB,KAAK,KAAK,GAAA,CAAA;AAAA,wBAC/C,KAAK,eAAjBF,UAAA,GAAAF,mBAAyG,QAAzG,aAAyGI,gBAA1B,KAAK,WAAW,GAAA,CAAA;;;;;0BA3BxF,kBAAA,KAAiB;AAAA,gBAAA;yBAkCf,QAAA,sBAAjBJ,mBAAyE,QAAzE,aAAyEI,gBAAf,QAAA,KAAK,GAAA,CAAA;cAG/DH,WAAmB,KAAA,QAAA,KAAA;AAAA,YAAA;cAIV,aAAA,SAAA,mBAAM,WAAjBC,aAAAF,mBAoHM,OApHN,aAoHM;AAAA,gCAnHJA,mBAkHWO,UAAA,MAAAC,WAlHa,QAAA,MAAI,CAAX,QAAG;;oCAClBR,mBAgHM,OAAA;AAAA,kBAjH4B,KAAA,IAAI;AAAA;kBAEnC,KAAG,CAAG;;AAAO,6BAAAS,MAAA,IAAI,aAAJ,gBAAAA,IAAc,UAAS,kBAAkB,IAAmB,IAAI,EAAE,IAAA;AAAA;AAAA,kBAChF,OAAM;AAAA,gBAAA;oBAIEA,MAAA,IAAI,aAAJ,gBAAAA,IAAc,wBADtBT,mBAyBS,UAAA;AAAA;oBAvBP,MAAK;AAAA,oBACJ,OAAKD,eAAA;AAAA;sBAAkF,EAAA,0BAAA,IAAI,OAAO,QAAA,gBAAgB,IAAI,SAAS,KAAK,CAAA,MAAK,EAAE,OAAO,QAAA,YAAY,EAAA;AAAA,sBAAmD,EAAA,4BAAA,IAAI,SAAA;AAAA,oBAAQ;oBAK7N,SAAKW,cAAA,CAAA,WAAO,eAAe,GAAG,GAAA,CAAA,MAAA,CAAA;AAAA,kBAAA;oDAE5B,IAAI,KAAK,IAAG,KACf,CAAA;AAAA,kCAAAV,mBAaM,OAAA;AAAA,sBAZJ,uBAAM,0BAAwB,EAAA,gCACY,0BAAoB,IAAI,GAAA,CAAE,CAAA;AAAA,sBACpE,OAAM;AAAA,sBACN,QAAO;AAAA,sBACP,SAAQ;AAAA,sBACR,MAAK;AAAA,sBACL,QAAO;AAAA,sBACP,gBAAa;AAAA,sBACb,kBAAe;AAAA,sBACf,mBAAgB;AAAA,oBAAA;sBAEhBF,mBAAyB,QAAA,EAAnB,GAAE,eAAA,GAAc,MAAA,EAAA;AAAA,oBAAA;yCAMb,IAAI,qBADjBE,mBAUI,KAAA;AAAA;oBARD,MAAM,IAAI;AAAA,oBACV,OAAKD,eAAA;AAAA;kDAAkF,IAAI,OAAO,QAAA,aAAA;AAAA,sBAA8D,EAAA,4BAAA,IAAI,SAAA;AAAA,oBAAQ;qBAM1KK,gBAAA,IAAI,KAAK,GAAA,IAAA,WAAA,KAGD,IAAI,mBADjBD,YAUc,wBAAA;AAAA;oBARX,IAAI,IAAI;AAAA,oBACR,OAAKJ,eAAA;AAAA;kDAAkF,IAAI,OAAO,QAAA,aAAA;AAAA,sBAA8D,EAAA,4BAAA,IAAI,SAAA;AAAA,oBAAQ;;qCAM7K,MAAe;AAAA,sBAAZM,gBAAAD,gBAAA,IAAI,KAAK,GAAA,CAAA;AAAA,oBAAA;;6DAEdJ,mBAWS,UAAA;AAAA;oBATP,MAAK;AAAA,oBACJ,OAAKD,eAAA;AAAA;kDAAkF,IAAI,OAAO,QAAA,aAAA;AAAA,sBAA8D,EAAA,4BAAA,IAAI,SAAA;AAAA,oBAAQ;oBAK5K,SAAK,CAAA,WAAE,eAAe,GAAG;AAAA,kBAAA,GAEvBK,gBAAA,IAAI,KAAK,GAAA,IAAA,WAAA;AAAA,oBAIHO,MAAA,IAAI,aAAJ,gBAAAA,IAAc,UAAzBL,gBAAAJ,aAAAF,mBA0CM,OA1CN,aA0CM;AAAA,qBAzCJE,UAAA,IAAA,GAAAF,mBAwCWO,UAAA,MAAAC,WAxCgB,IAAI,WAAd,WAAM;;wBAAwB,KAAA,OAAO;AAAA,sBAAA;wBAE5C,OAAO,qBADfR,mBAYI,KAAA;AAAA;0BAVD,MAAM,OAAO;AAAA,0BACb,OAAKD,eAAA;AAAA;kEAA8G,OAAO,OAAO,QAAA,aAAA;AAAA,4BAA4E,EAAA,sCAAA,OAAO,SAAA;AAAA,0BAAQ;0BAK5N,+CAAO,gBAAA,QAAe;AAAA,wBAAA;0BAEvBD,mBAAuE,QAAvE,aAAuEM,gBAAtB,OAAO,KAAK,GAAA,CAAA;AAAA,0BACjD,OAAO,eAAnBF,UAAA,GAAAF,mBAA6G,QAA7G,aAA6GI,gBAA5B,OAAO,WAAW,GAAA,CAAA;+CAGxF,OAAO,mBADpBD,YAYc,wBAAA;AAAA;0BAVX,IAAI,OAAO;AAAA,0BACX,OAAKJ,eAAA;AAAA;kEAA8G,OAAO,OAAO,QAAA,aAAA;AAAA,4BAA4E,EAAA,sCAAA,OAAO,SAAA;AAAA,0BAAQ;0BAK5N,+CAAO,gBAAA,QAAe;AAAA,wBAAA;2CAEvB,MAAuE;AAAA,4BAAvED,mBAAuE,QAAvE,aAAuEM,gBAAtB,OAAO,KAAK,GAAA,CAAA;AAAA,4BACjD,OAAO,eAAnBF,UAAA,GAAAF,mBAA6G,QAA7G,aAA6GI,gBAA5B,OAAO,WAAW,GAAA,CAAA;;;mEAErGJ,mBAYS,UAAA;AAAA;0BAVP,MAAK;AAAA,0BACJ,OAAKD,eAAA;AAAA;kEAA8G,OAAO,OAAO,QAAA,aAAA;AAAA,4BAA4E,EAAA,sCAAA,OAAO,SAAA;AAAA,0BAAQ;0BAK5N,SAAK,CAAA,WAAE,qBAAqB,QAAQ,GAAG;AAAA,wBAAA;0BAExCD,mBAAuE,QAAvE,aAAuEM,gBAAtB,OAAO,KAAK,GAAA,CAAA;AAAA,0BACjD,OAAO,eAAnBF,UAAA,GAAAF,mBAA6G,QAA7G,aAA6GI,gBAA5B,OAAO,WAAW,GAAA,CAAA;;;;;4BAvChE,gBAAA,UAAoB,IAAI,EAAE;AAAA,kBAAA;;;;YAgDzEN,mBAoEM,OApEN,aAoEM;AAAA,cAlEQ,QAAA,uBAAuB,aAAA,SAAY,CAAKc,MAAA,aAAA,kBAApDZ,mBAEO,QAFP,aAEOI,gBADF,QAAA,eAAe,GAAA,CAAA;cAKZQ,MAAA,aAAA,MAAkB,aAAA,sBAD1BT,YAaEU,aAAA;AAAA;gBAXC,mBAAiBD,MAAA,aAAA,EAAc,eAAe;AAAA,gBAC9C,qBAAmBA,MAAA,aAAA,EAAc,iBAAiB;AAAA,gBAClD,aAAWA,MAAA,aAAA,EAAc,SAAS;AAAA,gBAClC,eAAaA,MAAA,aAAA,EAAc,WAAW;AAAA,gBACtC,iBAAeA,MAAA,aAAA,EAAc,aAAa;AAAA,gBAC1C,yBAAuBA,MAAA,aAAA,EAAc,oBAAoB;AAAA,gBACzD,gBAAcA,MAAA,aAAA,EAAc,YAAY;AAAA,gBACxC,wBAAsBA,MAAA,aAAA,EAAc,mBAAmB;AAAA,gBACvD,UAAM,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAEA,MAAA,aAAA,EAAc,UAAA;AAAA,gBACtB,QAAI,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAEA,MAAA,aAAA,EAAc,WAAA;AAAA,gBACpB,UAAM,OAAA,CAAA,MAAA,OAAA,CAAA,IAAA,CAAA,WAAEA,MAAA,aAAA,EAAc,aAAA;AAAA,cAAY;cAIzBA,MAAA,aAAA,KAAiB,aAAA,sBAA7BZ,mBAEO,QAFP,aAEOI,gBADF,QAAA,eAAe,GAAA,CAAA;cAIpBH,WAAuB,KAAA,QAAA,SAAA;AAAA,cAEJ,QAAA,gCAAnBE,YAAgDW,aAAA;AAAA;gBAAZ,MAAK;AAAA,cAAA;cAGjC,QAAA,6BADRd,mBAUS,UAAA;AAAA;gBARP,MAAK;AAAA,gBACL,OAAM;AAAA,gBACN,cAAW;AAAA,gBACV,+CAAO,aAAA,QAAY;AAAA,cAAA;gBAEpBF,mBAEM,OAAA;AAAA,kBAFD,OAAM;AAAA,kBAA4B,SAAQ;AAAA,kBAAY,MAAK;AAAA,kBAAO,QAAO;AAAA,kBAAe,gBAAa;AAAA,kBAAI,kBAAe;AAAA,kBAAQ,mBAAgB;AAAA,gBAAA;kBACnJA,mBAAoV,QAAA,EAA9U,GAAE,2UAAyU;AAAA,kBAAGA,mBAAgC,UAAA;AAAA,oBAAxB,IAAG;AAAA,oBAAK,IAAG;AAAA,oBAAK,GAAE;AAAA,kBAAA;;;cAK1W,QAAA,0BADRK,YAUc,wBAAA;AAAA;gBARX,IAAI,QAAA;AAAA,gBACL,OAAM;AAAA,gBACN,cAAW;AAAA,gBACV,+CAAO,KAAI,aAAA;AAAA,cAAA;iCAEZ,MAEM,CAAA,GAAA,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA;AAAA,kBAFNL,mBAEM,OAAA;AAAA,oBAFD,OAAM;AAAA,oBAAyB,SAAQ;AAAA,oBAAY,MAAK;AAAA,oBAAO,QAAO;AAAA,oBAAe,gBAAa;AAAA,oBAAI,kBAAe;AAAA,oBAAQ,mBAAgB;AAAA,kBAAA;oBAChJA,mBAA+K,QAAA,EAAzK,GAAE,sKAAoK;AAAA,oBAAGA,mBAA0B,QAAA,EAApB,GAAE,iBAAe;AAAA,kBAAA;;;;cAKlM,QAAA,4BADRE,mBAWS,UAAA;AAAA;gBATP,MAAK;AAAA,gBACL,OAAM;AAAA,gBACN,cAAW;AAAA,gBACV,+CAAO,KAAI,eAAA;AAAA,cAAA;gBAEZF,mBAEM,OAFN,aAEMM,gBADD,eAAA,KAAc,GAAA,CAAA;AAAA,gBAEP,QAAA,yBAAZJ,mBAA4E,QAA5E,aAA4EI,gBAAlB,QAAA,QAAQ,GAAA,CAAA;;;;;QAOlE,QAAA,6BADRD,YAcgBY,aAAA;AAAA;sBAZL,aAAA;AAAA,yEAAA,aAAY,QAAA;AAAA,UACpB,QAAO,aAAA,mBAAA,mBAAgB;AAAA,UACvB,OAAM,aAAA,mBAAA,mBAAgB;AAAA,UACtB,qBAAiB,aAAA,mBAAA,mBAAgB,mBAAc;AAAA,UAC/C,OAAM,aAAA,mBAAA,mBAAgB;AAAA,QAAA;UAKZ,oBACT,MAAmC;AAAA,YAAnCd,WAAmC,KAAA,QAAA,qBAAA;AAAA,UAAA;;;uBAJZ,aAAA,mBAAA,mBAAgB,SAAI,CAAA,GAAA,CAA5B,QAAG;;cAAwD,MAAA,OAAA,IAAI,EAAE;AAAA,0BAChF,MAAyC;AAAA,gBAAzCA,WAAyC,KAAA,QAAA,gBAAZ,IAAI,EAAE,EAAA;AAAA,cAAA;;;;QAQ/BW,MAAA,aAAA,MAAkB,aAAA,sBAD1BT,YAOEa,aAAA;AAAA;UALC,eAAaJ,MAAA,aAAA,EAAc,UAAU;AAAA,UACrC,yBAAuBA,MAAA,aAAA,EAAc,aAAa;AAAA,UAClD,uBAAkB,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA,CAAA,WAAE,SAASA,MAAA,aAAA,EAAc,UAAA,IAAcA,MAAA,aAAA,EAAc;UACvE,UAAM,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA,CAAA,WAAEA,MAAA,aAAA,EAAc,aAAa,MAAM;AAAA,UACzC,YAAQ,OAAA,EAAA,MAAA,OAAA,EAAA,IAAA,CAAA,WAAEA,MAAA,aAAA,EAAc,aAAA;AAAA,QAAY;;;;;"}
|
|
@@ -25,9 +25,9 @@ declare const __VLS_component: import('vue').DefineComponent<Props, {}, {}, {},
|
|
|
25
25
|
"onEntry-click"?: ((entry: AuditEntry) => any) | undefined;
|
|
26
26
|
}>, {
|
|
27
27
|
size: "sm" | "md" | "lg";
|
|
28
|
-
emptyMessage: string;
|
|
29
28
|
order: "newest" | "oldest";
|
|
30
29
|
showFilters: boolean;
|
|
30
|
+
emptyMessage: string;
|
|
31
31
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
32
32
|
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
|
|
33
33
|
export default _default;
|
|
@@ -19,9 +19,9 @@ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, imp
|
|
|
19
19
|
}>, {
|
|
20
20
|
size: ModalSize;
|
|
21
21
|
title: string;
|
|
22
|
-
showFilters: boolean;
|
|
23
22
|
currentExperimentId: number | null;
|
|
24
23
|
groupByProject: boolean;
|
|
24
|
+
showFilters: boolean;
|
|
25
25
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
|
|
26
26
|
listRef: HTMLDivElement;
|
|
27
27
|
}, any>;
|
|
@@ -7,8 +7,8 @@ interface Props {
|
|
|
7
7
|
copyable?: boolean;
|
|
8
8
|
}
|
|
9
9
|
declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
10
|
+
copyable: boolean;
|
|
10
11
|
precision: number;
|
|
11
12
|
notation: NumberNotation;
|
|
12
|
-
copyable: boolean;
|
|
13
13
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLSpanElement>;
|
|
14
14
|
export default _default;
|
|
@@ -22,3 +22,4 @@ export { useExperimentSelector, type UseExperimentSelectorOptions, type UseExper
|
|
|
22
22
|
export { formatExperimentDate, datePresetToISO, EXPERIMENT_STATUS_OPTIONS, EXPERIMENT_STATUS_VARIANT_MAP, EXPERIMENT_STATUS_LABELS, DATE_PRESET_OPTIONS, SORT_OPTIONS, } from './experiment-utils';
|
|
23
23
|
export { useExperimentData, type UseExperimentDataOptions, type UseExperimentDataReturn, } from './useExperimentData';
|
|
24
24
|
export { getFieldRegistryEntry, getTypeDefault, type RegistryEntry, } from './formBuilderRegistry';
|
|
25
|
+
export { useAppExperiment, APP_EXPERIMENT_KEY, type UseAppExperimentOptions, type UseAppExperimentReturn, type AppExperimentState, } from './useAppExperiment';
|
|
@@ -22,7 +22,9 @@ import { useExperimentSelector } from "./useExperimentSelector.js";
|
|
|
22
22
|
import { DATE_PRESET_OPTIONS, EXPERIMENT_STATUS_LABELS, EXPERIMENT_STATUS_OPTIONS, EXPERIMENT_STATUS_VARIANT_MAP, SORT_OPTIONS, datePresetToISO, formatExperimentDate } from "./experiment-utils.js";
|
|
23
23
|
import { useExperimentData } from "./useExperimentData.js";
|
|
24
24
|
import { getFieldRegistryEntry, getTypeDefault } from "./formBuilderRegistry.js";
|
|
25
|
+
import { APP_EXPERIMENT_KEY, useAppExperiment } from "./useAppExperiment.js";
|
|
25
26
|
export {
|
|
27
|
+
APP_EXPERIMENT_KEY,
|
|
26
28
|
ATOMIC_WEIGHTS,
|
|
27
29
|
DATE_PRESET_OPTIONS,
|
|
28
30
|
DEFAULT_COLORS,
|
|
@@ -47,6 +49,7 @@ export {
|
|
|
47
49
|
rangesOverlap,
|
|
48
50
|
snapToSlot,
|
|
49
51
|
useApi,
|
|
52
|
+
useAppExperiment,
|
|
50
53
|
useAsync,
|
|
51
54
|
useAsyncBatch,
|
|
52
55
|
useAuth,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Ref, ComputedRef, InjectionKey } from 'vue';
|
|
2
|
+
import { ExperimentSummary, ExperimentStatus } from '../types';
|
|
3
|
+
export interface UseAppExperimentOptions {
|
|
4
|
+
onSelect?: (experiment: ExperimentSummary) => void | Promise<void>;
|
|
5
|
+
onSave?: () => string | null | Promise<string | null>;
|
|
6
|
+
onDetach?: () => void;
|
|
7
|
+
saveDisabled?: Ref<boolean> | ComputedRef<boolean>;
|
|
8
|
+
saveDisabledMessage?: string | Ref<string | undefined> | ComputedRef<string | undefined>;
|
|
9
|
+
}
|
|
10
|
+
export interface UseAppExperimentReturn {
|
|
11
|
+
set: (experiment: Pick<ExperimentSummary, 'id' | 'name' | 'status'>) => void;
|
|
12
|
+
clear: () => void;
|
|
13
|
+
experimentName: Readonly<Ref<string | undefined>>;
|
|
14
|
+
experimentId: Readonly<Ref<number | null>>;
|
|
15
|
+
}
|
|
16
|
+
export interface AppExperimentState {
|
|
17
|
+
experimentName: Ref<string | undefined>;
|
|
18
|
+
experimentStatus: Ref<ExperimentStatus | undefined>;
|
|
19
|
+
experimentId: Ref<number | null>;
|
|
20
|
+
showModal: Ref<boolean>;
|
|
21
|
+
saveLoading: Ref<boolean>;
|
|
22
|
+
saveSuccessMessage: Ref<string | undefined>;
|
|
23
|
+
showSave: Ref<boolean>;
|
|
24
|
+
showDetach: ComputedRef<boolean>;
|
|
25
|
+
closeModal: () => void;
|
|
26
|
+
saveDisabled: ComputedRef<boolean>;
|
|
27
|
+
saveDisabledMessage: ComputedRef<string | undefined>;
|
|
28
|
+
openModal: () => void;
|
|
29
|
+
handleSelect: (experiment: ExperimentSummary) => void;
|
|
30
|
+
handleSave: () => Promise<void>;
|
|
31
|
+
handleDetach: () => void;
|
|
32
|
+
}
|
|
33
|
+
export declare const APP_EXPERIMENT_KEY: InjectionKey<AppExperimentState>;
|
|
34
|
+
export declare function useAppExperiment(options?: UseAppExperimentOptions): UseAppExperimentReturn;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { ref, computed, toValue, onScopeDispose, provide, readonly } from "vue";
|
|
2
|
+
const APP_EXPERIMENT_KEY = Symbol("app-experiment");
|
|
3
|
+
function useAppExperiment(options = {}) {
|
|
4
|
+
const experimentName = ref();
|
|
5
|
+
const experimentStatus = ref();
|
|
6
|
+
const experimentId = ref(null);
|
|
7
|
+
const showModal = ref(false);
|
|
8
|
+
const saveLoading = ref(false);
|
|
9
|
+
const saveSuccessMessage = ref();
|
|
10
|
+
let successTimer = null;
|
|
11
|
+
const showSave = ref(!!options.onSave);
|
|
12
|
+
const showDetach = computed(() => experimentId.value !== null);
|
|
13
|
+
const saveDisabled = computed(() => toValue(options.saveDisabled) ?? false);
|
|
14
|
+
const saveDisabledMessage = computed(() => toValue(options.saveDisabledMessage));
|
|
15
|
+
function set(experiment) {
|
|
16
|
+
experimentId.value = experiment.id;
|
|
17
|
+
experimentName.value = experiment.name;
|
|
18
|
+
experimentStatus.value = experiment.status;
|
|
19
|
+
}
|
|
20
|
+
function clear() {
|
|
21
|
+
experimentId.value = null;
|
|
22
|
+
experimentName.value = void 0;
|
|
23
|
+
experimentStatus.value = void 0;
|
|
24
|
+
}
|
|
25
|
+
function openModal() {
|
|
26
|
+
showModal.value = true;
|
|
27
|
+
}
|
|
28
|
+
function closeModal() {
|
|
29
|
+
showModal.value = false;
|
|
30
|
+
}
|
|
31
|
+
function handleSelect(experiment) {
|
|
32
|
+
var _a;
|
|
33
|
+
set(experiment);
|
|
34
|
+
showModal.value = false;
|
|
35
|
+
(_a = options.onSelect) == null ? void 0 : _a.call(options, experiment);
|
|
36
|
+
}
|
|
37
|
+
async function handleSave() {
|
|
38
|
+
if (!options.onSave || saveLoading.value) return;
|
|
39
|
+
saveLoading.value = true;
|
|
40
|
+
try {
|
|
41
|
+
const message = await options.onSave();
|
|
42
|
+
if (message) {
|
|
43
|
+
saveSuccessMessage.value = message;
|
|
44
|
+
if (successTimer) clearTimeout(successTimer);
|
|
45
|
+
successTimer = setTimeout(() => {
|
|
46
|
+
saveSuccessMessage.value = void 0;
|
|
47
|
+
successTimer = null;
|
|
48
|
+
}, 3e3);
|
|
49
|
+
}
|
|
50
|
+
} finally {
|
|
51
|
+
saveLoading.value = false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function handleDetach() {
|
|
55
|
+
var _a;
|
|
56
|
+
clear();
|
|
57
|
+
(_a = options.onDetach) == null ? void 0 : _a.call(options);
|
|
58
|
+
}
|
|
59
|
+
onScopeDispose(() => {
|
|
60
|
+
if (successTimer) clearTimeout(successTimer);
|
|
61
|
+
});
|
|
62
|
+
const state = {
|
|
63
|
+
experimentName,
|
|
64
|
+
experimentStatus,
|
|
65
|
+
experimentId,
|
|
66
|
+
showModal,
|
|
67
|
+
saveLoading,
|
|
68
|
+
saveSuccessMessage,
|
|
69
|
+
showSave,
|
|
70
|
+
showDetach,
|
|
71
|
+
saveDisabled,
|
|
72
|
+
saveDisabledMessage,
|
|
73
|
+
openModal,
|
|
74
|
+
closeModal,
|
|
75
|
+
handleSelect,
|
|
76
|
+
handleSave,
|
|
77
|
+
handleDetach
|
|
78
|
+
};
|
|
79
|
+
provide(APP_EXPERIMENT_KEY, state);
|
|
80
|
+
return {
|
|
81
|
+
set,
|
|
82
|
+
clear,
|
|
83
|
+
experimentName: readonly(experimentName),
|
|
84
|
+
experimentId: readonly(experimentId)
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export {
|
|
88
|
+
APP_EXPERIMENT_KEY,
|
|
89
|
+
useAppExperiment
|
|
90
|
+
};
|
|
91
|
+
//# sourceMappingURL=useAppExperiment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAppExperiment.js","sources":["../../src/composables/useAppExperiment.ts"],"sourcesContent":["import {\n ref,\n computed,\n readonly,\n provide,\n toValue,\n onScopeDispose,\n type Ref,\n type ComputedRef,\n type InjectionKey,\n} from 'vue'\nimport type { ExperimentSummary, ExperimentStatus } from '../types'\n\nexport interface UseAppExperimentOptions {\n onSelect?: (experiment: ExperimentSummary) => void | Promise<void>\n onSave?: () => string | null | Promise<string | null>\n onDetach?: () => void\n saveDisabled?: Ref<boolean> | ComputedRef<boolean>\n saveDisabledMessage?: string | Ref<string | undefined> | ComputedRef<string | undefined>\n}\n\nexport interface UseAppExperimentReturn {\n set: (experiment: Pick<ExperimentSummary, 'id' | 'name' | 'status'>) => void\n clear: () => void\n experimentName: Readonly<Ref<string | undefined>>\n experimentId: Readonly<Ref<number | null>>\n}\n\nexport interface AppExperimentState {\n experimentName: Ref<string | undefined>\n experimentStatus: Ref<ExperimentStatus | undefined>\n experimentId: Ref<number | null>\n showModal: Ref<boolean>\n saveLoading: Ref<boolean>\n saveSuccessMessage: Ref<string | undefined>\n showSave: Ref<boolean>\n showDetach: ComputedRef<boolean>\n closeModal: () => void\n saveDisabled: ComputedRef<boolean>\n saveDisabledMessage: ComputedRef<string | undefined>\n openModal: () => void\n handleSelect: (experiment: ExperimentSummary) => void\n handleSave: () => Promise<void>\n handleDetach: () => void\n}\n\nexport const APP_EXPERIMENT_KEY: InjectionKey<AppExperimentState> = Symbol('app-experiment')\n\nexport function useAppExperiment(options: UseAppExperimentOptions = {}): UseAppExperimentReturn {\n const experimentName = ref<string | undefined>()\n const experimentStatus = ref<ExperimentStatus | undefined>()\n const experimentId = ref<number | null>(null)\n const showModal = ref(false)\n const saveLoading = ref(false)\n const saveSuccessMessage = ref<string | undefined>()\n\n let successTimer: ReturnType<typeof setTimeout> | null = null\n\n const showSave = ref(!!options.onSave)\n const showDetach = computed(() => experimentId.value !== null)\n const saveDisabled = computed(() => toValue(options.saveDisabled) ?? false)\n const saveDisabledMessage = computed(() => toValue(options.saveDisabledMessage))\n\n function set(experiment: Pick<ExperimentSummary, 'id' | 'name' | 'status'>) {\n experimentId.value = experiment.id\n experimentName.value = experiment.name\n experimentStatus.value = experiment.status\n }\n\n function clear() {\n experimentId.value = null\n experimentName.value = undefined\n experimentStatus.value = undefined\n }\n\n function openModal() {\n showModal.value = true\n }\n\n function closeModal() {\n showModal.value = false\n }\n\n function handleSelect(experiment: ExperimentSummary) {\n set(experiment)\n showModal.value = false\n options.onSelect?.(experiment)\n }\n\n async function handleSave() {\n if (!options.onSave || saveLoading.value) return\n saveLoading.value = true\n try {\n const message = await options.onSave()\n if (message) {\n saveSuccessMessage.value = message\n if (successTimer) clearTimeout(successTimer)\n successTimer = setTimeout(() => {\n saveSuccessMessage.value = undefined\n successTimer = null\n }, 3000)\n }\n } finally {\n saveLoading.value = false\n }\n }\n\n function handleDetach() {\n clear()\n options.onDetach?.()\n }\n\n onScopeDispose(() => {\n if (successTimer) clearTimeout(successTimer)\n })\n\n const state: AppExperimentState = {\n experimentName,\n experimentStatus,\n experimentId,\n showModal,\n saveLoading,\n saveSuccessMessage,\n showSave,\n showDetach,\n saveDisabled,\n saveDisabledMessage,\n openModal,\n closeModal,\n handleSelect,\n handleSave,\n handleDetach,\n }\n\n provide(APP_EXPERIMENT_KEY, state)\n\n return {\n set,\n clear,\n experimentName: readonly(experimentName),\n experimentId: readonly(experimentId),\n }\n}\n"],"names":[],"mappings":";AA8CO,MAAM,qBAAuD,OAAO,gBAAgB;AAEpF,SAAS,iBAAiB,UAAmC,IAA4B;AAC9F,QAAM,iBAAiB,IAAA;AACvB,QAAM,mBAAmB,IAAA;AACzB,QAAM,eAAe,IAAmB,IAAI;AAC5C,QAAM,YAAY,IAAI,KAAK;AAC3B,QAAM,cAAc,IAAI,KAAK;AAC7B,QAAM,qBAAqB,IAAA;AAE3B,MAAI,eAAqD;AAEzD,QAAM,WAAW,IAAI,CAAC,CAAC,QAAQ,MAAM;AACrC,QAAM,aAAa,SAAS,MAAM,aAAa,UAAU,IAAI;AAC7D,QAAM,eAAe,SAAS,MAAM,QAAQ,QAAQ,YAAY,KAAK,KAAK;AAC1E,QAAM,sBAAsB,SAAS,MAAM,QAAQ,QAAQ,mBAAmB,CAAC;AAE/E,WAAS,IAAI,YAA+D;AAC1E,iBAAa,QAAQ,WAAW;AAChC,mBAAe,QAAQ,WAAW;AAClC,qBAAiB,QAAQ,WAAW;AAAA,EACtC;AAEA,WAAS,QAAQ;AACf,iBAAa,QAAQ;AACrB,mBAAe,QAAQ;AACvB,qBAAiB,QAAQ;AAAA,EAC3B;AAEA,WAAS,YAAY;AACnB,cAAU,QAAQ;AAAA,EACpB;AAEA,WAAS,aAAa;AACpB,cAAU,QAAQ;AAAA,EACpB;AAEA,WAAS,aAAa,YAA+B;;AACnD,QAAI,UAAU;AACd,cAAU,QAAQ;AAClB,kBAAQ,aAAR,iCAAmB;AAAA,EACrB;AAEA,iBAAe,aAAa;AAC1B,QAAI,CAAC,QAAQ,UAAU,YAAY,MAAO;AAC1C,gBAAY,QAAQ;AACpB,QAAI;AACF,YAAM,UAAU,MAAM,QAAQ,OAAA;AAC9B,UAAI,SAAS;AACX,2BAAmB,QAAQ;AAC3B,YAAI,2BAA2B,YAAY;AAC3C,uBAAe,WAAW,MAAM;AAC9B,6BAAmB,QAAQ;AAC3B,yBAAe;AAAA,QACjB,GAAG,GAAI;AAAA,MACT;AAAA,IACF,UAAA;AACE,kBAAY,QAAQ;AAAA,IACtB;AAAA,EACF;AAEA,WAAS,eAAe;;AACtB,UAAA;AACA,kBAAQ,aAAR;AAAA,EACF;AAEA,iBAAe,MAAM;AACnB,QAAI,2BAA2B,YAAY;AAAA,EAC7C,CAAC;AAED,QAAM,QAA4B;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAGF,UAAQ,oBAAoB,KAAK;AAEjC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,gBAAgB,SAAS,cAAc;AAAA,IACvC,cAAc,SAAS,YAAY;AAAA,EAAA;AAEvC;"}
|
|
@@ -54,7 +54,14 @@ function usePlatformContext(options = {}) {
|
|
|
54
54
|
}
|
|
55
55
|
platformContext.value = {
|
|
56
56
|
isIntegrated: hasPluginParam,
|
|
57
|
-
theme:
|
|
57
|
+
theme: (() => {
|
|
58
|
+
try {
|
|
59
|
+
const s = localStorage.getItem("mld-settings");
|
|
60
|
+
if (s) return JSON.parse(s).theme || "system";
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
63
|
+
return "system";
|
|
64
|
+
})(),
|
|
58
65
|
platformOrigin: platformOrigin || void 0
|
|
59
66
|
};
|
|
60
67
|
}
|