@glowhop/vue-tour 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # @glowhop/vue-tour
2
+
3
+ ## 1.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - e6da5bf: GlowTour.js V.1.0.0 release
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [e6da5bf]
12
+ - @glowhop/core-tour@1.0.0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Glowhop
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # @glowhop/vue-tour
2
+
3
+ ESM-only Vue 3 adapter with provide/inject refs for native reactive state. Content is Vue slot content. See the [Core guide](https://github.com/Glowhop/GlowTour.js/tree/main/packages/core) for workflow options and actions.
4
+
5
+ Compatibility: Vue 3.3+ (`^3.3.0`). SSR: the root renders through `@vue/server-renderer` and browser work starts on mount; hydration is verified at package level and in a production Nuxt app. Full contract: [compatibility](https://github.com/Glowhop/GlowTour.js/blob/main/docs/compatibility.md).
6
+
7
+ <!-- glow-tour:snippet vue-quick-start -->
8
+ ```vue
9
+ <script setup lang="ts">
10
+ import "@glowhop/styles-tour/default.css";
11
+ import { GlowTourDefault, createGlowTour } from "@glowhop/vue-tour";
12
+ const tour = createGlowTour();
13
+ const workflow = tour.create("intro").step({ id: "welcome", target: "#welcome", title: "Welcome", content: "Hello." }).build();
14
+ function start() { void tour.run(workflow); }
15
+ </script>
16
+ <template><button id="welcome">Welcome</button><button type="button" @click="start">Start tour</button><GlowTourDefault :tour="tour" /></template>
17
+ ```
18
+
19
+ <!-- glow-tour:snippet vue-advanced -->
20
+ ```vue
21
+ <script setup lang="ts">
22
+ import { GlowTourRoot, GlowTourOverlay, GlowTourPopover, GlowTourHeader, GlowTourContent, GlowTourFooter, GlowTourAdvanceTrigger, createGlowTour } from "@glowhop/vue-tour";
23
+ const tour = createGlowTour(); const workflow = tour.create("custom").step({ id: "welcome", target: "#welcome", title: "Welcome", content: "Hello." }).build(); const start = () => void tour.run(workflow);
24
+ </script>
25
+ <template><button id="welcome" type="button" @click="start">Start</button><GlowTourRoot :tour="tour"><GlowTourOverlay /><GlowTourPopover><GlowTourHeader /><GlowTourContent /><GlowTourFooter><GlowTourAdvanceTrigger /></GlowTourFooter></GlowTourPopover></GlowTourRoot></template>
26
+ ```
27
+
28
+ Use `GlowTourRoot`, `GlowTourOverlay`, `GlowTourPointer`, `GlowTourPopover`, `GlowTourHeader`, `GlowTourContent`, `GlowTourFooter`, and named triggers for composition. Vue refs and provide/inject are the native state surface. Static/dynamic targets, placement, interaction, scroll, callbacks, actions/events, cancellation, and cleanup follow Core.
@@ -0,0 +1,25 @@
1
+ import type { GlowTour as CoreGlowTour } from "@glowhop/core-tour";
2
+ import { type PropType } from "vue";
3
+ import type { VueTourContent } from "../glow-tour.js";
4
+ type Tour = CoreGlowTour<VueTourContent>;
5
+ /** Default GlowTour.js component that renders all tour UI elements in a standard layout. */
6
+ export declare const GlowTourDefault: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
7
+ idPrefix: {
8
+ type: StringConstructor;
9
+ };
10
+ tour: {
11
+ required: true;
12
+ type: PropType<Tour>;
13
+ };
14
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
15
+ [key: string]: any;
16
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
17
+ idPrefix: {
18
+ type: StringConstructor;
19
+ };
20
+ tour: {
21
+ required: true;
22
+ type: PropType<Tour>;
23
+ };
24
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
25
+ export {};
@@ -0,0 +1,39 @@
1
+ // packages/vue/src/components/default-tour.ts
2
+ import { defineComponent, h } from "vue";
3
+ import {
4
+ GlowTourAdvanceTrigger,
5
+ GlowTourBackTrigger,
6
+ GlowTourCancelTrigger,
7
+ GlowTourContent,
8
+ GlowTourFooter,
9
+ GlowTourHeader,
10
+ GlowTourOverlay,
11
+ GlowTourPointer,
12
+ GlowTourPopover,
13
+ GlowTourRoot
14
+ } from "./tour-components.js";
15
+ var GlowTourDefault = defineComponent({
16
+ name: "GlowTourDefault",
17
+ props: {
18
+ idPrefix: { type: String },
19
+ tour: { required: true, type: Object }
20
+ },
21
+ setup(props) {
22
+ return () => h(GlowTourRoot, { idPrefix: props.idPrefix, tour: props.tour }, () => [
23
+ h(GlowTourOverlay),
24
+ h(GlowTourPointer),
25
+ h(GlowTourPopover, null, () => [
26
+ h(GlowTourHeader),
27
+ h(GlowTourContent),
28
+ h(GlowTourFooter, null, () => [
29
+ h(GlowTourCancelTrigger),
30
+ h(GlowTourBackTrigger),
31
+ h(GlowTourAdvanceTrigger)
32
+ ])
33
+ ])
34
+ ]);
35
+ }
36
+ });
37
+ export {
38
+ GlowTourDefault
39
+ };
@@ -0,0 +1,183 @@
1
+ import type { GlowTour as CoreGlowTour, TourState } from "@glowhop/core-tour";
2
+ import type { VNodeChild } from "vue";
3
+ import { type PropType, type ShallowRef } from "vue";
4
+ import type { VueTourContent } from "../glow-tour.js";
5
+ type Tour = CoreGlowTour<VueTourContent>;
6
+ /** Pointer direction content configuration for custom pointer content. */
7
+ export interface PointerDirectionContent {
8
+ readonly top?: VNodeChild;
9
+ readonly bottom?: VNodeChild;
10
+ readonly left?: VNodeChild;
11
+ readonly right?: VNodeChild;
12
+ }
13
+ /**
14
+ * Retrieves the current tour state snapshot.
15
+ * Must be called within a GlowTourRoot component context.
16
+ * @returns A reactive shallow ref containing the current tour state.
17
+ */
18
+ export declare function useTour(): ShallowRef<TourState<VueTourContent>>;
19
+ /** Root container component for GlowTour.js. Provides tour context and manages the root binding. */
20
+ export declare const GlowTourRoot: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
21
+ idPrefix: {
22
+ type: StringConstructor;
23
+ };
24
+ tour: {
25
+ required: true;
26
+ type: PropType<Tour>;
27
+ };
28
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
29
+ [key: string]: any;
30
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
31
+ idPrefix: {
32
+ type: StringConstructor;
33
+ };
34
+ tour: {
35
+ required: true;
36
+ type: PropType<Tour>;
37
+ };
38
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
39
+ /** Header component displaying the current step's title. */
40
+ export declare const GlowTourHeader: import("vue").DefineComponent<{}, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
41
+ [key: string]: any;
42
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
43
+ /** Content component displaying the current step's content with live region. */
44
+ export declare const GlowTourContent: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
45
+ ariaLive: {
46
+ default: string;
47
+ type: StringConstructor;
48
+ };
49
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
50
+ [key: string]: any;
51
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
52
+ ariaLive: {
53
+ default: string;
54
+ type: StringConstructor;
55
+ };
56
+ }>> & Readonly<{}>, {
57
+ ariaLive: string;
58
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
59
+ /** Footer component containing action buttons. Conditionally rendered based on tour step configuration. */
60
+ export declare const GlowTourFooter: import("vue").DefineComponent<{}, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
61
+ [key: string]: any;
62
+ }> | null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
63
+ /** Popover component containing the tour content with accessibility attributes. */
64
+ export declare const GlowTourPopover: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
65
+ role: {
66
+ default: string;
67
+ type: StringConstructor;
68
+ };
69
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
70
+ [key: string]: any;
71
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
72
+ role: {
73
+ default: string;
74
+ type: StringConstructor;
75
+ };
76
+ }>> & Readonly<{}>, {
77
+ role: string;
78
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
79
+ /** Pointer component displaying directional indicators pointing to the target element. */
80
+ export declare const GlowTourPointer: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
81
+ directionContent: {
82
+ default: undefined;
83
+ type: PropType<PointerDirectionContent>;
84
+ };
85
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
86
+ [key: string]: any;
87
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
88
+ directionContent: {
89
+ default: undefined;
90
+ type: PropType<PointerDirectionContent>;
91
+ };
92
+ }>> & Readonly<{}>, {
93
+ directionContent: PointerDirectionContent;
94
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
95
+ /** Overlay component rendering a clipped SVG mask highlighting the target element. */
96
+ export declare const GlowTourOverlay: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
97
+ ariaHidden: {
98
+ default: boolean;
99
+ type: BooleanConstructor;
100
+ };
101
+ focusable: {
102
+ default: string;
103
+ type: StringConstructor;
104
+ };
105
+ viewBox: {
106
+ default: string;
107
+ type: StringConstructor;
108
+ };
109
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
110
+ [key: string]: any;
111
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
112
+ ariaHidden: {
113
+ default: boolean;
114
+ type: BooleanConstructor;
115
+ };
116
+ focusable: {
117
+ default: string;
118
+ type: StringConstructor;
119
+ };
120
+ viewBox: {
121
+ default: string;
122
+ type: StringConstructor;
123
+ };
124
+ }>> & Readonly<{}>, {
125
+ ariaHidden: boolean;
126
+ focusable: string;
127
+ viewBox: string;
128
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
129
+ /** Button component for navigating to the previous step in the tour. */
130
+ export declare const GlowTourBackTrigger: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
131
+ ariaLabel: {
132
+ type: StringConstructor;
133
+ };
134
+ backLabel: {
135
+ type: StringConstructor;
136
+ };
137
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
138
+ [key: string]: any;
139
+ }> | null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
140
+ ariaLabel: {
141
+ type: StringConstructor;
142
+ };
143
+ backLabel: {
144
+ type: StringConstructor;
145
+ };
146
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
147
+ /** Button component for advancing to the next step or finishing the tour. */
148
+ export declare const GlowTourAdvanceTrigger: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
149
+ ariaLabel: {
150
+ type: StringConstructor;
151
+ };
152
+ finishLabel: {
153
+ type: StringConstructor;
154
+ };
155
+ advanceLabel: {
156
+ type: StringConstructor;
157
+ };
158
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
159
+ [key: string]: any;
160
+ }> | null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
161
+ ariaLabel: {
162
+ type: StringConstructor;
163
+ };
164
+ finishLabel: {
165
+ type: StringConstructor;
166
+ };
167
+ advanceLabel: {
168
+ type: StringConstructor;
169
+ };
170
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
171
+ /** Button component for canceling/skipping the tour. */
172
+ export declare const GlowTourCancelTrigger: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
173
+ ariaLabel: {
174
+ type: StringConstructor;
175
+ };
176
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
177
+ [key: string]: any;
178
+ }> | null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
179
+ ariaLabel: {
180
+ type: StringConstructor;
181
+ };
182
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
183
+ export {};
@@ -0,0 +1,289 @@
1
+ // packages/vue/src/components/tour-components.ts
2
+ import {
3
+ connectGlowTourRoot,
4
+ OVERLAY_IDLE_ATTRIBUTES,
5
+ OVERLAY_IDLE_STYLE,
6
+ OVERLAY_PATH_IDLE_ATTRIBUTES,
7
+ POINTER_IDLE_ATTRIBUTES,
8
+ POINTER_IDLE_STYLE,
9
+ POPOVER_IDLE_ATTRIBUTES,
10
+ POPOVER_IDLE_STYLE
11
+ } from "@glowhop/core-tour/adapter";
12
+ import {
13
+ defineComponent,
14
+ h,
15
+ inject,
16
+ mergeProps,
17
+ onBeforeUnmount,
18
+ provide,
19
+ shallowRef,
20
+ watch
21
+ } from "vue";
22
+ var DEFAULT_POINTER_DIRECTION_CONTENT = {
23
+ bottom: "\uD83D\uDC47",
24
+ left: "\uD83D\uDC48",
25
+ right: "\uD83D\uDC49",
26
+ top: "\uD83D\uDC46"
27
+ };
28
+ var TOUR_CONTEXT = Symbol("GlowTourContext");
29
+ function componentName(name) {
30
+ return `GlowTour${name}`;
31
+ }
32
+ function useTourContext() {
33
+ const context = inject(TOUR_CONTEXT);
34
+ if (!context) {
35
+ throw new Error("GlowTour components must be rendered inside <GlowTourRoot tour={...}>.");
36
+ }
37
+ return context;
38
+ }
39
+ function useTourSnapshot(tour) {
40
+ const snapshot = shallowRef(tour.value.state.get());
41
+ watch(tour, (activeTour, _previousTour, onCleanup) => {
42
+ snapshot.value = activeTour.state.get();
43
+ onCleanup(activeTour.state.subscribe((next) => snapshot.value = next));
44
+ }, { immediate: true });
45
+ return snapshot;
46
+ }
47
+ function useTour() {
48
+ const { tour } = useTourContext();
49
+ return useTourSnapshot(tour);
50
+ }
51
+ function useStep() {
52
+ const context = useTourContext();
53
+ const snapshot = useTourSnapshot(context.tour);
54
+ return () => snapshot.value.currentStep?.currentProps ?? null;
55
+ }
56
+ function useBoundElement(bind) {
57
+ const context = useTourContext();
58
+ const element = shallowRef(null);
59
+ watch([context.binding, element], ([binding, activeElement], _previous, onCleanup) => {
60
+ if (!binding || !activeElement)
61
+ return;
62
+ onCleanup(bind(binding, activeElement));
63
+ }, { flush: "post" });
64
+ return element;
65
+ }
66
+ function isConsumerDisabled(attrs) {
67
+ return attrs.disabled === "" || attrs.disabled === true;
68
+ }
69
+ var GlowTourRoot = defineComponent({
70
+ name: componentName("Root"),
71
+ inheritAttrs: false,
72
+ props: {
73
+ idPrefix: { type: String },
74
+ tour: { required: true, type: Object }
75
+ },
76
+ setup(props, { attrs, slots }) {
77
+ const binding = shallowRef(null);
78
+ const tour = shallowRef(props.tour);
79
+ provide(TOUR_CONTEXT, { binding, tour });
80
+ let element = null;
81
+ let active;
82
+ const release = () => {
83
+ const current = active;
84
+ if (!current)
85
+ return;
86
+ active = undefined;
87
+ current.binding.release();
88
+ if (binding.value === current.binding)
89
+ binding.value = null;
90
+ };
91
+ const connect = () => {
92
+ const activeTour = props.tour;
93
+ const idPrefix = props.idPrefix;
94
+ tour.value = activeTour;
95
+ if (active?.root === element && active.tour === activeTour && active.idPrefix === idPrefix) {
96
+ return;
97
+ }
98
+ release();
99
+ if (!element)
100
+ return;
101
+ const nextBinding = connectGlowTourRoot(activeTour, {
102
+ idPrefix,
103
+ root: element
104
+ });
105
+ active = { binding: nextBinding, idPrefix, root: element, tour: activeTour };
106
+ binding.value = nextBinding;
107
+ };
108
+ const setRoot = (root) => {
109
+ element = root instanceof HTMLElement ? root : null;
110
+ connect();
111
+ };
112
+ watch([() => props.tour, () => props.idPrefix], connect);
113
+ onBeforeUnmount(release);
114
+ return () => h("section", mergeProps(attrs, { "data-glow-tour-root": "", ref: setRoot }), slots.default?.());
115
+ }
116
+ });
117
+ var GlowTourHeader = defineComponent({
118
+ name: componentName("Header"),
119
+ inheritAttrs: false,
120
+ setup(_props, { attrs }) {
121
+ const context = useTourContext();
122
+ const step = useStep();
123
+ return () => h("header", mergeProps(attrs, { "data-glow-tour-header": "", id: context.binding.value?.ids.title }), [step()?.title ?? null]);
124
+ }
125
+ });
126
+ var GlowTourContent = defineComponent({
127
+ name: componentName("Content"),
128
+ inheritAttrs: false,
129
+ props: { ariaLive: { default: "polite", type: String } },
130
+ setup(props, { attrs }) {
131
+ const context = useTourContext();
132
+ const step = useStep();
133
+ return () => h("div", mergeProps(attrs, {
134
+ "aria-live": props.ariaLive,
135
+ "data-glow-tour-content": "",
136
+ id: context.binding.value?.ids.description
137
+ }), [step()?.content ?? null]);
138
+ }
139
+ });
140
+ var GlowTourFooter = defineComponent({
141
+ name: componentName("Footer"),
142
+ inheritAttrs: false,
143
+ setup(_props, { attrs, slots }) {
144
+ const step = useStep();
145
+ return () => step()?.popover?.hideFooter ? null : h("footer", mergeProps(attrs, { "data-glow-tour-footer": "" }), slots.default?.());
146
+ }
147
+ });
148
+ var GlowTourPopover = defineComponent({
149
+ name: componentName("Popover"),
150
+ inheritAttrs: false,
151
+ props: { role: { default: "dialog", type: String } },
152
+ setup(props, { attrs, slots }) {
153
+ const context = useTourContext();
154
+ const element = useBoundElement((binding, activeElement) => binding.bindPopover(activeElement));
155
+ return () => h("section", mergeProps({ style: POPOVER_IDLE_STYLE }, attrs, {
156
+ "aria-describedby": context.binding.value?.ids.description,
157
+ "aria-hidden": POPOVER_IDLE_ATTRIBUTES["aria-hidden"],
158
+ "aria-labelledby": context.binding.value?.ids.title,
159
+ "data-glow-tour-popover": "",
160
+ id: context.binding.value?.ids.popover,
161
+ inert: POPOVER_IDLE_ATTRIBUTES.inert,
162
+ ref: element,
163
+ role: props.role,
164
+ tabindex: -1
165
+ }), slots.default?.());
166
+ }
167
+ });
168
+ var GlowTourPointer = defineComponent({
169
+ name: componentName("Pointer"),
170
+ inheritAttrs: false,
171
+ props: {
172
+ directionContent: { default: undefined, type: Object }
173
+ },
174
+ setup(props, { attrs }) {
175
+ const element = useBoundElement((binding, activeElement) => binding.bindPointer(activeElement));
176
+ return () => {
177
+ const content = { ...DEFAULT_POINTER_DIRECTION_CONTENT, ...props.directionContent };
178
+ return h("div", mergeProps({ style: POINTER_IDLE_STYLE }, attrs, {
179
+ "aria-hidden": POINTER_IDLE_ATTRIBUTES["aria-hidden"],
180
+ "data-glow-tour-pointer": "",
181
+ ref: element
182
+ }), Object.keys(DEFAULT_POINTER_DIRECTION_CONTENT).map((direction) => h("div", { "data-glow-tour-pointer-direction": direction }, [content[direction]])));
183
+ };
184
+ }
185
+ });
186
+ var GlowTourOverlay = defineComponent({
187
+ name: componentName("Overlay"),
188
+ inheritAttrs: false,
189
+ props: {
190
+ ariaHidden: { default: true, type: Boolean },
191
+ focusable: { default: "false", type: String },
192
+ viewBox: { default: "0 0 0 0", type: String }
193
+ },
194
+ setup(props, { attrs, slots }) {
195
+ const element = useBoundElement((binding, activeElement) => binding.bindOverlay(activeElement));
196
+ return () => h("svg", mergeProps({ style: OVERLAY_IDLE_STYLE }, attrs, {
197
+ "aria-hidden": props.ariaHidden,
198
+ "data-glow-tour-allow-interaction": OVERLAY_IDLE_ATTRIBUTES["data-glow-tour-allow-interaction"],
199
+ "data-glow-tour-overlay": "",
200
+ focusable: props.focusable,
201
+ inert: OVERLAY_IDLE_ATTRIBUTES.inert,
202
+ ref: element,
203
+ role: "presentation",
204
+ viewBox: props.viewBox
205
+ }), [
206
+ h("path", {
207
+ cursor: OVERLAY_PATH_IDLE_ATTRIBUTES.cursor,
208
+ "data-glow-tour-overlay-path": "",
209
+ "fill-rule": "evenodd",
210
+ opacity: OVERLAY_PATH_IDLE_ATTRIBUTES.opacity,
211
+ "pointer-events": OVERLAY_PATH_IDLE_ATTRIBUTES["pointer-events"]
212
+ }),
213
+ slots.default?.()
214
+ ]);
215
+ }
216
+ });
217
+ function trigger(marker, capabilityDisabled, label, ariaLabel, attrs, slots) {
218
+ const context = useTourContext();
219
+ return () => {
220
+ const consumerDisabled = isConsumerDisabled(attrs);
221
+ const disabled = capabilityDisabled() || consumerDisabled;
222
+ const buttonProps = {
223
+ "aria-controls": context.binding.value?.ids.popover,
224
+ "aria-disabled": disabled ? "true" : "false",
225
+ "aria-label": attrs["aria-label"] ?? ariaLabel() ?? label(),
226
+ "data-glow-tour-cancel-trigger": marker === "cancel" ? "" : undefined,
227
+ "data-glow-tour-consumer-disabled": consumerDisabled ? "true" : undefined,
228
+ "data-glow-tour-advance-trigger": marker === "advance" ? "" : undefined,
229
+ "data-glow-tour-previous-trigger": marker === "previous" ? "" : undefined,
230
+ disabled,
231
+ type: "button"
232
+ };
233
+ return h("button", mergeProps(attrs, buttonProps), slots.default?.(buttonProps) ?? label());
234
+ };
235
+ }
236
+ var GlowTourBackTrigger = defineComponent({
237
+ name: componentName("BackTrigger"),
238
+ inheritAttrs: false,
239
+ props: { ariaLabel: { type: String }, backLabel: { type: String } },
240
+ setup(props, { attrs, slots }) {
241
+ const context = useTourContext();
242
+ const snapshot = useTourSnapshot(context.tour);
243
+ const step = useStep();
244
+ const renderTrigger = trigger("previous", () => !snapshot.value.canPrevious || step()?.popover?.disablePreviousButton === true, () => props.backLabel ?? "Back step", () => props.ariaLabel, attrs, slots);
245
+ return () => step()?.popover?.hidePreviousButton ? null : renderTrigger();
246
+ }
247
+ });
248
+ var GlowTourAdvanceTrigger = defineComponent({
249
+ name: componentName("AdvanceTrigger"),
250
+ inheritAttrs: false,
251
+ props: {
252
+ ariaLabel: { type: String },
253
+ finishLabel: { type: String },
254
+ advanceLabel: { type: String }
255
+ },
256
+ setup(props, { attrs, slots }) {
257
+ const context = useTourContext();
258
+ const snapshot = useTourSnapshot(context.tour);
259
+ const step = useStep();
260
+ const renderTrigger = trigger("advance", () => !snapshot.value.canAdvance || step()?.popover?.disableAdvanceButton === true, () => {
261
+ return snapshot.value.isLastStep ? props.finishLabel ?? "Finish tour" : props.advanceLabel ?? "Advance step";
262
+ }, () => props.ariaLabel, attrs, slots);
263
+ return () => step()?.popover?.hideAdvanceButton ? null : renderTrigger();
264
+ }
265
+ });
266
+ var GlowTourCancelTrigger = defineComponent({
267
+ name: componentName("CancelTrigger"),
268
+ inheritAttrs: false,
269
+ props: { ariaLabel: { type: String } },
270
+ setup(props, { attrs, slots }) {
271
+ const context = useTourContext();
272
+ const snapshot = useTourSnapshot(context.tour);
273
+ const renderTrigger = trigger("cancel", () => !snapshot.value.canCancel, () => "Skip", () => props.ariaLabel, attrs, slots);
274
+ return () => snapshot.value.canCancel ? renderTrigger() : null;
275
+ }
276
+ });
277
+ export {
278
+ useTour,
279
+ GlowTourRoot,
280
+ GlowTourPopover,
281
+ GlowTourPointer,
282
+ GlowTourOverlay,
283
+ GlowTourHeader,
284
+ GlowTourFooter,
285
+ GlowTourContent,
286
+ GlowTourCancelTrigger,
287
+ GlowTourBackTrigger,
288
+ GlowTourAdvanceTrigger
289
+ };
package/config.d.ts ADDED
@@ -0,0 +1,37 @@
1
+ import type { BuiltinAction, ConfigValidationIssue, EventHandlerConfig as CoreEventHandlerConfig, LifecycleActionRef as CoreLifecycleActionRef, StepActionRef as CoreStepActionRef, StepConfig as CoreStepConfig, TransitionActionRef as CoreTransitionActionRef, WorkflowConfig as CoreWorkflowConfig, WorkflowDefinitionFromConfig as CoreWorkflowDefinitionFromConfig, CreateWorkflowFromConfigOptions, ValidateWorkflowConfigOptions } from "@glowhop/core-tour/config";
2
+ import { ConfigValidationError } from "@glowhop/core-tour/config";
3
+ import type { VueTourContent } from "./glow-tour.js";
4
+ export type { BuiltinAction, ConfigValidationIssue, CreateWorkflowFromConfigOptions, ValidateWorkflowConfigOptions, };
5
+ export { ConfigValidationError };
6
+ /** Vue workflow config: `WorkflowConfig` pre-bound to `VueTourContent`. */
7
+ export type WorkflowConfig = CoreWorkflowConfig<VueTourContent>;
8
+ /** Vue step config: `StepConfig` pre-bound to `VueTourContent`. */
9
+ export type StepConfig = CoreStepConfig<VueTourContent>;
10
+ /** Vue event handler config: `EventHandlerConfig` pre-bound to `VueTourContent`. */
11
+ export type EventHandlerConfig = CoreEventHandlerConfig<VueTourContent>;
12
+ /** Vue step action reference: `StepActionRef` pre-bound to `VueTourContent`. */
13
+ export type StepActionRef = CoreStepActionRef<VueTourContent>;
14
+ /** Vue transition action reference: `TransitionActionRef` pre-bound to `VueTourContent`. */
15
+ export type TransitionActionRef = CoreTransitionActionRef<VueTourContent>;
16
+ /** Vue lifecycle action reference: `LifecycleActionRef` pre-bound to `VueTourContent`. */
17
+ export type LifecycleActionRef = CoreLifecycleActionRef<VueTourContent>;
18
+ /** Vue workflow definition produced from config, pre-bound to `VueTourContent`. */
19
+ export type WorkflowDefinitionFromConfig = CoreWorkflowDefinitionFromConfig<VueTourContent>;
20
+ /**
21
+ * Builds a Vue `WorkflowDefinition` from a JSON-serializable config, pre-bound to
22
+ * `VueTourContent` so the result is accepted by `createGlowTour().run(...)` with no generic
23
+ * and no cast.
24
+ * @param config The parsed JSON (or equivalent plain object) to build from.
25
+ * @param options Options; see `CreateWorkflowFromConfigOptions`.
26
+ * @throws {ConfigValidationError} When the config is invalid.
27
+ * @returns A frozen `WorkflowDefinition` with `.source` attached.
28
+ */
29
+ export declare function createWorkflowFromConfig(config: unknown, options?: CreateWorkflowFromConfigOptions): WorkflowDefinitionFromConfig;
30
+ /**
31
+ * Validates and narrows an unknown value to a Vue `WorkflowConfig`.
32
+ * @param config The parsed JSON (or equivalent plain object) to validate.
33
+ * @param options Validation options; see `ValidateWorkflowConfigOptions`.
34
+ * @throws {ConfigValidationError} When one or more issues are found.
35
+ * @returns The same value, narrowed to `WorkflowConfig`.
36
+ */
37
+ export declare function validateWorkflowConfig(config: unknown, options?: ValidateWorkflowConfigOptions): WorkflowConfig;
package/config.js ADDED
@@ -0,0 +1,17 @@
1
+ // packages/vue/src/config.ts
2
+ import {
3
+ ConfigValidationError,
4
+ createWorkflowFromConfig as createCoreWorkflowFromConfig,
5
+ validateWorkflowConfig as validateCoreWorkflowConfig
6
+ } from "@glowhop/core-tour/config";
7
+ function createWorkflowFromConfig(config, options = {}) {
8
+ return createCoreWorkflowFromConfig(config, options);
9
+ }
10
+ function validateWorkflowConfig(config, options = {}) {
11
+ return validateCoreWorkflowConfig(config, options);
12
+ }
13
+ export {
14
+ validateWorkflowConfig,
15
+ createWorkflowFromConfig,
16
+ ConfigValidationError
17
+ };
package/glow-tour.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ import type { GlowTour as CoreGlowTour, StartOptions as CoreStartOptions, StepPropsStore as CoreStepPropsStore, TourState as CoreTourState, WorkflowDefinition as CoreWorkflowDefinition, GlowTourOptions } from "@glowhop/core-tour";
2
+ import type { VNodeChild } from "vue";
3
+ /** Vue content type: any valid Vue VNode child. */
4
+ export type VueTourContent = VNodeChild;
5
+ /** Vue tour controller instance. */
6
+ export type Tour = CoreGlowTour<VueTourContent>;
7
+ /** Vue tour state snapshot. */
8
+ export type TourState = CoreTourState<VueTourContent>;
9
+ /** Vue step properties store. */
10
+ export type StepPropsStore = CoreStepPropsStore<VueTourContent>;
11
+ /** Vue workflow definition. */
12
+ export type WorkflowDefinition = CoreWorkflowDefinition<VueTourContent>;
13
+ /** Vue tour start options. */
14
+ export type StartOptions = CoreStartOptions<VueTourContent>;
15
+ /**
16
+ * Creates a new GlowTour.js instance for Vue.
17
+ * @param options Tour options for error handling.
18
+ * @returns A tour controller ready to run Vue workflows.
19
+ */
20
+ export declare function createGlowTour(options?: GlowTourOptions): Tour;
package/glow-tour.js ADDED
@@ -0,0 +1,8 @@
1
+ // packages/vue/src/glow-tour.ts
2
+ import { createGlowTour as createCoreGlowTour } from "@glowhop/core-tour";
3
+ function createGlowTour(options = {}) {
4
+ return createCoreGlowTour(options);
5
+ }
6
+ export {
7
+ createGlowTour
8
+ };
package/index.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export type { GlowTourOptions } from "@glowhop/core-tour";
2
+ export { GlowTourDefault } from "./components/default-tour.js";
3
+ export type { PointerDirectionContent } from "./components/tour-components.js";
4
+ export { GlowTourAdvanceTrigger, GlowTourBackTrigger, GlowTourCancelTrigger, GlowTourContent, GlowTourFooter, GlowTourHeader, GlowTourOverlay, GlowTourPointer, GlowTourPopover, GlowTourRoot, useTour, } from "./components/tour-components.js";
5
+ export type { StartOptions, StepPropsStore, Tour, TourState, VueTourContent, WorkflowDefinition, } from "./glow-tour.js";
6
+ export { createGlowTour } from "./glow-tour.js";
package/index.js ADDED
@@ -0,0 +1,31 @@
1
+ // packages/vue/src/index.ts
2
+ import { GlowTourDefault } from "./components/default-tour.js";
3
+ import {
4
+ GlowTourAdvanceTrigger,
5
+ GlowTourBackTrigger,
6
+ GlowTourCancelTrigger,
7
+ GlowTourContent,
8
+ GlowTourFooter,
9
+ GlowTourHeader,
10
+ GlowTourOverlay,
11
+ GlowTourPointer,
12
+ GlowTourPopover,
13
+ GlowTourRoot,
14
+ useTour
15
+ } from "./components/tour-components.js";
16
+ import { createGlowTour } from "./glow-tour.js";
17
+ export {
18
+ useTour,
19
+ createGlowTour,
20
+ GlowTourRoot,
21
+ GlowTourPopover,
22
+ GlowTourPointer,
23
+ GlowTourOverlay,
24
+ GlowTourHeader,
25
+ GlowTourFooter,
26
+ GlowTourDefault,
27
+ GlowTourContent,
28
+ GlowTourCancelTrigger,
29
+ GlowTourBackTrigger,
30
+ GlowTourAdvanceTrigger
31
+ };
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@glowhop/vue-tour",
3
+ "version": "1.0.0",
4
+ "description": "Vue 3 adapter for GlowTour.js.",
5
+ "license": "MIT",
6
+ "homepage": "https://github.com/Glowhop/GlowTour.js#readme",
7
+ "bugs": {
8
+ "url": "https://github.com/Glowhop/GlowTour.js/issues"
9
+ },
10
+ "keywords": [
11
+ "tour",
12
+ "guided-tour",
13
+ "vue",
14
+ "onboarding"
15
+ ],
16
+ "engines": {
17
+ "node": ">=18.19.1"
18
+ },
19
+ "files": [
20
+ "**/*"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/Glowhop/GlowTour.js.git",
28
+ "directory": "packages/vue"
29
+ },
30
+ "type": "module",
31
+ "types": "./index.d.ts",
32
+ "exports": {
33
+ ".": {
34
+ "types": "./index.d.ts",
35
+ "import": "./index.js"
36
+ },
37
+ "./config": {
38
+ "types": "./config.d.ts",
39
+ "import": "./config.js"
40
+ }
41
+ },
42
+ "dependencies": {
43
+ "@glowhop/core-tour": "1.0.0"
44
+ },
45
+ "peerDependencies": {
46
+ "vue": "^3.3.0"
47
+ },
48
+ "sideEffects": false
49
+ }