@morscherlab/mint-sdk 1.4.0-beta.15 → 1.4.0-beta.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/{AppSidebar-Bi8g9mRt.js → AppSidebar-CB0-RQ4m.js} +876 -114
  2. package/dist/AppSidebar-CB0-RQ4m.js.map +1 -0
  3. package/dist/{SettingsModal-jra_2u0o.js → SettingsModal-CoZK3EDN.js} +2 -2
  4. package/dist/{SettingsModal-jra_2u0o.js.map → SettingsModal-CoZK3EDN.js.map} +1 -1
  5. package/dist/__tests__/components/AppTopBarOnboarding.test.d.ts +1 -0
  6. package/dist/__tests__/composables/useOnboarding.test.d.ts +1 -0
  7. package/dist/components/AppTopBar.vue.d.ts +4 -4
  8. package/dist/components/internal/AppTopBarOnboardingInternal.vue.d.ts +7 -0
  9. package/dist/components/internal/OnboardingLayerInternal.vue.d.ts +7 -0
  10. package/dist/composables/useOnboarding.d.ts +119 -0
  11. package/dist/index.js +5 -5
  12. package/dist/{install-Bx_6KwJA.js → install-BKgb5qZw.js} +5 -5
  13. package/dist/{install-Bx_6KwJA.js.map → install-BKgb5qZw.js.map} +1 -1
  14. package/dist/install.js +1 -1
  15. package/dist/{runtime-BJvGms6h.js → runtime-Cz1GJa_O.js} +2 -2
  16. package/dist/{runtime-BJvGms6h.js.map → runtime-Cz1GJa_O.js.map} +1 -1
  17. package/dist/runtime.js +2 -2
  18. package/dist/{shell-Czyrzk7l.js → shell-kq9p4VsX.js} +7 -2
  19. package/dist/{shell-Czyrzk7l.js.map → shell-kq9p4VsX.js.map} +1 -1
  20. package/dist/shell.d.ts +1 -0
  21. package/dist/shell.js +3 -3
  22. package/dist/styles.css +385 -0
  23. package/package.json +1 -1
  24. package/src/__tests__/components/AppTopBarOnboarding.test.ts +160 -0
  25. package/src/__tests__/composables/useOnboarding.test.ts +317 -0
  26. package/src/__tests__/styles/v2AuditRules.test.ts +8 -0
  27. package/src/components/AppTopBar.onboarding.story.vue +69 -0
  28. package/src/components/AppTopBar.vue +11 -2
  29. package/src/components/internal/AppTopBarOnboardingInternal.vue +172 -0
  30. package/src/components/internal/OnboardingLayerInternal.vue +173 -0
  31. package/src/composables/useOnboarding.ts +465 -0
  32. package/src/shell.ts +17 -0
  33. package/src/styles/components/onboarding.css +368 -0
  34. package/src/styles/index.css +1 -0
  35. package/src/styles/variables.css +16 -0
  36. package/dist/AppSidebar-Bi8g9mRt.js.map +0 -1
@@ -2,8 +2,9 @@ import { a as BaseButton_default, i as useEventListener, t as useDropdownState }
2
2
  import { n as integrationHost, u as useSettingsStore } from "./experiment-DyO54FQB.js";
3
3
  import { E as useMenuKeyboard, I as FormField_default, _ as APP_EXPERIMENT_KEY, t as isRecord, z as BaseCheckbox_default } from "./records-B4yl2oIu.js";
4
4
  import { F as applySpecDefaults, _ as getFieldRegistryEntry, a as StepWizard_default, d as humanize, f as numericValue, l as normalizeControls, m as orderedUnique, o as usePlatform, s as defaultValueForControl, u as normalizeOption, v as getTypeDefault } from "./useListReorder-C_8RYeVP.js";
5
- import { Fragment, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineAsyncComponent, defineComponent, guardReactiveProps, inject, mergeProps, nextTick, normalizeClass, normalizeProps, normalizeStyle, onBeforeUnmount, onMounted, openBlock, reactive, readonly, ref, renderList, renderSlot, resolveComponent, resolveDynamicComponent, shallowRef, toDisplayString, toRaw, toValue, unref, useSlots, useTemplateRef, vShow, watch, withCtx, withDirectives, withModifiers } from "vue";
6
- import { CircleAlert, CircleCheck, CircleX, ListChecks, LoaderCircle, Moon, Sun } from "lucide-vue-next";
5
+ import { Fragment, Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineAsyncComponent, defineComponent, guardReactiveProps, inject, mergeProps, nextTick, normalizeClass, normalizeProps, normalizeStyle, onBeforeUnmount, onMounted, onScopeDispose, openBlock, provide, reactive, readonly, ref, renderList, renderSlot, resolveComponent, resolveDynamicComponent, shallowRef, toDisplayString, toRaw, toValue, unref, useId, useSlots, useTemplateRef, vShow, watch, withCtx, withDirectives, withModifiers } from "vue";
6
+ import { Check, CircleAlert, CircleCheck, CircleHelp, CircleX, ListChecks, LoaderCircle, Moon, Play, Sun, X } from "lucide-vue-next";
7
+ import { autoUpdate, computePosition, flip, offset, shift } from "@floating-ui/dom";
7
8
  //#region src/composables/useTheme.ts
8
9
  /** Reads and toggles the active theme (light/dark/system) with reactivity to OS preference changes. */
9
10
  function useTheme() {
@@ -49,25 +50,25 @@ var ThemeToggle_default = /* @__PURE__ */ defineComponent({
49
50
  });
50
51
  //#endregion
51
52
  //#region src/components/CollapsibleCard.vue?vue&type=script&setup=true&lang.ts
52
- var _hoisted_1$10 = { class: "mint-collapsible-card__header-shell" };
53
- var _hoisted_2$8 = ["disabled", "aria-expanded"];
54
- var _hoisted_3$8 = { class: "mint-collapsible-card__title-section" };
55
- var _hoisted_4$7 = ["d"];
56
- var _hoisted_5$7 = ["d"];
57
- var _hoisted_6$6 = { class: "mint-collapsible-card__titles" };
58
- var _hoisted_7$5 = { class: "mint-collapsible-card__title" };
59
- var _hoisted_8$5 = {
53
+ var _hoisted_1$12 = { class: "mint-collapsible-card__header-shell" };
54
+ var _hoisted_2$10 = ["disabled", "aria-expanded"];
55
+ var _hoisted_3$10 = { class: "mint-collapsible-card__title-section" };
56
+ var _hoisted_4$9 = ["d"];
57
+ var _hoisted_5$9 = ["d"];
58
+ var _hoisted_6$8 = { class: "mint-collapsible-card__titles" };
59
+ var _hoisted_7$7 = { class: "mint-collapsible-card__title" };
60
+ var _hoisted_8$7 = {
60
61
  key: 0,
61
62
  class: "mint-collapsible-card__subtitle"
62
63
  };
63
- var _hoisted_9$5 = { class: "mint-collapsible-card__actions" };
64
- var _hoisted_10$4 = [
64
+ var _hoisted_9$7 = { class: "mint-collapsible-card__actions" };
65
+ var _hoisted_10$6 = [
65
66
  "disabled",
66
67
  "aria-label",
67
68
  "title",
68
69
  "onClick"
69
70
  ];
70
- var _hoisted_11$4 = {
71
+ var _hoisted_11$6 = {
71
72
  key: 0,
72
73
  class: "mint-collapsible-card__action-icon",
73
74
  viewBox: "0 0 24 24",
@@ -78,13 +79,13 @@ var _hoisted_11$4 = {
78
79
  "stroke-linejoin": "round",
79
80
  "aria-hidden": "true"
80
81
  };
81
- var _hoisted_12$4 = ["d"];
82
- var _hoisted_13$4 = ["d"];
83
- var _hoisted_14$2 = {
82
+ var _hoisted_12$5 = ["d"];
83
+ var _hoisted_13$5 = ["d"];
84
+ var _hoisted_14$3 = {
84
85
  key: 1,
85
86
  class: "mint-collapsible-card__action-text-icon"
86
87
  };
87
- var _hoisted_15$2 = [
88
+ var _hoisted_15$3 = [
88
89
  "disabled",
89
90
  "aria-label",
90
91
  "aria-expanded"
@@ -160,13 +161,13 @@ var CollapsibleCard_default = /* @__PURE__ */ defineComponent({
160
161
  emit("action", action.id);
161
162
  }
162
163
  return (_ctx, _cache) => {
163
- return openBlock(), createElementBlock("div", { class: normalizeClass(["mint-collapsible-card", __props.dense ? "mint-collapsible-card--dense" : ""]) }, [createElementVNode("div", _hoisted_1$10, [createElementVNode("button", {
164
+ return openBlock(), createElementBlock("div", { class: normalizeClass(["mint-collapsible-card", __props.dense ? "mint-collapsible-card--dense" : ""]) }, [createElementVNode("div", _hoisted_1$12, [createElementVNode("button", {
164
165
  type: "button",
165
166
  class: normalizeClass(headerClasses.value),
166
167
  disabled: __props.disabled,
167
168
  "aria-expanded": isOpen.value,
168
169
  onClick: toggle
169
- }, [createElementVNode("div", _hoisted_3$8, [__props.icon ? (openBlock(), createElementBlock("div", {
170
+ }, [createElementVNode("div", _hoisted_3$10, [__props.icon ? (openBlock(), createElementBlock("div", {
170
171
  key: 0,
171
172
  class: "mint-collapsible-card__icon-badge",
172
173
  style: normalizeStyle(iconBgStyle.value)
@@ -184,15 +185,15 @@ var CollapsibleCard_default = /* @__PURE__ */ defineComponent({
184
185
  return openBlock(), createElementBlock("path", {
185
186
  key: i,
186
187
  d
187
- }, null, 8, _hoisted_4$7);
188
+ }, null, 8, _hoisted_4$9);
188
189
  }), 128)) : (openBlock(), createElementBlock("path", {
189
190
  key: 1,
190
191
  d: __props.icon
191
- }, null, 8, _hoisted_5$7))], 4)) : (openBlock(), createElementBlock("span", {
192
+ }, null, 8, _hoisted_5$9))], 4)) : (openBlock(), createElementBlock("span", {
192
193
  key: 1,
193
194
  class: "mint-collapsible-card__icon-text",
194
195
  style: normalizeStyle(iconColorStyle.value)
195
- }, toDisplayString(__props.icon), 5))], 4)) : createCommentVNode("", true), createElementVNode("div", _hoisted_6$6, [createElementVNode("h3", _hoisted_7$5, toDisplayString(__props.title), 1), __props.subtitle ? (openBlock(), createElementBlock("p", _hoisted_8$5, toDisplayString(__props.subtitle), 1)) : createCommentVNode("", true)])])], 10, _hoisted_2$8), createElementVNode("div", _hoisted_9$5, [
196
+ }, toDisplayString(__props.icon), 5))], 4)) : createCommentVNode("", true), createElementVNode("div", _hoisted_6$8, [createElementVNode("h3", _hoisted_7$7, toDisplayString(__props.title), 1), __props.subtitle ? (openBlock(), createElementBlock("p", _hoisted_8$7, toDisplayString(__props.subtitle), 1)) : createCommentVNode("", true)])])], 10, _hoisted_2$10), createElementVNode("div", _hoisted_9$7, [
196
197
  __props.badge !== void 0 ? (openBlock(), createElementBlock("span", {
197
198
  key: 0,
198
199
  class: normalizeClass(badgeClasses.value)
@@ -207,15 +208,15 @@ var CollapsibleCard_default = /* @__PURE__ */ defineComponent({
207
208
  "aria-label": action.label,
208
209
  title: action.label,
209
210
  onClick: ($event) => handleActionClick(action)
210
- }, [action.icon && isSvgIconValue(action.icon) ? (openBlock(), createElementBlock("svg", _hoisted_11$4, [Array.isArray(action.icon) ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(action.icon, (d, i) => {
211
+ }, [action.icon && isSvgIconValue(action.icon) ? (openBlock(), createElementBlock("svg", _hoisted_11$6, [Array.isArray(action.icon) ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(action.icon, (d, i) => {
211
212
  return openBlock(), createElementBlock("path", {
212
213
  key: i,
213
214
  d
214
- }, null, 8, _hoisted_12$4);
215
+ }, null, 8, _hoisted_12$5);
215
216
  }), 128)) : (openBlock(), createElementBlock("path", {
216
217
  key: 1,
217
218
  d: action.icon
218
- }, null, 8, _hoisted_13$4))])) : action.icon ? (openBlock(), createElementBlock("span", _hoisted_14$2, toDisplayString(action.icon), 1)) : createCommentVNode("", true)], 14, _hoisted_10$4);
219
+ }, null, 8, _hoisted_13$5))])) : action.icon ? (openBlock(), createElementBlock("span", _hoisted_14$3, toDisplayString(action.icon), 1)) : createCommentVNode("", true)], 14, _hoisted_10$6);
219
220
  }), 128)),
220
221
  __props.showToggle ? (openBlock(), createElementBlock("div", {
221
222
  key: 1,
@@ -244,7 +245,7 @@ var CollapsibleCard_default = /* @__PURE__ */ defineComponent({
244
245
  "stroke-linejoin": "round",
245
246
  viewBox: "0 0 24 24",
246
247
  "aria-hidden": "true"
247
- }, [..._cache[2] || (_cache[2] = [createElementVNode("path", { d: "m6 9 6 6 6-6" }, null, -1)])], 2))], 8, _hoisted_15$2)
248
+ }, [..._cache[2] || (_cache[2] = [createElementVNode("path", { d: "m6 9 6 6 6-6" }, null, -1)])], 2))], 8, _hoisted_15$3)
248
249
  ])]), createVNode(Transition, { name: "collapse" }, {
249
250
  default: withCtx(() => [withDirectives(createElementVNode("div", _hoisted_16$2, [createElementVNode("div", _hoisted_17$2, [renderSlot(_ctx.$slots, "default")])], 512), [[vShow, isOpen.value]])]),
250
251
  _: 3
@@ -848,13 +849,13 @@ function usePluginWorkspace(options) {
848
849
  }
849
850
  //#endregion
850
851
  //#region src/components/AppLayout.vue?vue&type=script&setup=true&lang.ts
851
- var _hoisted_1$9 = {
852
+ var _hoisted_1$11 = {
852
853
  key: 0,
853
854
  class: "mint-layout__topbar"
854
855
  };
855
- var _hoisted_2$7 = { class: "mint-layout__body" };
856
- var _hoisted_3$7 = ["aria-label", "aria-expanded"];
857
- var _hoisted_4$6 = {
856
+ var _hoisted_2$9 = { class: "mint-layout__body" };
857
+ var _hoisted_3$9 = ["aria-label", "aria-expanded"];
858
+ var _hoisted_4$8 = {
858
859
  key: 0,
859
860
  class: "mint-layout__sidebar-toggle-icon",
860
861
  viewBox: "0 0 24 24",
@@ -865,7 +866,7 @@ var _hoisted_4$6 = {
865
866
  "stroke-linejoin": "round",
866
867
  "aria-hidden": "true"
867
868
  };
868
- var _hoisted_5$6 = {
869
+ var _hoisted_5$8 = {
869
870
  key: 1,
870
871
  class: "mint-layout__sidebar-toggle-icon",
871
872
  viewBox: "0 0 24 24",
@@ -876,7 +877,7 @@ var _hoisted_5$6 = {
876
877
  "stroke-linejoin": "round",
877
878
  "aria-hidden": "true"
878
879
  };
879
- var _hoisted_6$5 = { class: "mint-layout__main" };
880
+ var _hoisted_6$7 = { class: "mint-layout__main" };
880
881
  //#endregion
881
882
  //#region src/components/AppLayout.vue
882
883
  var AppLayout_default = /* @__PURE__ */ defineComponent({
@@ -954,7 +955,7 @@ var AppLayout_default = /* @__PURE__ */ defineComponent({
954
955
  sidebarOpenModel.value = false;
955
956
  }
956
957
  return (_ctx, _cache) => {
957
- return openBlock(), createElementBlock("div", { class: normalizeClass(layoutClasses.value) }, [_ctx.$slots.topbar ? (openBlock(), createElementBlock("div", _hoisted_1$9, [renderSlot(_ctx.$slots, "topbar")])) : createCommentVNode("", true), createElementVNode("div", _hoisted_2$7, [
958
+ return openBlock(), createElementBlock("div", { class: normalizeClass(layoutClasses.value) }, [_ctx.$slots.topbar ? (openBlock(), createElementBlock("div", _hoisted_1$11, [renderSlot(_ctx.$slots, "topbar")])) : createCommentVNode("", true), createElementVNode("div", _hoisted_2$9, [
958
959
  __props.responsiveSidebar && _ctx.$slots.sidebar ? (openBlock(), createElementBlock("button", {
959
960
  key: 0,
960
961
  type: "button",
@@ -962,7 +963,7 @@ var AppLayout_default = /* @__PURE__ */ defineComponent({
962
963
  "aria-label": sidebarOpenModel.value ? __props.sidebarCloseLabel : __props.sidebarToggleLabel,
963
964
  "aria-expanded": sidebarOpenModel.value,
964
965
  onClick: toggleSidebar
965
- }, [!sidebarOpenModel.value ? (openBlock(), createElementBlock("svg", _hoisted_4$6, [..._cache[0] || (_cache[0] = [createElementVNode("path", { d: "M4 6h16M4 12h16M4 18h16" }, null, -1)])])) : (openBlock(), createElementBlock("svg", _hoisted_5$6, [..._cache[1] || (_cache[1] = [createElementVNode("path", { d: "M6 18 18 6M6 6l12 12" }, null, -1)])]))], 8, _hoisted_3$7)) : createCommentVNode("", true),
966
+ }, [!sidebarOpenModel.value ? (openBlock(), createElementBlock("svg", _hoisted_4$8, [..._cache[0] || (_cache[0] = [createElementVNode("path", { d: "M4 6h16M4 12h16M4 18h16" }, null, -1)])])) : (openBlock(), createElementBlock("svg", _hoisted_5$8, [..._cache[1] || (_cache[1] = [createElementVNode("path", { d: "M6 18 18 6M6 6l12 12" }, null, -1)])]))], 8, _hoisted_3$9)) : createCommentVNode("", true),
966
967
  __props.responsiveSidebar && _ctx.$slots.sidebar && sidebarOpenModel.value ? (openBlock(), createElementBlock("div", {
967
968
  key: 1,
968
969
  class: "mint-layout__sidebar-backdrop",
@@ -973,7 +974,7 @@ var AppLayout_default = /* @__PURE__ */ defineComponent({
973
974
  class: "mint-layout__sidebar",
974
975
  style: normalizeStyle(sidebarStyle.value)
975
976
  }, [renderSlot(_ctx.$slots, "sidebar")], 4)) : createCommentVNode("", true),
976
- createElementVNode("main", _hoisted_6$5, [renderSlot(_ctx.$slots, "default")])
977
+ createElementVNode("main", _hoisted_6$7, [renderSlot(_ctx.$slots, "default")])
977
978
  ])], 2);
978
979
  };
979
980
  }
@@ -1123,18 +1124,18 @@ function isFiniteNumber(value, min, max) {
1123
1124
  }
1124
1125
  //#endregion
1125
1126
  //#region src/components/internal/ActionItemInternal.vue?vue&type=script&setup=true&lang.ts
1126
- var _hoisted_1$8 = [
1127
+ var _hoisted_1$10 = [
1127
1128
  "href",
1128
1129
  "aria-disabled",
1129
1130
  "tabindex"
1130
1131
  ];
1131
- var _hoisted_2$6 = [
1132
+ var _hoisted_2$8 = [
1132
1133
  "href",
1133
1134
  "aria-disabled",
1134
1135
  "tabindex",
1135
1136
  "onClick"
1136
1137
  ];
1137
- var _hoisted_3$6 = ["type", "disabled"];
1138
+ var _hoisted_3$8 = ["type", "disabled"];
1138
1139
  //#endregion
1139
1140
  //#region src/components/internal/ActionItemInternal.vue
1140
1141
  var ActionItemInternal_default = /* @__PURE__ */ defineComponent({
@@ -1180,7 +1181,7 @@ var ActionItemInternal_default = /* @__PURE__ */ defineComponent({
1180
1181
  "aria-disabled": __props.disabled || void 0,
1181
1182
  tabindex: __props.disabled ? -1 : void 0,
1182
1183
  onClick: handleClick
1183
- }), [renderSlot(_ctx.$slots, "default")], 16, _hoisted_1$8)) : __props.to ? (openBlock(), createBlock(_component_router_link, {
1184
+ }), [renderSlot(_ctx.$slots, "default")], 16, _hoisted_1$10)) : __props.to ? (openBlock(), createBlock(_component_router_link, {
1184
1185
  key: 1,
1185
1186
  to: __props.to,
1186
1187
  custom: ""
@@ -1190,33 +1191,33 @@ var ActionItemInternal_default = /* @__PURE__ */ defineComponent({
1190
1191
  "aria-disabled": __props.disabled || void 0,
1191
1192
  tabindex: __props.disabled ? -1 : void 0,
1192
1193
  onClick: ($event) => handleRouterClick($event, navigate)
1193
- }), [renderSlot(_ctx.$slots, "default")], 16, _hoisted_2$6)]),
1194
+ }), [renderSlot(_ctx.$slots, "default")], 16, _hoisted_2$8)]),
1194
1195
  _: 3
1195
1196
  }, 8, ["to"])) : (openBlock(), createElementBlock("button", mergeProps({ key: 2 }, _ctx.$attrs, {
1196
1197
  type: __props.type,
1197
1198
  disabled: __props.disabled,
1198
1199
  onClick: handleClick
1199
- }), [renderSlot(_ctx.$slots, "default")], 16, _hoisted_3$6));
1200
+ }), [renderSlot(_ctx.$slots, "default")], 16, _hoisted_3$8));
1200
1201
  };
1201
1202
  }
1202
1203
  });
1203
1204
  //#endregion
1204
1205
  //#region src/components/PluginIcon.vue?vue&type=script&setup=true&lang.ts
1205
- var _hoisted_1$7 = ["viewBox"];
1206
- var _hoisted_2$5 = { key: 0 };
1207
- var _hoisted_3$5 = [
1206
+ var _hoisted_1$9 = ["viewBox"];
1207
+ var _hoisted_2$7 = { key: 0 };
1208
+ var _hoisted_3$7 = [
1208
1209
  "id",
1209
1210
  "x1",
1210
1211
  "y1",
1211
1212
  "x2",
1212
1213
  "y2"
1213
1214
  ];
1214
- var _hoisted_4$5 = [
1215
+ var _hoisted_4$7 = [
1215
1216
  "offset",
1216
1217
  "stop-color",
1217
1218
  "stop-opacity"
1218
1219
  ];
1219
- var _hoisted_5$5 = [
1220
+ var _hoisted_5$7 = [
1220
1221
  "x",
1221
1222
  "y",
1222
1223
  "width",
@@ -1224,14 +1225,14 @@ var _hoisted_5$5 = [
1224
1225
  "rx",
1225
1226
  "fill"
1226
1227
  ];
1227
- var _hoisted_6$4 = [
1228
+ var _hoisted_6$6 = [
1228
1229
  "d",
1229
1230
  "fill",
1230
1231
  "stroke",
1231
1232
  "stroke-width",
1232
1233
  "opacity"
1233
1234
  ];
1234
- var _hoisted_7$4 = {
1235
+ var _hoisted_7$6 = {
1235
1236
  key: 1,
1236
1237
  class: "mint-plugin-icon__svg",
1237
1238
  viewBox: "0 0 24 24",
@@ -1242,8 +1243,8 @@ var _hoisted_7$4 = {
1242
1243
  "stroke-linejoin": "round",
1243
1244
  "aria-hidden": "true"
1244
1245
  };
1245
- var _hoisted_8$4 = ["d"];
1246
- var _hoisted_9$4 = ["src"];
1246
+ var _hoisted_8$6 = ["d"];
1247
+ var _hoisted_9$6 = ["src"];
1247
1248
  //#endregion
1248
1249
  //#region src/components/PluginIcon.vue
1249
1250
  var PluginIcon_default = /* @__PURE__ */ defineComponent({
@@ -1319,7 +1320,7 @@ var PluginIcon_default = /* @__PURE__ */ defineComponent({
1319
1320
  viewBox: structuredIcon.value.viewBox,
1320
1321
  "aria-hidden": "true"
1321
1322
  }, [
1322
- structuredIcon.value.gradient ? (openBlock(), createElementBlock("defs", _hoisted_2$5, [createElementVNode("linearGradient", {
1323
+ structuredIcon.value.gradient ? (openBlock(), createElementBlock("defs", _hoisted_2$7, [createElementVNode("linearGradient", {
1323
1324
  id: gradientId.value,
1324
1325
  x1: gradientCoords.value.x1,
1325
1326
  y1: gradientCoords.value.y1,
@@ -1331,8 +1332,8 @@ var PluginIcon_default = /* @__PURE__ */ defineComponent({
1331
1332
  offset: stop.offset,
1332
1333
  "stop-color": stop.color,
1333
1334
  "stop-opacity": stop.opacity
1334
- }, null, 8, _hoisted_4$5);
1335
- }), 128))], 8, _hoisted_3$5)])) : createCommentVNode("", true),
1335
+ }, null, 8, _hoisted_4$7);
1336
+ }), 128))], 8, _hoisted_3$7)])) : createCommentVNode("", true),
1336
1337
  structuredIcon.value.background ? (openBlock(), createElementBlock("rect", {
1337
1338
  key: 1,
1338
1339
  x: structuredViewBox.value.x,
@@ -1341,7 +1342,7 @@ var PluginIcon_default = /* @__PURE__ */ defineComponent({
1341
1342
  height: structuredViewBox.value.height,
1342
1343
  rx: structuredIcon.value.background.radius,
1343
1344
  fill: backgroundFill.value
1344
- }, null, 8, _hoisted_5$5)) : createCommentVNode("", true),
1345
+ }, null, 8, _hoisted_5$7)) : createCommentVNode("", true),
1345
1346
  (openBlock(true), createElementBlock(Fragment, null, renderList(structuredIcon.value.paths, (path, index) => {
1346
1347
  return openBlock(), createElementBlock("path", {
1347
1348
  key: index,
@@ -1352,52 +1353,52 @@ var PluginIcon_default = /* @__PURE__ */ defineComponent({
1352
1353
  opacity: path.opacity,
1353
1354
  "stroke-linecap": "round",
1354
1355
  "stroke-linejoin": "round"
1355
- }, null, 8, _hoisted_6$4);
1356
+ }, null, 8, _hoisted_6$6);
1356
1357
  }), 128))
1357
- ], 8, _hoisted_1$7)) : detected.value.format === "path" || detected.value.format === "fallback" ? (openBlock(), createElementBlock("svg", _hoisted_7$4, [createElementVNode("path", { d: iconValue.value }, null, 8, _hoisted_8$4)])) : (openBlock(), createElementBlock("img", {
1358
+ ], 8, _hoisted_1$9)) : detected.value.format === "path" || detected.value.format === "fallback" ? (openBlock(), createElementBlock("svg", _hoisted_7$6, [createElementVNode("path", { d: iconValue.value }, null, 8, _hoisted_8$6)])) : (openBlock(), createElementBlock("img", {
1358
1359
  key: 2,
1359
1360
  class: "mint-plugin-icon__img",
1360
1361
  src: iconValue.value,
1361
1362
  alt: "",
1362
1363
  referrerpolicy: "no-referrer",
1363
1364
  loading: "lazy"
1364
- }, null, 8, _hoisted_9$4))], 6);
1365
+ }, null, 8, _hoisted_9$6))], 6);
1365
1366
  };
1366
1367
  }
1367
1368
  });
1368
1369
  //#endregion
1369
1370
  //#region src/components/internal/AppTopBarPageSelectorInternal.vue?vue&type=script&setup=true&lang.ts
1370
- var _hoisted_1$6 = {
1371
+ var _hoisted_1$8 = {
1371
1372
  ref: "root",
1372
1373
  class: "mint-page-selector__crumb"
1373
1374
  };
1374
- var _hoisted_2$4 = { class: "mint-page-selector__plugin" };
1375
- var _hoisted_3$4 = ["aria-expanded"];
1376
- var _hoisted_4$4 = {
1375
+ var _hoisted_2$6 = { class: "mint-page-selector__plugin" };
1376
+ var _hoisted_3$6 = ["aria-expanded"];
1377
+ var _hoisted_4$6 = {
1377
1378
  key: 1,
1378
1379
  class: "mint-page-selector__icon-fallback"
1379
1380
  };
1380
- var _hoisted_5$4 = { class: "mint-page-selector__label" };
1381
- var _hoisted_6$3 = {
1381
+ var _hoisted_5$6 = { class: "mint-page-selector__label" };
1382
+ var _hoisted_6$5 = {
1382
1383
  class: "mint-page-selector__chevron-wrap",
1383
1384
  "aria-hidden": "true"
1384
1385
  };
1385
- var _hoisted_7$3 = ["aria-label"];
1386
- var _hoisted_8$3 = {
1386
+ var _hoisted_7$5 = ["aria-label"];
1387
+ var _hoisted_8$5 = {
1387
1388
  class: "mint-page-selector__menu-title",
1388
1389
  "aria-hidden": "true"
1389
1390
  };
1390
- var _hoisted_9$3 = {
1391
+ var _hoisted_9$5 = {
1391
1392
  key: 1,
1392
1393
  class: "mint-page-selector__icon-fallback"
1393
1394
  };
1394
- var _hoisted_10$3 = { class: "mint-page-selector__item-text" };
1395
- var _hoisted_11$3 = { class: "mint-page-selector__item-label" };
1396
- var _hoisted_12$3 = {
1395
+ var _hoisted_10$5 = { class: "mint-page-selector__item-text" };
1396
+ var _hoisted_11$5 = { class: "mint-page-selector__item-label" };
1397
+ var _hoisted_12$4 = {
1397
1398
  key: 0,
1398
1399
  class: "mint-page-selector__item-hint"
1399
1400
  };
1400
- var _hoisted_13$3 = {
1401
+ var _hoisted_13$4 = {
1401
1402
  key: 0,
1402
1403
  class: "mint-page-selector__item-key",
1403
1404
  "aria-hidden": "true"
@@ -1478,7 +1479,7 @@ var AppTopBarPageSelectorInternal_default = /* @__PURE__ */ defineComponent({
1478
1479
  close();
1479
1480
  }
1480
1481
  return (_ctx, _cache) => {
1481
- return openBlock(), createElementBlock("div", _hoisted_1$6, [__props.pluginName ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createElementVNode("span", _hoisted_2$4, toDisplayString(__props.pluginName), 1), _cache[1] || (_cache[1] = createElementVNode("span", {
1482
+ return openBlock(), createElementBlock("div", _hoisted_1$8, [__props.pluginName ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createElementVNode("span", _hoisted_2$6, toDisplayString(__props.pluginName), 1), _cache[1] || (_cache[1] = createElementVNode("span", {
1482
1483
  class: "mint-page-selector__slash",
1483
1484
  "aria-hidden": "true"
1484
1485
  }, "/", -1))], 64)) : createCommentVNode("", true), createElementVNode("div", {
@@ -1502,9 +1503,9 @@ var AppTopBarPageSelectorInternal_default = /* @__PURE__ */ defineComponent({
1502
1503
  icon: current.value.icon,
1503
1504
  size: "sm",
1504
1505
  variant: "solid"
1505
- }, null, 8, ["icon"])) : (openBlock(), createElementBlock("span", _hoisted_4$4, toDisplayString(current.value.label.charAt(0)), 1))])], 2)) : createCommentVNode("", true),
1506
- createElementVNode("span", _hoisted_5$4, toDisplayString(current.value?.label ?? __props.placeholder), 1),
1507
- createElementVNode("span", _hoisted_6$3, [(openBlock(), createElementBlock("svg", {
1506
+ }, null, 8, ["icon"])) : (openBlock(), createElementBlock("span", _hoisted_4$6, toDisplayString(current.value.label.charAt(0)), 1))])], 2)) : createCommentVNode("", true),
1507
+ createElementVNode("span", _hoisted_5$6, toDisplayString(current.value?.label ?? __props.placeholder), 1),
1508
+ createElementVNode("span", _hoisted_6$5, [(openBlock(), createElementBlock("svg", {
1508
1509
  class: normalizeClass(["mint-page-selector__chevron", { "mint-page-selector__chevron--open": unref(isOpen) }]),
1509
1510
  viewBox: "0 0 24 24",
1510
1511
  fill: "none",
@@ -1513,14 +1514,14 @@ var AppTopBarPageSelectorInternal_default = /* @__PURE__ */ defineComponent({
1513
1514
  "stroke-linecap": "round",
1514
1515
  "stroke-linejoin": "round"
1515
1516
  }, [..._cache[2] || (_cache[2] = [createElementVNode("path", { d: "m6 9 6 6 6-6" }, null, -1)])], 2))])
1516
- ], 42, _hoisted_3$4), unref(isOpen) ? (openBlock(), createElementBlock("div", {
1517
+ ], 42, _hoisted_3$6), unref(isOpen) ? (openBlock(), createElementBlock("div", {
1517
1518
  key: 0,
1518
1519
  ref: "menu",
1519
1520
  class: "mint-page-selector__menu",
1520
1521
  role: "menu",
1521
1522
  "aria-label": menuTitle.value,
1522
1523
  onKeydown: handleMenuKeydown
1523
- }, [createElementVNode("div", _hoisted_8$3, toDisplayString(menuTitle.value), 1), (openBlock(true), createElementBlock(Fragment, null, renderList(normalizedPages.value, (page, index) => {
1524
+ }, [createElementVNode("div", _hoisted_8$5, toDisplayString(menuTitle.value), 1), (openBlock(true), createElementBlock(Fragment, null, renderList(normalizedPages.value, (page, index) => {
1524
1525
  return openBlock(), createBlock(ActionItemInternal_default, {
1525
1526
  key: page.id,
1526
1527
  href: page.href,
@@ -1543,9 +1544,9 @@ var AppTopBarPageSelectorInternal_default = /* @__PURE__ */ defineComponent({
1543
1544
  icon: page.icon,
1544
1545
  size: "sm",
1545
1546
  variant: "solid"
1546
- }, null, 8, ["icon"])) : (openBlock(), createElementBlock("span", _hoisted_9$3, toDisplayString(page.label.charAt(0)), 1))])], 2),
1547
- createElementVNode("span", _hoisted_10$3, [createElementVNode("span", _hoisted_11$3, toDisplayString(page.label), 1), page.hint ? (openBlock(), createElementBlock("span", _hoisted_12$3, toDisplayString(page.hint), 1)) : createCommentVNode("", true)]),
1548
- index < 9 ? (openBlock(), createElementBlock("span", _hoisted_13$3, toDisplayString(index + 1), 1)) : createCommentVNode("", true)
1547
+ }, null, 8, ["icon"])) : (openBlock(), createElementBlock("span", _hoisted_9$5, toDisplayString(page.label.charAt(0)), 1))])], 2),
1548
+ createElementVNode("span", _hoisted_10$5, [createElementVNode("span", _hoisted_11$5, toDisplayString(page.label), 1), page.hint ? (openBlock(), createElementBlock("span", _hoisted_12$4, toDisplayString(page.hint), 1)) : createCommentVNode("", true)]),
1549
+ index < 9 ? (openBlock(), createElementBlock("span", _hoisted_13$4, toDisplayString(index + 1), 1)) : createCommentVNode("", true)
1549
1550
  ]),
1550
1551
  _: 2
1551
1552
  }, 1032, [
@@ -1557,22 +1558,22 @@ var AppTopBarPageSelectorInternal_default = /* @__PURE__ */ defineComponent({
1557
1558
  "aria-keyshortcuts",
1558
1559
  "onClick"
1559
1560
  ]);
1560
- }), 128))], 40, _hoisted_7$3)) : createCommentVNode("", true)], 4)], 512);
1561
+ }), 128))], 40, _hoisted_7$5)) : createCommentVNode("", true)], 4)], 512);
1561
1562
  };
1562
1563
  }
1563
1564
  });
1564
1565
  //#endregion
1565
1566
  //#region src/components/internal/AppTopBarPillNavInternal.vue?vue&type=script&setup=true&lang.ts
1566
- var _hoisted_1$5 = {
1567
+ var _hoisted_1$7 = {
1567
1568
  class: "mint-pill-nav",
1568
1569
  "aria-label": "Primary"
1569
1570
  };
1570
- var _hoisted_2$3 = [
1571
+ var _hoisted_2$5 = [
1571
1572
  "disabled",
1572
1573
  "aria-expanded",
1573
1574
  "onClick"
1574
1575
  ];
1575
- var _hoisted_3$3 = {
1576
+ var _hoisted_3$5 = {
1576
1577
  key: 0,
1577
1578
  class: "mint-pill-nav__icon",
1578
1579
  viewBox: "0 0 24 24",
@@ -1583,15 +1584,15 @@ var _hoisted_3$3 = {
1583
1584
  "stroke-linejoin": "round",
1584
1585
  "aria-hidden": "true"
1585
1586
  };
1586
- var _hoisted_4$3 = ["d"];
1587
- var _hoisted_5$3 = ["d"];
1588
- var _hoisted_6$2 = {
1587
+ var _hoisted_4$5 = ["d"];
1588
+ var _hoisted_5$5 = ["d"];
1589
+ var _hoisted_6$4 = {
1589
1590
  key: 1,
1590
1591
  class: "mint-pill-nav__dot",
1591
1592
  role: "img",
1592
1593
  "aria-label": "Needs attention"
1593
1594
  };
1594
- var _hoisted_7$2 = {
1595
+ var _hoisted_7$4 = {
1595
1596
  key: 0,
1596
1597
  class: "mint-pill-nav__icon",
1597
1598
  viewBox: "0 0 24 24",
@@ -1602,21 +1603,21 @@ var _hoisted_7$2 = {
1602
1603
  "stroke-linejoin": "round",
1603
1604
  "aria-hidden": "true"
1604
1605
  };
1605
- var _hoisted_8$2 = ["d"];
1606
- var _hoisted_9$2 = ["d"];
1607
- var _hoisted_10$2 = {
1606
+ var _hoisted_8$4 = ["d"];
1607
+ var _hoisted_9$4 = ["d"];
1608
+ var _hoisted_10$4 = {
1608
1609
  key: 1,
1609
1610
  class: "mint-pill-nav__dot",
1610
1611
  role: "img",
1611
1612
  "aria-label": "Needs attention"
1612
1613
  };
1613
- var _hoisted_11$2 = {
1614
+ var _hoisted_11$4 = {
1614
1615
  key: 2,
1615
1616
  class: "mint-popover mint-pill-nav__dropdown",
1616
1617
  role: "menu"
1617
1618
  };
1618
- var _hoisted_12$2 = { class: "mint-pill-nav__dropdown-label" };
1619
- var _hoisted_13$2 = {
1619
+ var _hoisted_12$3 = { class: "mint-pill-nav__dropdown-label" };
1620
+ var _hoisted_13$3 = {
1620
1621
  key: 0,
1621
1622
  class: "mint-pill-nav__dropdown-description"
1622
1623
  };
@@ -1699,7 +1700,7 @@ var AppTopBarPillNavInternal_default = /* @__PURE__ */ defineComponent({
1699
1700
  }
1700
1701
  useEventListener(() => document, "click", handleClickOutside);
1701
1702
  return (_ctx, _cache) => {
1702
- return openBlock(), createElementBlock("nav", _hoisted_1$5, [(openBlock(true), createElementBlock(Fragment, null, renderList(normalizedItems.value, (item) => {
1703
+ return openBlock(), createElementBlock("nav", _hoisted_1$7, [(openBlock(true), createElementBlock(Fragment, null, renderList(normalizedItems.value, (item) => {
1703
1704
  return openBlock(), createElementBlock("div", {
1704
1705
  key: item.id,
1705
1706
  ref_for: true,
@@ -1718,17 +1719,17 @@ var AppTopBarPillNavInternal_default = /* @__PURE__ */ defineComponent({
1718
1719
  "aria-haspopup": "menu",
1719
1720
  onClick: withModifiers(($event) => handleClick(item), ["stop"])
1720
1721
  }, [
1721
- isSvgIcon(item.icon) ? (openBlock(), createElementBlock("svg", _hoisted_3$3, [Array.isArray(item.icon) ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(item.icon, (d, index) => {
1722
+ isSvgIcon(item.icon) ? (openBlock(), createElementBlock("svg", _hoisted_3$5, [Array.isArray(item.icon) ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(item.icon, (d, index) => {
1722
1723
  return openBlock(), createElementBlock("path", {
1723
1724
  key: index,
1724
1725
  d
1725
- }, null, 8, _hoisted_4$3);
1726
+ }, null, 8, _hoisted_4$5);
1726
1727
  }), 128)) : (openBlock(), createElementBlock("path", {
1727
1728
  key: 1,
1728
1729
  d: item.icon
1729
- }, null, 8, _hoisted_5$3))])) : createCommentVNode("", true),
1730
+ }, null, 8, _hoisted_5$5))])) : createCommentVNode("", true),
1730
1731
  createTextVNode(" " + toDisplayString(activeChild(item)?.label ?? item.label) + " ", 1),
1731
- item.dot ? (openBlock(), createElementBlock("span", _hoisted_6$2)) : createCommentVNode("", true),
1732
+ item.dot ? (openBlock(), createElementBlock("span", _hoisted_6$4)) : createCommentVNode("", true),
1732
1733
  (openBlock(), createElementBlock("svg", {
1733
1734
  class: normalizeClass(["mint-pill-nav__chevron", { "mint-pill-nav__chevron--open": openItemId.value === item.id }]),
1734
1735
  viewBox: "0 0 24 24",
@@ -1739,7 +1740,7 @@ var AppTopBarPillNavInternal_default = /* @__PURE__ */ defineComponent({
1739
1740
  "stroke-linejoin": "round",
1740
1741
  "aria-hidden": "true"
1741
1742
  }, [..._cache[0] || (_cache[0] = [createElementVNode("path", { d: "m6 9 6 6 6-6" }, null, -1)])], 2))
1742
- ], 10, _hoisted_2$3)) : (openBlock(), createBlock(ActionItemInternal_default, {
1743
+ ], 10, _hoisted_2$5)) : (openBlock(), createBlock(ActionItemInternal_default, {
1743
1744
  key: 1,
1744
1745
  href: item.href,
1745
1746
  to: item.to,
@@ -1752,17 +1753,17 @@ var AppTopBarPillNavInternal_default = /* @__PURE__ */ defineComponent({
1752
1753
  onClick: ($event) => handleClick(item)
1753
1754
  }, {
1754
1755
  default: withCtx(() => [
1755
- isSvgIcon(item.icon) ? (openBlock(), createElementBlock("svg", _hoisted_7$2, [Array.isArray(item.icon) ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(item.icon, (d, index) => {
1756
+ isSvgIcon(item.icon) ? (openBlock(), createElementBlock("svg", _hoisted_7$4, [Array.isArray(item.icon) ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(item.icon, (d, index) => {
1756
1757
  return openBlock(), createElementBlock("path", {
1757
1758
  key: index,
1758
1759
  d
1759
- }, null, 8, _hoisted_8$2);
1760
+ }, null, 8, _hoisted_8$4);
1760
1761
  }), 128)) : (openBlock(), createElementBlock("path", {
1761
1762
  key: 1,
1762
1763
  d: item.icon
1763
- }, null, 8, _hoisted_9$2))])) : createCommentVNode("", true),
1764
+ }, null, 8, _hoisted_9$4))])) : createCommentVNode("", true),
1764
1765
  createTextVNode(" " + toDisplayString(item.label) + " ", 1),
1765
- item.dot ? (openBlock(), createElementBlock("span", _hoisted_10$2)) : createCommentVNode("", true)
1766
+ item.dot ? (openBlock(), createElementBlock("span", _hoisted_10$4)) : createCommentVNode("", true)
1766
1767
  ]),
1767
1768
  _: 2
1768
1769
  }, 1032, [
@@ -1771,7 +1772,7 @@ var AppTopBarPillNavInternal_default = /* @__PURE__ */ defineComponent({
1771
1772
  "disabled",
1772
1773
  "class",
1773
1774
  "onClick"
1774
- ])), item.children?.length && openItemId.value === item.id ? (openBlock(), createElementBlock("div", _hoisted_11$2, [(openBlock(true), createElementBlock(Fragment, null, renderList(item.children, (option) => {
1775
+ ])), item.children?.length && openItemId.value === item.id ? (openBlock(), createElementBlock("div", _hoisted_11$4, [(openBlock(true), createElementBlock(Fragment, null, renderList(item.children, (option) => {
1775
1776
  return openBlock(), createBlock(ActionItemInternal_default, {
1776
1777
  key: option.id,
1777
1778
  href: option.href,
@@ -1786,8 +1787,8 @@ var AppTopBarPillNavInternal_default = /* @__PURE__ */ defineComponent({
1786
1787
  onClick: ($event) => handleOptionClick(option, item)
1787
1788
  }, {
1788
1789
  default: withCtx(() => [
1789
- createElementVNode("span", _hoisted_12$2, toDisplayString(option.label), 1),
1790
- option.description ? (openBlock(), createElementBlock("span", _hoisted_13$2, toDisplayString(option.description), 1)) : createCommentVNode("", true),
1790
+ createElementVNode("span", _hoisted_12$3, toDisplayString(option.label), 1),
1791
+ option.description ? (openBlock(), createElementBlock("span", _hoisted_13$3, toDisplayString(option.description), 1)) : createCommentVNode("", true),
1791
1792
  _cache[1] || (_cache[1] = createElementVNode("svg", {
1792
1793
  class: "mint-menu-item__check",
1793
1794
  viewBox: "0 0 16 16",
@@ -1813,6 +1814,757 @@ var AppTopBarPillNavInternal_default = /* @__PURE__ */ defineComponent({
1813
1814
  }
1814
1815
  });
1815
1816
  //#endregion
1817
+ //#region src/components/internal/OnboardingLayerInternal.vue?vue&type=script&setup=true&lang.ts
1818
+ var _hoisted_1$6 = ["aria-label", "onClick"];
1819
+ var _hoisted_2$4 = {
1820
+ key: 0,
1821
+ class: "mint-onboarding"
1822
+ };
1823
+ var _hoisted_3$4 = ["aria-labelledby"];
1824
+ var _hoisted_4$4 = ["aria-label"];
1825
+ var _hoisted_5$4 = {
1826
+ key: 0,
1827
+ class: "mint-onboarding__count"
1828
+ };
1829
+ var _hoisted_6$3 = { "aria-hidden": "true" };
1830
+ var _hoisted_7$3 = { class: "mint-onboarding__sr" };
1831
+ var _hoisted_8$3 = ["id"];
1832
+ var _hoisted_9$3 = { class: "mint-onboarding__body" };
1833
+ var _hoisted_10$3 = { class: "mint-onboarding__footer" };
1834
+ var _hoisted_11$3 = {
1835
+ key: 0,
1836
+ class: "mint-onboarding__hint"
1837
+ };
1838
+ var HOLE_PAD = 4;
1839
+ //#endregion
1840
+ //#region src/components/internal/OnboardingLayerInternal.vue
1841
+ var OnboardingLayerInternal_default = /* @__PURE__ */ defineComponent({
1842
+ __name: "OnboardingLayerInternal",
1843
+ props: { state: {} },
1844
+ setup(__props) {
1845
+ /**
1846
+ * The tour layer: a scrim with a hole over the anchor, the step card, and the
1847
+ * what's-new dots. AppTopBar renders it when the app provides onboarding.
1848
+ */
1849
+ const props = __props;
1850
+ const active = computed(() => props.state.active.value);
1851
+ const card = ref(null);
1852
+ const hole = ref(null);
1853
+ const cardPosition = ref({
1854
+ x: 0,
1855
+ y: 0
1856
+ });
1857
+ const titleId = useId();
1858
+ let stopAutoUpdate;
1859
+ async function position() {
1860
+ const current = active.value;
1861
+ if (!current || !card.value) return;
1862
+ hole.value = current.element.getBoundingClientRect();
1863
+ const { x, y } = await computePosition(current.element, card.value, {
1864
+ strategy: "fixed",
1865
+ placement: current.step.placement ?? "bottom",
1866
+ middleware: [
1867
+ offset(12),
1868
+ flip(),
1869
+ shift({ padding: 12 })
1870
+ ]
1871
+ });
1872
+ if (active.value === current) cardPosition.value = {
1873
+ x,
1874
+ y
1875
+ };
1876
+ }
1877
+ let returnFocus = null;
1878
+ watch(active, async (current, previous) => {
1879
+ stopAutoUpdate?.();
1880
+ stopAutoUpdate = void 0;
1881
+ hole.value = null;
1882
+ if (current && !previous) returnFocus = document.activeElement;
1883
+ if (!current) {
1884
+ if (returnFocus?.isConnected) returnFocus.focus();
1885
+ returnFocus = null;
1886
+ return;
1887
+ }
1888
+ await nextTick();
1889
+ if (!card.value || active.value !== current) return;
1890
+ current.element.scrollIntoView({
1891
+ block: "nearest",
1892
+ inline: "nearest"
1893
+ });
1894
+ stopAutoUpdate = autoUpdate(current.element, card.value, () => void position());
1895
+ if (current.step.advanceOn === "click") current.element.focus();
1896
+ else card.value.focus();
1897
+ }, { immediate: true });
1898
+ onBeforeUnmount(() => stopAutoUpdate?.());
1899
+ useEventListener(document, "keydown", (event) => {
1900
+ const current = active.value;
1901
+ if (!current || !card.value) return;
1902
+ const focused = document.activeElement;
1903
+ if (focused && focused !== document.body && !card.value.contains(focused) && focused !== current.element) return;
1904
+ const onCard = focused === card.value;
1905
+ if (event.key === "Escape") {
1906
+ event.stopPropagation();
1907
+ props.state.dismiss();
1908
+ } else if (event.key === "Tab") {
1909
+ const buttons = [...card.value.querySelectorAll("button")];
1910
+ const stops = current.step.advanceOn === "click" ? [current.element, ...buttons] : buttons;
1911
+ const at = stops.indexOf(document.activeElement);
1912
+ const target = at === -1 ? event.shiftKey ? stops.length - 1 : 0 : (at + (event.shiftKey ? -1 : 1) + stops.length) % stops.length;
1913
+ event.preventDefault();
1914
+ stops[target].focus();
1915
+ } else if (event.key === "Enter" && onCard && current.step.advanceOn !== "click") {
1916
+ event.preventDefault();
1917
+ props.state.next();
1918
+ }
1919
+ }, { capture: true });
1920
+ const holeStyle = computed(() => hole.value && {
1921
+ left: `${hole.value.left - HOLE_PAD}px`,
1922
+ top: `${hole.value.top - HOLE_PAD}px`,
1923
+ width: `${hole.value.width + 8}px`,
1924
+ height: `${hole.value.height + 8}px`
1925
+ });
1926
+ const blockerStyle = computed(() => {
1927
+ const rect = hole.value;
1928
+ if (!rect || active.value?.step.advanceOn !== "click") return void 0;
1929
+ const [x, y, w, h] = [
1930
+ rect.left - HOLE_PAD,
1931
+ rect.top - HOLE_PAD,
1932
+ rect.width + 8,
1933
+ rect.height + 8
1934
+ ];
1935
+ return { clipPath: `path(evenodd, 'M0 0H${window.innerWidth}V${window.innerHeight}H0Z M${x} ${y}h${w}v${h}h${-w}Z')` };
1936
+ });
1937
+ const isLast = computed(() => !!active.value && active.value.index === active.value.count - 1);
1938
+ const nextLabel = computed(() => active.value?.news ? "Got it" : isLast.value ? "Done" : "Next");
1939
+ const dots = ref([]);
1940
+ let frame = 0;
1941
+ function placeDots() {
1942
+ cancelAnimationFrame(frame);
1943
+ frame = requestAnimationFrame(() => {
1944
+ dots.value = active.value ? [] : props.state.news.value.flatMap((item) => {
1945
+ if (!item.unseen) return [];
1946
+ const element = document.querySelector(`[data-onboarding="${CSS.escape(item.anchor)}"]`);
1947
+ if (!element) return [];
1948
+ const rect = element.getBoundingClientRect();
1949
+ return rect.width ? [{
1950
+ id: item.id,
1951
+ title: item.title,
1952
+ x: rect.right,
1953
+ y: rect.top
1954
+ }] : [];
1955
+ });
1956
+ });
1957
+ }
1958
+ const observer = new MutationObserver(placeDots);
1959
+ watch(() => props.state.unseenNews.value > 0, (watching) => {
1960
+ observer.disconnect();
1961
+ if (watching) observer.observe(document.body, {
1962
+ childList: true,
1963
+ subtree: true
1964
+ });
1965
+ placeDots();
1966
+ }, { immediate: true });
1967
+ watch(active, placeDots);
1968
+ useEventListener(window, "resize", placeDots);
1969
+ useEventListener(window, "scroll", placeDots, {
1970
+ capture: true,
1971
+ passive: true
1972
+ });
1973
+ onBeforeUnmount(() => {
1974
+ observer.disconnect();
1975
+ cancelAnimationFrame(frame);
1976
+ });
1977
+ return (_ctx, _cache) => {
1978
+ return openBlock(), createBlock(Teleport, { to: "body" }, [(openBlock(true), createElementBlock(Fragment, null, renderList(dots.value, (dot) => {
1979
+ return openBlock(), createElementBlock("button", {
1980
+ key: dot.id,
1981
+ type: "button",
1982
+ class: "mint-onboarding__dot",
1983
+ style: normalizeStyle({
1984
+ left: `${dot.x}px`,
1985
+ top: `${dot.y}px`
1986
+ }),
1987
+ "aria-label": `New: ${dot.title}`,
1988
+ onClick: ($event) => __props.state.showNews(dot.id)
1989
+ }, null, 12, _hoisted_1$6);
1990
+ }), 128)), active.value ? (openBlock(), createElementBlock("div", _hoisted_2$4, [
1991
+ createElementVNode("div", {
1992
+ class: "mint-onboarding__blocker",
1993
+ style: normalizeStyle(blockerStyle.value)
1994
+ }, null, 4),
1995
+ holeStyle.value ? (openBlock(), createElementBlock("div", {
1996
+ key: 0,
1997
+ class: "mint-onboarding__hole",
1998
+ style: normalizeStyle(holeStyle.value)
1999
+ }, null, 4)) : createCommentVNode("", true),
2000
+ createElementVNode("div", {
2001
+ ref_key: "card",
2002
+ ref: card,
2003
+ class: "mint-onboarding__card",
2004
+ role: "dialog",
2005
+ "aria-modal": "true",
2006
+ "aria-labelledby": unref(titleId),
2007
+ tabindex: "-1",
2008
+ style: normalizeStyle({
2009
+ left: `${cardPosition.value.x}px`,
2010
+ top: `${cardPosition.value.y}px`
2011
+ })
2012
+ }, [
2013
+ createElementVNode("button", {
2014
+ type: "button",
2015
+ class: "mint-onboarding__close",
2016
+ "aria-label": active.value.news ? "Close" : "Close tour",
2017
+ onClick: _cache[0] || (_cache[0] = ($event) => __props.state.dismiss())
2018
+ }, [createVNode(unref(X), {
2019
+ size: 14,
2020
+ "aria-hidden": "true"
2021
+ })], 8, _hoisted_4$4),
2022
+ active.value.count > 1 ? (openBlock(), createElementBlock("span", _hoisted_5$4, [createElementVNode("span", _hoisted_6$3, toDisplayString(active.value.index + 1) + " / " + toDisplayString(active.value.count), 1), createElementVNode("span", _hoisted_7$3, "Step " + toDisplayString(active.value.index + 1) + " of " + toDisplayString(active.value.count), 1)])) : createCommentVNode("", true),
2023
+ createElementVNode("p", {
2024
+ id: unref(titleId),
2025
+ class: "mint-onboarding__title"
2026
+ }, toDisplayString(active.value.step.title), 9, _hoisted_8$3),
2027
+ createElementVNode("p", _hoisted_9$3, toDisplayString(active.value.step.body), 1),
2028
+ createElementVNode("div", _hoisted_10$3, [
2029
+ active.value.step.advanceOn === "click" ? (openBlock(), createElementBlock("span", _hoisted_11$3, "Click the highlighted control.")) : createCommentVNode("", true),
2030
+ active.value.index > 0 ? (openBlock(), createBlock(BaseButton_default, {
2031
+ key: 1,
2032
+ variant: "ghost",
2033
+ size: "sm",
2034
+ onClick: _cache[1] || (_cache[1] = ($event) => __props.state.back())
2035
+ }, {
2036
+ default: withCtx(() => [..._cache[3] || (_cache[3] = [createTextVNode("Back", -1)])]),
2037
+ _: 1
2038
+ })) : createCommentVNode("", true),
2039
+ active.value.step.advanceOn !== "click" ? (openBlock(), createBlock(BaseButton_default, {
2040
+ key: 2,
2041
+ size: "sm",
2042
+ onClick: _cache[2] || (_cache[2] = ($event) => __props.state.next())
2043
+ }, {
2044
+ default: withCtx(() => [createTextVNode(toDisplayString(nextLabel.value), 1)]),
2045
+ _: 1
2046
+ })) : createCommentVNode("", true)
2047
+ ])
2048
+ ], 12, _hoisted_3$4)
2049
+ ])) : createCommentVNode("", true)]);
2050
+ };
2051
+ }
2052
+ });
2053
+ //#endregion
2054
+ //#region src/components/internal/AppTopBarOnboardingInternal.vue?vue&type=script&setup=true&lang.ts
2055
+ var _hoisted_1$5 = ["aria-expanded"];
2056
+ var _hoisted_2$3 = { class: "mint-onboarding-help__count" };
2057
+ var _hoisted_3$3 = {
2058
+ class: "mint-onboarding-help__bar",
2059
+ "aria-hidden": "true"
2060
+ };
2061
+ var _hoisted_4$3 = ["aria-label", "aria-expanded"];
2062
+ var _hoisted_5$3 = {
2063
+ key: 0,
2064
+ class: "mint-onboarding-help__badge",
2065
+ "aria-hidden": "true"
2066
+ };
2067
+ var _hoisted_6$2 = { class: "mint-onboarding-help__header" };
2068
+ var _hoisted_7$2 = { class: "mint-onboarding-help__count" };
2069
+ var _hoisted_8$2 = {
2070
+ class: "mint-onboarding-help__progress",
2071
+ "aria-hidden": "true"
2072
+ };
2073
+ var _hoisted_9$2 = { class: "mint-onboarding-help__todos" };
2074
+ var _hoisted_10$2 = ["aria-label"];
2075
+ var _hoisted_11$2 = { class: "mint-onboarding-help__todo-title" };
2076
+ var _hoisted_12$2 = ["onClick"];
2077
+ var _hoisted_13$2 = ["onClick"];
2078
+ var _hoisted_14$2 = ["onClick"];
2079
+ var _hoisted_15$2 = {
2080
+ key: 0,
2081
+ class: "mint-onboarding-help__new"
2082
+ };
2083
+ //#endregion
2084
+ //#region src/components/internal/AppTopBarOnboardingInternal.vue
2085
+ var AppTopBarOnboardingInternal_default = /* @__PURE__ */ defineComponent({
2086
+ __name: "AppTopBarOnboardingInternal",
2087
+ props: { state: {} },
2088
+ setup(__props) {
2089
+ /**
2090
+ * The top-bar onboarding controls: the "Getting started n/m" chip while the
2091
+ * checklist is open, and the Help button with the checklist, tours and news.
2092
+ */
2093
+ const props = __props;
2094
+ const root = ref(null);
2095
+ const helpButton = ref(null);
2096
+ const panel = ref(null);
2097
+ const panelPosition = ref({
2098
+ x: 0,
2099
+ y: 0
2100
+ });
2101
+ const open = ref(false);
2102
+ const hasContent = computed(() => props.state.tasks.value.length > 0 || props.state.tours.value.length > 0 || props.state.news.value.length > 0);
2103
+ const progress = computed(() => {
2104
+ const total = props.state.tasks.value.length;
2105
+ return total ? Math.round(props.state.tasksDone.value / total * 100) : 0;
2106
+ });
2107
+ function toggle() {
2108
+ open.value = !open.value;
2109
+ if (open.value) props.state.refresh();
2110
+ }
2111
+ let stopAutoUpdate;
2112
+ watch(open, async (isOpen) => {
2113
+ stopAutoUpdate?.();
2114
+ stopAutoUpdate = void 0;
2115
+ if (!isOpen) return;
2116
+ await nextTick();
2117
+ const button = helpButton.value;
2118
+ const floating = panel.value;
2119
+ if (!button || !floating || !open.value) return;
2120
+ stopAutoUpdate = autoUpdate(button, floating, async () => {
2121
+ const { x, y } = await computePosition(button, floating, {
2122
+ strategy: "fixed",
2123
+ placement: "bottom-end",
2124
+ middleware: [offset(8), shift({ padding: 8 })]
2125
+ });
2126
+ panelPosition.value = {
2127
+ x,
2128
+ y
2129
+ };
2130
+ });
2131
+ });
2132
+ onBeforeUnmount(() => stopAutoUpdate?.());
2133
+ function run(action) {
2134
+ open.value = false;
2135
+ action();
2136
+ }
2137
+ useEventListener(document, "pointerdown", (event) => {
2138
+ const target = event.target;
2139
+ if (open.value && !root.value?.contains(target) && !panel.value?.contains(target)) open.value = false;
2140
+ });
2141
+ useEventListener(document, "keydown", (event) => {
2142
+ if (open.value && event.key === "Escape") open.value = false;
2143
+ });
2144
+ return (_ctx, _cache) => {
2145
+ return openBlock(), createElementBlock(Fragment, null, [hasContent.value ? (openBlock(), createElementBlock("div", {
2146
+ key: 0,
2147
+ ref_key: "root",
2148
+ ref: root,
2149
+ class: "mint-onboarding-help"
2150
+ }, [
2151
+ __props.state.checklistVisible.value ? (openBlock(), createElementBlock("button", {
2152
+ key: 0,
2153
+ type: "button",
2154
+ class: normalizeClass(["mint-onboarding-help__chip", { "mint-onboarding-help__chip--open": open.value }]),
2155
+ "data-onboarding": "topbar-checklist",
2156
+ "aria-expanded": open.value,
2157
+ onClick: toggle
2158
+ }, [
2159
+ _cache[1] || (_cache[1] = createTextVNode(" Getting started ", -1)),
2160
+ createElementVNode("span", _hoisted_2$3, toDisplayString(__props.state.tasksDone.value) + "/" + toDisplayString(__props.state.tasks.value.length), 1),
2161
+ createElementVNode("span", _hoisted_3$3, [createElementVNode("span", { style: normalizeStyle({ width: `${progress.value}%` }) }, null, 4)])
2162
+ ], 10, _hoisted_1$5)) : createCommentVNode("", true),
2163
+ createElementVNode("button", {
2164
+ ref_key: "helpButton",
2165
+ ref: helpButton,
2166
+ type: "button",
2167
+ class: normalizeClass(["mint-topbar__settings-btn", { "mint-topbar__settings-btn--open": open.value }]),
2168
+ "data-onboarding": "topbar-help",
2169
+ "aria-label": __props.state.unseenNews.value ? `Help, ${__props.state.unseenNews.value} new` : "Help",
2170
+ "aria-expanded": open.value,
2171
+ onClick: toggle
2172
+ }, [createVNode(unref(CircleHelp), {
2173
+ class: "mint-topbar__settings-icon",
2174
+ "aria-hidden": "true"
2175
+ }), __props.state.unseenNews.value ? (openBlock(), createElementBlock("span", _hoisted_5$3, toDisplayString(__props.state.unseenNews.value), 1)) : createCommentVNode("", true)], 10, _hoisted_4$3),
2176
+ (openBlock(), createBlock(Teleport, { to: "body" }, [open.value ? (openBlock(), createElementBlock("div", {
2177
+ key: 0,
2178
+ ref_key: "panel",
2179
+ ref: panel,
2180
+ class: "mint-popover mint-onboarding-help__panel",
2181
+ role: "dialog",
2182
+ "aria-label": "Help",
2183
+ style: normalizeStyle({
2184
+ left: `${panelPosition.value.x}px`,
2185
+ top: `${panelPosition.value.y}px`
2186
+ })
2187
+ }, [
2188
+ __props.state.tasks.value.length ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
2189
+ createElementVNode("div", _hoisted_6$2, [_cache[2] || (_cache[2] = createElementVNode("span", { class: "mint-onboarding-help__heading" }, "Getting started", -1)), createElementVNode("span", _hoisted_7$2, toDisplayString(__props.state.tasksDone.value) + "/" + toDisplayString(__props.state.tasks.value.length), 1)]),
2190
+ createElementVNode("div", _hoisted_8$2, [createElementVNode("span", { style: normalizeStyle({ width: `${progress.value}%` }) }, null, 4)]),
2191
+ createElementVNode("ul", _hoisted_9$2, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.state.tasks.value, (task) => {
2192
+ return openBlock(), createElementBlock("li", {
2193
+ key: task.id,
2194
+ class: normalizeClass(["mint-onboarding-help__todo", { "mint-onboarding-help__todo--done": task.done }])
2195
+ }, [
2196
+ createElementVNode("span", {
2197
+ class: "mint-onboarding-help__check",
2198
+ role: "img",
2199
+ "aria-label": task.done ? "Done" : "Not done"
2200
+ }, [task.done ? (openBlock(), createBlock(unref(Check), {
2201
+ key: 0,
2202
+ size: 10,
2203
+ "stroke-width": 3,
2204
+ "aria-hidden": "true"
2205
+ })) : createCommentVNode("", true)], 8, _hoisted_10$2),
2206
+ createElementVNode("span", _hoisted_11$2, toDisplayString(task.title), 1),
2207
+ task.action && !task.done ? (openBlock(), createElementBlock("button", {
2208
+ key: 0,
2209
+ type: "button",
2210
+ class: "mint-onboarding-help__link",
2211
+ onClick: ($event) => run(task.action.run)
2212
+ }, toDisplayString(task.action.label), 9, _hoisted_12$2)) : createCommentVNode("", true)
2213
+ ], 2);
2214
+ }), 128))]),
2215
+ __props.state.tasksDone.value < __props.state.tasks.value.length ? (openBlock(), createElementBlock("button", {
2216
+ key: 0,
2217
+ type: "button",
2218
+ class: "mint-onboarding-help__link mint-onboarding-help__hide",
2219
+ onClick: _cache[0] || (_cache[0] = ($event) => __props.state.setChecklistHidden(!__props.state.checklistHidden.value))
2220
+ }, toDisplayString(__props.state.checklistHidden.value ? "Show checklist in the top bar" : "Hide checklist from the top bar"), 1)) : createCommentVNode("", true)
2221
+ ], 64)) : createCommentVNode("", true),
2222
+ __props.state.tours.value.length ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [_cache[3] || (_cache[3] = createElementVNode("div", { class: "mint-onboarding-help__section" }, "Tours", -1)), (openBlock(true), createElementBlock(Fragment, null, renderList(__props.state.tours.value, (tour) => {
2223
+ return openBlock(), createElementBlock("button", {
2224
+ key: tour.id,
2225
+ type: "button",
2226
+ class: "mint-menu-item",
2227
+ onClick: ($event) => run(() => __props.state.startTour(tour.id))
2228
+ }, [createVNode(unref(Play), {
2229
+ class: "mint-onboarding-help__icon",
2230
+ "aria-hidden": "true"
2231
+ }), createTextVNode(" " + toDisplayString(tour.title), 1)], 8, _hoisted_13$2);
2232
+ }), 128))], 64)) : createCommentVNode("", true),
2233
+ __props.state.news.value.length ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [_cache[4] || (_cache[4] = createElementVNode("div", { class: "mint-onboarding-help__section" }, "What's new", -1)), (openBlock(true), createElementBlock(Fragment, null, renderList(__props.state.news.value, (item) => {
2234
+ return openBlock(), createElementBlock("button", {
2235
+ key: item.id,
2236
+ type: "button",
2237
+ class: "mint-menu-item",
2238
+ onClick: ($event) => run(() => __props.state.showNews(item.id))
2239
+ }, [createTextVNode(toDisplayString(item.title) + " ", 1), item.unseen ? (openBlock(), createElementBlock("span", _hoisted_15$2, "New")) : createCommentVNode("", true)], 8, _hoisted_14$2);
2240
+ }), 128))], 64)) : createCommentVNode("", true)
2241
+ ], 4)) : createCommentVNode("", true)]))
2242
+ ], 512)) : createCommentVNode("", true), createVNode(OnboardingLayerInternal_default, { state: __props.state }, null, 8, ["state"])], 64);
2243
+ };
2244
+ }
2245
+ });
2246
+ //#endregion
2247
+ //#region src/composables/useOnboarding.ts
2248
+ var ONBOARDING_KEY = Symbol("mint-onboarding");
2249
+ /** Wait this long for the missing anchor of a run's first step, or of the step after a click step; then skip it. */
2250
+ var ANCHOR_WAIT_MS = 2e3;
2251
+ var HIDE_CHECKLIST = "hide:checklist";
2252
+ var stepKey = (tour, step) => `step:${tour.id}/${step.id}`;
2253
+ var anchorSelector = (anchor) => `[data-onboarding="${CSS.escape(anchor)}"]`;
2254
+ /** Types a definition, so it can live in its own file. */
2255
+ function defineOnboarding(definition) {
2256
+ return definition;
2257
+ }
2258
+ function readSeen(key) {
2259
+ try {
2260
+ const raw = globalThis.localStorage?.getItem(key);
2261
+ const parsed = raw ? JSON.parse(raw) : null;
2262
+ return Array.isArray(parsed) ? parsed.filter((item) => typeof item === "string") : null;
2263
+ } catch {
2264
+ return null;
2265
+ }
2266
+ }
2267
+ function writeSeen(key, seen) {
2268
+ try {
2269
+ globalThis.localStorage?.setItem(key, JSON.stringify([...seen]));
2270
+ } catch {}
2271
+ }
2272
+ /** Resolves with the element once it is in the document, or null after `timeout` or when `signal` aborts. */
2273
+ function waitForElement(selector, timeout, signal) {
2274
+ const found = document.querySelector(selector);
2275
+ if (found) return Promise.resolve(found);
2276
+ return new Promise((resolve) => {
2277
+ const observer = new MutationObserver(() => {
2278
+ const element = document.querySelector(selector);
2279
+ if (element) finish(element);
2280
+ });
2281
+ const timer = setTimeout(() => finish(null), timeout);
2282
+ const onAbort = () => finish(null);
2283
+ function finish(element) {
2284
+ observer.disconnect();
2285
+ clearTimeout(timer);
2286
+ signal.removeEventListener("abort", onAbort);
2287
+ resolve(element);
2288
+ }
2289
+ signal.addEventListener("abort", onAbort);
2290
+ observer.observe(document.body, {
2291
+ childList: true,
2292
+ subtree: true,
2293
+ attributes: true,
2294
+ attributeFilter: ["data-onboarding"]
2295
+ });
2296
+ });
2297
+ }
2298
+ var MODAL_SELECTOR = "[aria-modal=\"true\"]:not(.mint-onboarding__card)";
2299
+ /** Resolves true once no modal is open, or false when `signal` aborts first. */
2300
+ function waitForNoModal(signal) {
2301
+ if (!document.querySelector(MODAL_SELECTOR)) return Promise.resolve(true);
2302
+ return new Promise((resolve) => {
2303
+ const observer = new MutationObserver(() => {
2304
+ if (!document.querySelector(MODAL_SELECTOR)) finish(true);
2305
+ });
2306
+ const onAbort = () => finish(false);
2307
+ function finish(closed) {
2308
+ observer.disconnect();
2309
+ signal.removeEventListener("abort", onAbort);
2310
+ resolve(closed);
2311
+ }
2312
+ signal.addEventListener("abort", onAbort);
2313
+ observer.observe(document.body, {
2314
+ childList: true,
2315
+ subtree: true,
2316
+ attributes: true,
2317
+ attributeFilter: ["aria-modal"]
2318
+ });
2319
+ });
2320
+ }
2321
+ /**
2322
+ * Creates the app's onboarding coordinator and provides it to `AppTopBar`, which then
2323
+ * shows the Help button, the checklist chip and the tour layer. Call it once, in the
2324
+ * root component. It shows one item at a time and waits for open modals.
2325
+ *
2326
+ * ```ts
2327
+ * provideOnboarding(onboarding, { appId: 'leaf' })
2328
+ * ```
2329
+ */
2330
+ function provideOnboarding(definition, options) {
2331
+ const { user, isAdmin } = usePlatform();
2332
+ const userId = computed(() => {
2333
+ const fallback = isAdmin.value ? "local" : null;
2334
+ const value = options.userId === void 0 ? user.value?.id ?? fallback : toValue(options.userId);
2335
+ return value == null ? null : String(value);
2336
+ });
2337
+ const route = computed(() => toValue(options.route) ?? void 0);
2338
+ const storageKey = computed(() => userId.value === null ? null : `mint.onboarding.${options.appId}.${userId.value}`);
2339
+ const enabled = computed(() => storageKey.value !== null);
2340
+ const seen = ref(/* @__PURE__ */ new Set());
2341
+ const tick = ref(0);
2342
+ const active = shallowRef(null);
2343
+ let run = null;
2344
+ let runId = 0;
2345
+ let stepWait;
2346
+ let detachClick;
2347
+ /** Applies `update` to the stored state merged with this tab's, so tabs do not drop each other's keys. */
2348
+ function persist(update) {
2349
+ const key = storageKey.value;
2350
+ if (!key) return;
2351
+ const merged = /* @__PURE__ */ new Set([...readSeen(key) ?? [], ...seen.value]);
2352
+ update(merged);
2353
+ seen.value = merged;
2354
+ writeSeen(key, merged);
2355
+ }
2356
+ function markSeen(...keys) {
2357
+ if (keys.every((key) => seen.value.has(key))) return;
2358
+ persist((set) => keys.forEach((key) => set.add(key)));
2359
+ }
2360
+ function onStorage(event) {
2361
+ if (event.key && event.key === storageKey.value) seen.value = new Set(readSeen(event.key) ?? []);
2362
+ }
2363
+ window.addEventListener("storage", onStorage);
2364
+ watch(storageKey, (key) => {
2365
+ stop();
2366
+ if (!key) {
2367
+ seen.value = /* @__PURE__ */ new Set();
2368
+ return;
2369
+ }
2370
+ const stored = readSeen(key);
2371
+ seen.value = new Set(stored ?? []);
2372
+ if (stored === null) {
2373
+ for (const item of definition.whatsNew ?? []) seen.value.add(`news:${item.id}`);
2374
+ writeSeen(key, seen.value);
2375
+ }
2376
+ }, { immediate: true });
2377
+ const tours = computed(() => (definition.tours ?? []).filter((tour) => !tour.route || tour.route === route.value));
2378
+ const tasks = computed(() => {
2379
+ tick.value;
2380
+ return (definition.checklist ?? []).filter((task) => task.available?.() ?? true).map((task) => ({
2381
+ ...task,
2382
+ done: seen.value.has(`task:${task.id}`) || !!task.done?.()
2383
+ }));
2384
+ });
2385
+ watch(tasks, (list) => markSeen(...list.filter((task) => task.done).map((task) => `task:${task.id}`)), { immediate: true });
2386
+ const tasksDone = computed(() => tasks.value.filter((task) => task.done).length);
2387
+ const checklistHidden = computed(() => seen.value.has(HIDE_CHECKLIST));
2388
+ const checklistVisible = computed(() => enabled.value && tasks.value.length > 0 && tasksDone.value < tasks.value.length && !checklistHidden.value);
2389
+ const news = computed(() => (definition.whatsNew ?? []).map((item) => ({
2390
+ ...item,
2391
+ unseen: !seen.value.has(`news:${item.id}`)
2392
+ })));
2393
+ const unseenNews = computed(() => enabled.value ? news.value.filter((item) => item.unseen).length : 0);
2394
+ function stop() {
2395
+ runId += 1;
2396
+ stepWait?.abort();
2397
+ run = null;
2398
+ detachClick?.();
2399
+ detachClick = void 0;
2400
+ active.value = null;
2401
+ }
2402
+ /**
2403
+ * Shows the first step at or after `from` whose anchor is there. Only the first step of
2404
+ * the run and the step after a click step wait for theirs (the page or a menu can still
2405
+ * be opening); after Next a missing anchor is skipped at once. Skipped steps stay unseen.
2406
+ */
2407
+ /**
2408
+ * The later steps the page can still show: the anchor is on the page now, or
2409
+ * a click step that can show opens it. The count grows if an anchor renders later.
2410
+ */
2411
+ function laterSteps(steps, from) {
2412
+ let count = 0;
2413
+ let previous = true;
2414
+ for (let at = from + 1; at < steps.length; at += 1) {
2415
+ previous = previous && steps[at - 1].advanceOn === "click" || !!document.querySelector(anchorSelector(steps[at].anchor));
2416
+ if (previous) count += 1;
2417
+ }
2418
+ return count;
2419
+ }
2420
+ async function showFrom(from) {
2421
+ if (!run) return;
2422
+ const id = ++runId;
2423
+ stepWait?.abort();
2424
+ const wait = new AbortController();
2425
+ stepWait = wait;
2426
+ detachClick?.();
2427
+ detachClick = void 0;
2428
+ const waitFirst = from === 0 || run.steps[from - 1].advanceOn === "click";
2429
+ for (let index = from; index < run.steps.length; index += 1) {
2430
+ const step = run.steps[index];
2431
+ const timeout = index === from && waitFirst ? ANCHOR_WAIT_MS : 0;
2432
+ const element = await waitForElement(anchorSelector(step.anchor), timeout, wait.signal);
2433
+ if (id !== runId) return;
2434
+ if (!element) {
2435
+ console.debug(`[mint-onboarding] No element with data-onboarding="${step.anchor}"; step "${step.id}" skipped.`);
2436
+ continue;
2437
+ }
2438
+ run.index = index;
2439
+ markSeen(run.tour ? stepKey(run.tour, step) : `news:${step.id}`);
2440
+ if (step.advanceOn === "click") {
2441
+ const onClick = () => next();
2442
+ element.addEventListener("click", onClick);
2443
+ detachClick = () => element.removeEventListener("click", onClick);
2444
+ }
2445
+ run.shown.add(index);
2446
+ const steps = run.steps;
2447
+ const position = [...run.shown].filter((at) => at < index && !!document.querySelector(anchorSelector(steps[at].anchor))).length;
2448
+ active.value = {
2449
+ step,
2450
+ element,
2451
+ index: position,
2452
+ count: position + 1 + laterSteps(run.steps, index),
2453
+ news: !run.tour
2454
+ };
2455
+ return;
2456
+ }
2457
+ const finished = !!run.tour;
2458
+ stop();
2459
+ if (finished && options.autoStart !== false) autoStart();
2460
+ }
2461
+ function begin(tour, steps) {
2462
+ if (!enabled.value || steps.length === 0) return;
2463
+ stop();
2464
+ run = {
2465
+ tour,
2466
+ steps,
2467
+ index: 0,
2468
+ shown: /* @__PURE__ */ new Set()
2469
+ };
2470
+ showFrom(0);
2471
+ }
2472
+ function startTour(id) {
2473
+ const tour = tours.value.find((item) => item.id === id);
2474
+ if (!tour) return;
2475
+ autoStartAbort?.abort();
2476
+ begin(tour, availableSteps(tour));
2477
+ }
2478
+ function showNews(id) {
2479
+ const item = definition.whatsNew?.find((entry) => entry.id === id);
2480
+ if (!item) return;
2481
+ autoStartAbort?.abort();
2482
+ begin(null, [item]);
2483
+ }
2484
+ function next() {
2485
+ if (run) showFrom(run.index + 1);
2486
+ }
2487
+ function back() {
2488
+ if (!run) return;
2489
+ for (let index = run.index - 1; index >= 0; index -= 1) if (document.querySelector(anchorSelector(run.steps[index].anchor))) {
2490
+ showFrom(index);
2491
+ return;
2492
+ }
2493
+ }
2494
+ function dismiss() {
2495
+ autoStartAbort?.abort();
2496
+ const tour = run?.tour;
2497
+ if (tour) markSeen(...tour.steps.map((step) => stepKey(tour, step)));
2498
+ stop();
2499
+ }
2500
+ function complete(taskId) {
2501
+ markSeen(`task:${taskId}`);
2502
+ }
2503
+ function setChecklistHidden(hidden) {
2504
+ if (!storageKey.value) return;
2505
+ if (hidden) markSeen(HIDE_CHECKLIST);
2506
+ else persist((set) => set.delete(HIDE_CHECKLIST));
2507
+ }
2508
+ function refresh() {
2509
+ tick.value += 1;
2510
+ }
2511
+ const availableSteps = (tour) => tour.steps.filter((step) => step.available?.() ?? true);
2512
+ const tried = /* @__PURE__ */ new Set();
2513
+ let autoStartAbort;
2514
+ async function autoStart() {
2515
+ autoStartAbort?.abort();
2516
+ const controller = new AbortController();
2517
+ autoStartAbort = controller;
2518
+ if (!await waitForNoModal(controller.signal) || run || !enabled.value) return;
2519
+ for (const tour of tours.value) {
2520
+ if (tried.has(tour.id)) continue;
2521
+ const unseen = availableSteps(tour).filter((step) => !seen.value.has(stepKey(tour, step)));
2522
+ if (unseen.length) {
2523
+ tried.add(tour.id);
2524
+ begin(tour, unseen);
2525
+ return;
2526
+ }
2527
+ }
2528
+ }
2529
+ watch([route, storageKey], () => {
2530
+ stop();
2531
+ tried.clear();
2532
+ refresh();
2533
+ if (options.autoStart !== false) autoStart();
2534
+ }, { immediate: true });
2535
+ onScopeDispose(() => {
2536
+ autoStartAbort?.abort();
2537
+ window.removeEventListener("storage", onStorage);
2538
+ stop();
2539
+ });
2540
+ const state = {
2541
+ definition,
2542
+ enabled,
2543
+ active,
2544
+ tours,
2545
+ tasks,
2546
+ tasksDone,
2547
+ checklistVisible,
2548
+ checklistHidden,
2549
+ news,
2550
+ unseenNews,
2551
+ startTour,
2552
+ showNews,
2553
+ next,
2554
+ back,
2555
+ dismiss,
2556
+ complete,
2557
+ setChecklistHidden,
2558
+ refresh
2559
+ };
2560
+ provide(ONBOARDING_KEY, state);
2561
+ return state;
2562
+ }
2563
+ /** The app's onboarding coordinator, e.g. to call `complete(taskId)`. Null when the app provides none. */
2564
+ function useOnboarding() {
2565
+ return inject(ONBOARDING_KEY, null);
2566
+ }
2567
+ //#endregion
1816
2568
  //#region src/composables/pluginIdentity.ts
1817
2569
  var identity = reactive({});
1818
2570
  /** The seeded identity AppTopBar shows in standalone mode. Internal: not exported from the package. */
@@ -1930,7 +2682,8 @@ var _hoisted_17$1 = {
1930
2682
  };
1931
2683
  var _hoisted_18$1 = {
1932
2684
  key: 0,
1933
- class: "mint-topbar__center"
2685
+ class: "mint-topbar__center",
2686
+ "data-onboarding": "topbar-pills"
1934
2687
  };
1935
2688
  var _hoisted_19$1 = { class: "mint-topbar__right" };
1936
2689
  var _hoisted_20$1 = {
@@ -1985,7 +2738,7 @@ var AppTopBar_default = /* @__PURE__ */ defineComponent({
1985
2738
  }, props.spec));
1986
2739
  const settingsConfig = computed(() => toValue(config.value.settings) || void 0);
1987
2740
  const showSettings = computed(() => settingsConfig.value !== void 0);
1988
- const SettingsModal = defineAsyncComponent(() => import("./SettingsModal-jra_2u0o.js").then((n) => n.n));
2741
+ const SettingsModal = defineAsyncComponent(() => import("./SettingsModal-CoZK3EDN.js").then((n) => n.n));
1989
2742
  const ExperimentPopover = defineAsyncComponent(() => import("./ExperimentPopover-ChKCrklH.js").then((n) => n.n));
1990
2743
  const ExperimentSelectorModal = defineAsyncComponent(() => import("./ExperimentSelectorModal-BqifjNaN.js").then((n) => n.n));
1991
2744
  const emit = __emit;
@@ -1999,6 +2752,7 @@ var AppTopBar_default = /* @__PURE__ */ defineComponent({
1999
2752
  const { integrated: isIntegrated, plugin } = usePlatform();
2000
2753
  const isStandalone = computed(() => !isIntegrated.value);
2001
2754
  const appExperiment = inject(APP_EXPERIMENT_KEY, null);
2755
+ const onboarding = useOnboarding();
2002
2756
  const canBindExperiment = computed(() => plugin.value?.plugin_type !== "static");
2003
2757
  const showExperiment = computed(() => !!appExperiment && !isStandalone.value && canBindExperiment.value);
2004
2758
  const runSlotJoined = ref(!!props.job);
@@ -2121,9 +2875,11 @@ var AppTopBar_default = /* @__PURE__ */ defineComponent({
2121
2875
  key: 1,
2122
2876
  ref_key: "platformPageSelectorEl",
2123
2877
  ref: platformPageSelectorEl,
2124
- class: "mint-topbar__platform-page-selector"
2878
+ class: "mint-topbar__platform-page-selector",
2879
+ "data-onboarding": "topbar-page-selector"
2125
2880
  }, null, 512)) : hasPropPageSelector.value ? (openBlock(), createBlock(AppTopBarPageSelectorInternal_default, {
2126
2881
  key: 2,
2882
+ "data-onboarding": "topbar-page-selector",
2127
2883
  pages: normalizedPageSelector.value,
2128
2884
  "current-page-id": __props.currentPageSelectorId,
2129
2885
  "plugin-name": pageSelectorPluginName.value,
@@ -2155,7 +2911,8 @@ var AppTopBar_default = /* @__PURE__ */ defineComponent({
2155
2911
  config.value.standaloneLabel !== false && isStandalone.value ? (openBlock(), createElementBlock("span", _hoisted_20$1, toDisplayString(config.value.standaloneLabel), 1)) : createCommentVNode("", true),
2156
2912
  showExperiment.value || __props.job !== void 0 || runSlotJoined.value ? (openBlock(), createElementBlock("div", {
2157
2913
  key: 1,
2158
- class: normalizeClass(["mint-topbar__run-slot", { "mint-topbar__run-slot--joined": runSlotJoined.value }])
2914
+ class: normalizeClass(["mint-topbar__run-slot", { "mint-topbar__run-slot--joined": runSlotJoined.value }]),
2915
+ "data-onboarding": "topbar-run"
2159
2916
  }, [
2160
2917
  showExperiment.value && unref(appExperiment) ? (openBlock(), createBlock(unref(ExperimentPopover), mergeProps({ key: 0 }, __props.job ? {
2161
2918
  ...unref(appExperiment).popover.value,
@@ -2198,15 +2955,20 @@ var AppTopBar_default = /* @__PURE__ */ defineComponent({
2198
2955
  })
2199
2956
  ], 2)) : createCommentVNode("", true),
2200
2957
  renderSlot(_ctx.$slots, "actions"),
2201
- config.value.themeToggle ? (openBlock(), createBlock(ThemeToggle_default, {
2958
+ unref(onboarding)?.enabled.value ? (openBlock(), createBlock(AppTopBarOnboardingInternal_default, {
2202
2959
  key: 2,
2960
+ state: unref(onboarding)
2961
+ }, null, 8, ["state"])) : createCommentVNode("", true),
2962
+ config.value.themeToggle ? (openBlock(), createBlock(ThemeToggle_default, {
2963
+ key: 3,
2203
2964
  size: "sm"
2204
2965
  })) : createCommentVNode("", true),
2205
2966
  showSettings.value ? (openBlock(), createElementBlock("button", {
2206
- key: 3,
2967
+ key: 4,
2207
2968
  type: "button",
2208
2969
  class: "mint-topbar__settings-btn",
2209
2970
  "aria-label": "Open settings",
2971
+ "data-onboarding": "topbar-settings",
2210
2972
  onClick: _cache[7] || (_cache[7] = ($event) => settingsOpen.value = true)
2211
2973
  }, [..._cache[15] || (_cache[15] = [createElementVNode("svg", {
2212
2974
  class: "mint-topbar__settings-icon",
@@ -3727,6 +4489,6 @@ var AppSidebar_default = /* @__PURE__ */ defineComponent({
3727
4489
  }
3728
4490
  });
3729
4491
  //#endregion
3730
- export { getDefaultControlView as A, controlBindings as C, controlsTo as D, controlValuesToComponentProps as E, ThemeToggle_default as M, useTheme as N, controlsToFormSchema as O, useControlSchema as S, controlValuesToComponentBindingsById as T, AppLayout_default as _, pickExistingRecordKeys as a, defineControls as b, valuesEqual as c, useForm as d, AppTopBar_default as f, normalizeLabelItemInput as g, normalizeItemInput as h, formSchemaFieldNames as i, CollapsibleCard_default as j, controlsToSettingsSchema as k, useFormBuilder as l, PluginIcon_default as m, FormSchemaInternal_default as n, pickRecordKeys as o, providePluginIdentity as p, FormFieldRendererInternal_default as r, recordValuesEqualForKeys as s, AppSidebar_default as t, evaluateCondition as u, usePluginWorkspace as v, controlValuesToComponentBindings as w, getControlDefaults as x, defineControlComponentBindings as y };
4492
+ export { controlValuesToComponentBindingsById as A, usePluginWorkspace as C, useControlSchema as D, getControlDefaults as E, getDefaultControlView as F, CollapsibleCard_default as I, ThemeToggle_default as L, controlsTo as M, controlsToFormSchema as N, controlBindings as O, controlsToSettingsSchema as P, useTheme as R, AppLayout_default as S, defineControls as T, provideOnboarding as _, pickExistingRecordKeys as a, normalizeItemInput as b, valuesEqual as c, useForm as d, AppTopBar_default as f, defineOnboarding as g, ONBOARDING_KEY as h, formSchemaFieldNames as i, controlValuesToComponentProps as j, controlValuesToComponentBindings as k, useFormBuilder as l, ANCHOR_WAIT_MS as m, FormSchemaInternal_default as n, pickRecordKeys as o, providePluginIdentity as p, FormFieldRendererInternal_default as r, recordValuesEqualForKeys as s, AppSidebar_default as t, evaluateCondition as u, useOnboarding as v, defineControlComponentBindings as w, normalizeLabelItemInput as x, PluginIcon_default as y };
3731
4493
 
3732
- //# sourceMappingURL=AppSidebar-Bi8g9mRt.js.map
4494
+ //# sourceMappingURL=AppSidebar-CB0-RQ4m.js.map