@ulu/frontend-vue 0.6.33 → 0.6.34

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.
@@ -1,100 +1,5 @@
1
- import { nextTick } from 'vue';
2
1
  declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {
3
- popoverBase: ({
4
- $: import('vue').ComponentInternalInstance;
5
- $data: {};
6
- $props: Partial<{}> & Omit<{} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, never>;
7
- $attrs: {
8
- [x: string]: unknown;
9
- };
10
- $refs: {
11
- [x: string]: unknown;
12
- } & {
13
- contentEl: HTMLSpanElement;
14
- contentArrow: HTMLSpanElement;
15
- };
16
- $slots: Readonly<{
17
- [name: string]: import('vue').Slot<any> | undefined;
18
- }>;
19
- $root: import('vue').ComponentPublicInstance | null;
20
- $parent: import('vue').ComponentPublicInstance | null;
21
- $host: Element | null;
22
- $emit: (event: string, ...args: any[]) => void;
23
- $el: HTMLSpanElement;
24
- $options: import('vue').ComponentOptionsBase<Readonly<{}> & Readonly<{}>, {
25
- close: () => void;
26
- update: Function;
27
- content: import('vue').Ref<null, null>;
28
- $emit: (event: "close" | "update:isOpen", ...args: any[]) => void;
29
- isOpen: boolean;
30
- clickOutsideCloses: boolean;
31
- escapeCloses: boolean;
32
- directFocus: Function;
33
- trigger: Record<string, any>;
34
- config: Record<string, any>;
35
- modifiers?: string | Record<string, any> | unknown[] | undefined;
36
- $props: {
37
- readonly isOpen?: boolean | undefined;
38
- readonly clickOutsideCloses?: boolean | undefined;
39
- readonly escapeCloses?: boolean | undefined;
40
- readonly directFocus?: Function | undefined;
41
- readonly trigger?: Record<string, any> | undefined;
42
- readonly config?: Record<string, any> | undefined;
43
- readonly modifiers?: string | Record<string, any> | unknown[] | undefined;
44
- };
45
- }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, {}, {}, string, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, import('vue').ComponentProvideOptions> & {
46
- beforeCreate?: (() => void) | (() => void)[];
47
- created?: (() => void) | (() => void)[];
48
- beforeMount?: (() => void) | (() => void)[];
49
- mounted?: (() => void) | (() => void)[];
50
- beforeUpdate?: (() => void) | (() => void)[];
51
- updated?: (() => void) | (() => void)[];
52
- activated?: (() => void) | (() => void)[];
53
- deactivated?: (() => void) | (() => void)[];
54
- beforeDestroy?: (() => void) | (() => void)[];
55
- beforeUnmount?: (() => void) | (() => void)[];
56
- destroyed?: (() => void) | (() => void)[];
57
- unmounted?: (() => void) | (() => void)[];
58
- renderTracked?: ((e: import('vue').DebuggerEvent) => void) | ((e: import('vue').DebuggerEvent) => void)[];
59
- renderTriggered?: ((e: import('vue').DebuggerEvent) => void) | ((e: import('vue').DebuggerEvent) => void)[];
60
- errorCaptured?: ((err: unknown, instance: import('vue').ComponentPublicInstance | null, info: string) => boolean | void) | ((err: unknown, instance: import('vue').ComponentPublicInstance | null, info: string) => boolean | void)[];
61
- };
62
- $forceUpdate: () => void;
63
- $nextTick: typeof nextTick;
64
- $watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends (...args: any) => infer R ? (...args: [R, R, import('@vue/reactivity').OnCleanup]) => any : (...args: [any, any, import('@vue/reactivity').OnCleanup]) => any, options?: import('vue').WatchOptions): import('vue').WatchStopHandle;
65
- } & Readonly<{}> & Omit<Readonly<{}> & Readonly<{}>, "$props" | "$emit" | "isOpen" | "clickOutsideCloses" | "escapeCloses" | "directFocus" | "trigger" | "config" | "modifiers" | "content" | "close" | "update"> & import('vue').ShallowUnwrapRef<{
66
- close: () => void;
67
- update: Function;
68
- content: import('vue').Ref<null, null>;
69
- $emit: (event: "close" | "update:isOpen", ...args: any[]) => void;
70
- isOpen: boolean;
71
- clickOutsideCloses: boolean;
72
- escapeCloses: boolean;
73
- directFocus: Function;
74
- trigger: Record<string, any>;
75
- config: Record<string, any>;
76
- modifiers?: string | Record<string, any> | unknown[] | undefined;
77
- $props: {
78
- readonly isOpen?: boolean | undefined;
79
- readonly clickOutsideCloses?: boolean | undefined;
80
- readonly escapeCloses?: boolean | undefined;
81
- readonly directFocus?: Function | undefined;
82
- readonly trigger?: Record<string, any> | undefined;
83
- readonly config?: Record<string, any> | undefined;
84
- readonly modifiers?: string | Record<string, any> | unknown[] | undefined;
85
- };
86
- }> & {} & import('vue').ComponentCustomProperties & {} & {
87
- $slots: {
88
- default?(_: {
89
- isOpen: boolean;
90
- close: () => void;
91
- }): any;
92
- footer?(_: {
93
- isOpen: boolean;
94
- close: () => void;
95
- }): any;
96
- };
97
- }) | null;
2
+ popoverBase: any;
98
3
  }, any>;
99
4
  export default _default;
100
5
  //# sourceMappingURL=UluTourDisplay.vue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UluTourDisplay.vue.d.ts","sourceRoot":"","sources":["../../../lib/plugins/tour/UluTourDisplay.vue"],"names":[],"mappings":"AA8EA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oCA8jByqQ,GAAG,8CAA8C,GAAG,yBAAyB,GAAG,6DAAmC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAvXttQ,KAAK"}
1
+ {"version":3,"file":"UluTourDisplay.vue.d.ts","sourceRoot":"","sources":["../../../lib/plugins/tour/UluTourDisplay.vue"],"names":[],"mappings":"AAgFA;"}
@@ -1,37 +1,37 @@
1
- import { computed as v, ref as f, watch as B, nextTick as T, onMounted as b, onUnmounted as z, createBlock as a, openBlock as o, Teleport as L, createElementBlock as y, createCommentVNode as x, unref as l, Fragment as F, resolveDynamicComponent as g, mergeProps as d, createSlots as $, withCtx as c, createVNode as k, normalizeStyle as I } from "vue";
2
- import R from "../../components/collapsible/UluModal.vue.js";
1
+ import { computed as l, ref as h, watch as z, nextTick as L, onMounted as F, onUnmounted as I, createBlock as a, openBlock as n, Teleport as M, createElementBlock as $, createCommentVNode as k, unref as r, Fragment as R, resolveDynamicComponent as p, mergeProps as d, createSlots as w, withCtx as f, normalizeStyle as D } from "vue";
2
+ import U from "../../components/collapsible/UluModal.vue.js";
3
3
  import V from "../popovers/UluPopoverBase.vue.js";
4
- import w from "./UluTourPager.vue.js";
5
- import _ from "./UluTourContent.vue.js";
6
- import { useTour as D } from "./useTour.js";
7
- const G = {
4
+ import q from "./UluTourPager.vue.js";
5
+ import P from "./UluTourContent.vue.js";
6
+ import { useTour as N } from "./useTour.js";
7
+ const Q = {
8
8
  __name: "UluTourDisplay",
9
- setup(M) {
10
- const { api: u, state: r } = D(), t = v(() => r.active?.steps[r.stepIndex]), i = f(null), m = f(null), C = v(() => ({
9
+ setup(O) {
10
+ const { api: i, state: o } = N(), t = l(() => o.active?.steps[o.stepIndex]), y = l(() => t.value?.component || o.active?.component), c = l(() => t.value?.contentComponent || o.active?.contentComponent), C = l(() => t.value?.pagerComponent || o.active?.pagerComponent || q), _ = l(() => t.value?.modalComponent || o.active?.modalComponent || U), S = l(() => t.value?.popoverComponent || o.active?.popoverComponent || V), v = h(null), g = h(null), E = l(() => ({
11
11
  placement: t.value?.placement || "bottom",
12
12
  arrow: !0,
13
13
  offset: 8
14
- })), P = v(() => ({
15
- ...r.active?.modalProps || {},
14
+ })), B = l(() => ({
15
+ ...o.active?.modalProps || {},
16
16
  ...t.value?.modalProps || {}
17
- })), S = v(() => ({
17
+ })), T = l(() => ({
18
18
  modifiers: "large",
19
- ...r.active?.popoverProps || {},
19
+ ...o.active?.popoverProps || {},
20
20
  ...t.value?.popoverProps || {}
21
- })), p = f(null), s = () => {
22
- if (i.value) {
23
- const e = i.value.getBoundingClientRect();
24
- p.value = {
21
+ })), s = h(null), m = () => {
22
+ if (v.value) {
23
+ const e = v.value.getBoundingClientRect();
24
+ s.value = {
25
25
  top: e.top,
26
26
  left: e.left,
27
27
  width: e.width,
28
28
  height: e.height
29
29
  };
30
30
  } else
31
- p.value = null;
32
- }, E = v(() => {
33
- if (!p.value) return {};
34
- const e = p.value;
31
+ s.value = null;
32
+ }, b = l(() => {
33
+ if (!s.value) return {};
34
+ const e = s.value;
35
35
  return {
36
36
  position: "fixed",
37
37
  top: 0,
@@ -56,44 +56,44 @@ const G = {
56
56
  )`
57
57
  };
58
58
  });
59
- return B(t, async (e) => {
59
+ return z(t, async (e) => {
60
60
  if (e?.target) {
61
- await T();
62
- const n = document.querySelector(e.target);
63
- n ? (i.value = n, m.value && m.value.update(), e.highlight && s()) : console.warn(`Tour target not found: ${e.target}`);
61
+ await L();
62
+ const u = document.querySelector(e.target);
63
+ u ? (v.value = u, g.value && g.value.update(), e.highlight && m()) : console.warn(`Tour target not found: ${e.target}`);
64
64
  } else
65
- i.value = null, p.value = null;
66
- }, { immediate: !0 }), b(() => {
67
- window.addEventListener("resize", s), window.addEventListener("scroll", s);
68
- }), z(() => {
69
- window.removeEventListener("resize", s), window.removeEventListener("scroll", s);
70
- }), (e, n) => (o(), a(L, { to: "body" }, [
71
- l(r).active ? (o(), y(F, { key: 0 }, [
72
- t.value?.component ? (o(), a(g(t.value.component), d({
65
+ v.value = null, s.value = null;
66
+ }, { immediate: !0 }), F(() => {
67
+ window.addEventListener("resize", m), window.addEventListener("scroll", m);
68
+ }), I(() => {
69
+ window.removeEventListener("resize", m), window.removeEventListener("scroll", m);
70
+ }), (e, u) => (n(), a(M, { to: "body" }, [
71
+ r(o).active ? (n(), $(R, { key: 0 }, [
72
+ y.value ? (n(), a(p(y.value), d({
73
73
  key: 0,
74
74
  "data-ulu-tour-ui": "true",
75
75
  step: t.value,
76
- tourState: l(r),
77
- api: l(u)
78
- }, t.value.componentProps), null, 16, ["step", "tourState", "api"])) : t.value?.target ? (o(), a(V, d({
76
+ tourState: r(o),
77
+ api: r(i)
78
+ }, t.value.componentProps), null, 16, ["step", "tourState", "api"])) : t.value?.target ? (n(), a(p(S.value), d({
79
79
  key: 2,
80
80
  ref_key: "popoverBase",
81
- ref: m,
82
- trigger: i.value,
83
- config: C.value,
81
+ ref: g,
82
+ trigger: v.value,
83
+ config: E.value,
84
84
  style: { zIndex: 9999 },
85
85
  isOpen: !0,
86
86
  "data-ulu-tour-ui": "true",
87
- onClose: n[1] || (n[1] = (h) => l(u).stop())
88
- }, S.value), $({
89
- default: c(() => [
90
- t.value?.contentComponent ? (o(), a(g(t.value.contentComponent), d({
87
+ onClose: u[1] || (u[1] = (x) => r(i).stop())
88
+ }, T.value), w({
89
+ default: f(() => [
90
+ c.value ? (n(), a(p(c.value), d({
91
91
  key: 0,
92
92
  step: t.value,
93
- tourState: l(r),
94
- api: l(u),
93
+ tourState: r(o),
94
+ api: r(i),
95
95
  "is-modal": !1
96
- }, t.value.componentProps), null, 16, ["step", "tourState", "api"])) : (o(), a(_, {
96
+ }, t.value.componentProps), null, 16, ["step", "tourState", "api"])) : (n(), a(P, {
97
97
  key: 1,
98
98
  step: t.value,
99
99
  "is-modal": !1
@@ -103,26 +103,26 @@ const G = {
103
103
  }, [
104
104
  t.value?.hideFooter ? void 0 : {
105
105
  name: "footer",
106
- fn: c(() => [
107
- k(w)
106
+ fn: f(() => [
107
+ (n(), a(p(C.value)))
108
108
  ]),
109
109
  key: "0"
110
110
  }
111
- ]), 1040, ["trigger", "config"])) : (o(), a(R, d({
111
+ ]), 1040, ["trigger", "config"])) : (n(), a(p(_.value), d({
112
112
  key: 1,
113
113
  modelValue: !0,
114
114
  "data-ulu-tour-ui": "true"
115
- }, P.value, {
116
- onClose: n[0] || (n[0] = (h) => l(u).stop())
117
- }), $({
118
- default: c(() => [
119
- t.value?.contentComponent ? (o(), a(g(t.value.contentComponent), d({
115
+ }, B.value, {
116
+ onClose: u[0] || (u[0] = (x) => r(i).stop())
117
+ }), w({
118
+ default: f(() => [
119
+ c.value ? (n(), a(p(c.value), d({
120
120
  key: 0,
121
121
  step: t.value,
122
- tourState: l(r),
123
- api: l(u),
122
+ tourState: r(o),
123
+ api: r(i),
124
124
  "is-modal": !0
125
- }, t.value.componentProps), null, 16, ["step", "tourState", "api"])) : (o(), a(_, {
125
+ }, t.value.componentProps), null, 16, ["step", "tourState", "api"])) : (n(), a(P, {
126
126
  key: 1,
127
127
  step: t.value,
128
128
  "is-modal": !0
@@ -132,23 +132,23 @@ const G = {
132
132
  }, [
133
133
  t.value?.hideFooter ? void 0 : {
134
134
  name: "footer",
135
- fn: c(() => [
136
- k(w)
135
+ fn: f(() => [
136
+ (n(), a(p(C.value)))
137
137
  ]),
138
138
  key: "0"
139
139
  }
140
140
  ]), 1040)),
141
- t.value?.target && t.value?.highlight && p.value ? (o(), y("div", {
141
+ t.value?.target && t.value?.highlight && s.value ? (n(), $("div", {
142
142
  key: 3,
143
143
  class: "tour-highlight-backdrop",
144
- style: I(E.value),
144
+ style: D(b.value),
145
145
  "data-ulu-tour-ui": "true",
146
- onClick: n[2] || (n[2] = (h) => l(u).stop())
147
- }, null, 4)) : x("", !0)
148
- ], 64)) : x("", !0)
146
+ onClick: u[2] || (u[2] = (x) => r(i).stop())
147
+ }, null, 4)) : k("", !0)
148
+ ], 64)) : k("", !0)
149
149
  ]));
150
150
  }
151
151
  };
152
152
  export {
153
- G as default
153
+ Q as default
154
154
  };
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../lib/plugins/tour/api.js"],"names":[],"mappings":"AA0BO,iCAHI,MAAM,GACJ,MAAM,CAqFjB"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../lib/plugins/tour/api.js"],"names":[],"mappings":"AA0BO,iCAHI,MAAM,GACJ,MAAM,CAkHjB"}
@@ -1,5 +1,5 @@
1
- import { markRaw as o } from "vue";
2
- const s = (e) => ({
1
+ import { markRaw as s } from "vue";
2
+ const r = (n) => ({
3
3
  /**
4
4
  * Starts a new tour
5
5
  * @param {Object} tour - The tour configuration object
@@ -10,57 +10,89 @@ const s = (e) => ({
10
10
  * @param {String|Array|Object} [tour.modalTitleClass] - Global class applied to the title of modal steps.
11
11
  * @param {String|Array|Object} [tour.popoverTitleClass] - Global class applied to the title of popover steps.
12
12
  * @param {String|Array|Object} [tour.pagerClass] - Global class applied to the pager.
13
+ * @param {Function} [tour.onStart] - Async hook called before the tour starts.
13
14
  * @param {Function} [tour.onStop] - Async hook called when the tour is closed/finished.
14
15
  */
15
- async start(n) {
16
- n?.steps?.length && (await this._runHooks(n.steps[0]), e.active = o(n), e.stepIndex = 0);
16
+ async start(i) {
17
+ if (!n.isTransitioning) {
18
+ n.isTransitioning = !0;
19
+ try {
20
+ if (!i?.steps?.length) return;
21
+ typeof i.onStart == "function" && await i.onStart(), await this._runHooks(i.steps[0]), n.active = s(i), n.stepIndex = 0;
22
+ } finally {
23
+ n.isTransitioning = !1;
24
+ }
25
+ }
17
26
  },
18
27
  /**
19
28
  * Advances the tour to the next step, or stops if it is the last step
20
29
  */
21
30
  async next() {
22
- const n = e.active;
23
- if (n)
24
- if (e.stepIndex < n.steps.length - 1) {
25
- await this._runLeaveHook(n.steps[e.stepIndex]);
26
- const i = e.stepIndex + 1;
27
- await this._runHooks(n.steps[i]), e.stepIndex = i;
28
- } else
29
- await this.stop();
31
+ if (n.isTransitioning) return;
32
+ const i = n.active;
33
+ if (i) {
34
+ n.isTransitioning = !0;
35
+ try {
36
+ if (n.stepIndex < i.steps.length - 1) {
37
+ await this._runLeaveHook(i.steps[n.stepIndex]);
38
+ const e = n.stepIndex + 1;
39
+ await this._runHooks(i.steps[e]), n.stepIndex = e;
40
+ } else
41
+ await this.stop(!0);
42
+ } finally {
43
+ n.isTransitioning = !1;
44
+ }
45
+ }
30
46
  },
31
47
  /**
32
48
  * Returns the tour to the previous step
33
49
  */
34
50
  async prev() {
35
- const n = e.active;
36
- if (n && e.stepIndex > 0) {
37
- await this._runLeaveHook(n.steps[e.stepIndex]);
38
- const i = e.stepIndex - 1;
39
- await this._runHooks(n.steps[i]), e.stepIndex = i;
51
+ if (n.isTransitioning) return;
52
+ const i = n.active;
53
+ if (i) {
54
+ n.isTransitioning = !0;
55
+ try {
56
+ if (n.stepIndex > 0) {
57
+ await this._runLeaveHook(i.steps[n.stepIndex]);
58
+ const e = n.stepIndex - 1;
59
+ await this._runHooks(i.steps[e]), n.stepIndex = e;
60
+ }
61
+ } finally {
62
+ n.isTransitioning = !1;
63
+ }
40
64
  }
41
65
  },
42
66
  /**
43
67
  * Stops and closes the current tour
68
+ * @param {Boolean} [internalBypass=false] - Used internally to bypass transition check
44
69
  */
45
- async stop() {
46
- const n = e.active;
47
- n && (n.steps[e.stepIndex] && await this._runLeaveHook(n.steps[e.stepIndex]), typeof n.onStop == "function" && await n.onStop()), e.active = null, e.stepIndex = 0;
70
+ async stop(i = !1) {
71
+ if (!(!i && n.isTransitioning)) {
72
+ n.isTransitioning = !0;
73
+ try {
74
+ const e = n.active;
75
+ e && (e.steps[n.stepIndex] && await this._runLeaveHook(e.steps[n.stepIndex]), typeof e.onStop == "function" && await e.onStop()), n.active = null, n.stepIndex = 0;
76
+ } finally {
77
+ n.isTransitioning = !1;
78
+ }
79
+ }
48
80
  },
49
81
  /**
50
82
  * Internal method to run asynchronous enter hooks on a step
51
83
  * @param {Object} step - The tour step configuration
52
84
  */
53
- async _runHooks(n) {
54
- n && typeof n.onEnter == "function" && await n.onEnter();
85
+ async _runHooks(i) {
86
+ i && typeof i.onEnter == "function" && await i.onEnter();
55
87
  },
56
88
  /**
57
89
  * Internal method to run asynchronous leave hooks on a step
58
90
  * @param {Object} step - The tour step configuration
59
91
  */
60
- async _runLeaveHook(n) {
61
- n && typeof n.onLeave == "function" && await n.onLeave();
92
+ async _runLeaveHook(i) {
93
+ i && typeof i.onLeave == "function" && await i.onLeave();
62
94
  }
63
95
  });
64
96
  export {
65
- s as createApi
97
+ r as createApi
66
98
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/plugins/tour/index.js"],"names":[],"mappings":"AAQA,gDAeC;;;;;wBAjBuB,cAAc"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/plugins/tour/index.js"],"names":[],"mappings":"AAQA,gDAgBC;;;;;wBAlBuB,cAAc"}
@@ -1,14 +1,15 @@
1
- import { reactive as e } from "vue";
2
- import u from "./UluTourDisplay.vue.js";
3
- import { createApi as i } from "./api.js";
4
- function s(o) {
5
- const t = e({
1
+ import { reactive as r } from "vue";
2
+ import e from "./UluTourDisplay.vue.js";
3
+ import { createApi as u } from "./api.js";
4
+ function a(o) {
5
+ const t = r({
6
6
  active: null,
7
- stepIndex: 0
8
- }), r = i(t);
9
- o.component("UluTourDisplay", u), o.config.globalProperties.$uluTour = r, o.config.globalProperties.$uluTourState = t, o.provide("uluTour", r), o.provide("uluTourState", t);
7
+ stepIndex: 0,
8
+ isTransitioning: !1
9
+ }), i = u(t);
10
+ o.component("UluTourDisplay", e), o.config.globalProperties.$uluTour = i, o.config.globalProperties.$uluTourState = t, o.provide("uluTour", i), o.provide("uluTourState", t);
10
11
  }
11
12
  export {
12
- u as UluTourDisplay,
13
- s as default
13
+ e as UluTourDisplay,
14
+ a as default
14
15
  };
@@ -4,8 +4,8 @@
4
4
 
5
5
  <!-- 1. FULL COMPONENT TAKEOVER -->
6
6
  <component
7
- v-if="currentStep?.component"
8
- :is="currentStep.component"
7
+ v-if="resolvedComponent"
8
+ :is="resolvedComponent"
9
9
  data-ulu-tour-ui="true"
10
10
  :step="currentStep"
11
11
  :tourState="tourState"
@@ -14,16 +14,17 @@
14
14
  />
15
15
 
16
16
  <!-- 2. RENDER MODAL STEP -->
17
- <UluModal
17
+ <component
18
18
  v-else-if="!currentStep?.target"
19
+ :is="resolvedModalComponent"
19
20
  :modelValue="true"
20
21
  data-ulu-tour-ui="true"
21
22
  v-bind="resolvedModalProps"
22
23
  @close="api.stop()"
23
24
  >
24
25
  <component
25
- v-if="currentStep?.contentComponent"
26
- :is="currentStep.contentComponent"
26
+ v-if="resolvedContentComponent"
27
+ :is="resolvedContentComponent"
27
28
  :step="currentStep"
28
29
  :tourState="tourState"
29
30
  :api="api"
@@ -33,13 +34,14 @@
33
34
  <UluTourContent v-else :step="currentStep" :is-modal="true" />
34
35
 
35
36
  <template #footer v-if="!currentStep?.hideFooter">
36
- <UluTourPager />
37
+ <component :is="resolvedPagerComponent" />
37
38
  </template>
38
- </UluModal>
39
+ </component>
39
40
 
40
41
  <!-- 3. RENDER POPOVER STEP -->
41
- <UluPopoverBase
42
+ <component
42
43
  v-else
44
+ :is="resolvedPopoverComponent"
43
45
  ref="popoverBase"
44
46
  :trigger="targetEl"
45
47
  :config="resolvedConfig"
@@ -50,8 +52,8 @@
50
52
  v-bind="resolvedPopoverProps"
51
53
  >
52
54
  <component
53
- v-if="currentStep?.contentComponent"
54
- :is="currentStep.contentComponent"
55
+ v-if="resolvedContentComponent"
56
+ :is="resolvedContentComponent"
55
57
  :step="currentStep"
56
58
  :tourState="tourState"
57
59
  :api="api"
@@ -61,9 +63,9 @@
61
63
  <UluTourContent v-else :step="currentStep" :is-modal="false" />
62
64
 
63
65
  <template #footer v-if="!currentStep?.hideFooter">
64
- <UluTourPager />
66
+ <component :is="resolvedPagerComponent" />
65
67
  </template>
66
- </UluPopoverBase>
68
+ </component>
67
69
 
68
70
  <!-- OPTIONAL HIGHLIGHT BACKDROP -->
69
71
  <div
@@ -89,6 +91,13 @@
89
91
 
90
92
  const currentStep = computed(() => tourState.active?.steps[tourState.stepIndex]);
91
93
 
94
+ // Component Resolution
95
+ const resolvedComponent = computed(() => currentStep.value?.component || tourState.active?.component);
96
+ const resolvedContentComponent = computed(() => currentStep.value?.contentComponent || tourState.active?.contentComponent);
97
+ const resolvedPagerComponent = computed(() => currentStep.value?.pagerComponent || tourState.active?.pagerComponent || UluTourPager);
98
+ const resolvedModalComponent = computed(() => currentStep.value?.modalComponent || tourState.active?.modalComponent || UluModal);
99
+ const resolvedPopoverComponent = computed(() => currentStep.value?.popoverComponent || tourState.active?.popoverComponent || UluPopoverBase);
100
+
92
101
  // Floating UI Setup for Popovers
93
102
  const targetEl = ref(null);
94
103
  const popoverBase = ref(null);