@apollovisionlabs/guide-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,540 @@
1
+ "use client";
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/index.ts
22
+ var index_exports = {};
23
+ __export(index_exports, {
24
+ GuideContext: () => GuideContext,
25
+ GuideProvider: () => GuideProvider,
26
+ createBrowserStorage: () => createBrowserStorage,
27
+ createMemoryStorage: () => createMemoryStorage,
28
+ findMissingTargets: () => findMissingTargets,
29
+ initialTourState: () => initialTourState,
30
+ isLiteralRoute: () => isLiteralRoute,
31
+ matchRoute: () => matchRoute,
32
+ tourReducer: () => tourReducer,
33
+ useAnnouncer: () => useAnnouncer,
34
+ useElementRect: () => useElementRect,
35
+ useFocusTrap: () => useFocusTrap,
36
+ useGuideStep: () => useGuideStep,
37
+ usePrefersReducedMotion: () => usePrefersReducedMotion,
38
+ useTargetElement: () => useTargetElement,
39
+ useTour: () => useTour
40
+ });
41
+ module.exports = __toCommonJS(index_exports);
42
+
43
+ // src/storage.ts
44
+ function createMemoryStorage(initial = {}) {
45
+ const store = new Map(Object.entries(initial));
46
+ return {
47
+ async read(tourId) {
48
+ return store.get(tourId) ?? null;
49
+ },
50
+ async write(tourId, progress) {
51
+ store.set(tourId, progress);
52
+ }
53
+ };
54
+ }
55
+ function createBrowserStorage(namespace = "guide") {
56
+ const key = (tourId) => `${namespace}:${tourId}`;
57
+ const available = () => typeof window !== "undefined" && !!window.localStorage;
58
+ return {
59
+ async read(tourId) {
60
+ if (!available()) return null;
61
+ try {
62
+ const raw = window.localStorage.getItem(key(tourId));
63
+ return raw ? JSON.parse(raw) : null;
64
+ } catch {
65
+ return null;
66
+ }
67
+ },
68
+ async write(tourId, progress) {
69
+ if (!available()) return;
70
+ try {
71
+ window.localStorage.setItem(key(tourId), JSON.stringify(progress));
72
+ } catch {
73
+ }
74
+ }
75
+ };
76
+ }
77
+
78
+ // src/matchRoute.ts
79
+ function segments(value) {
80
+ const path = value.split("?")[0] ?? "";
81
+ const trimmed = path.replace(/\/+$/, "");
82
+ return (trimmed === "" ? "/" : trimmed).split("/");
83
+ }
84
+ function isLiteralRoute(pattern) {
85
+ return !pattern.includes(":") && !pattern.includes("*");
86
+ }
87
+ function matchRoute(pattern, pathname) {
88
+ const expected = segments(pattern);
89
+ const actual = segments(pathname);
90
+ for (let index = 0; index < expected.length; index += 1) {
91
+ const segment = expected[index];
92
+ if (segment === "*") return true;
93
+ const candidate = actual[index];
94
+ if (candidate === void 0) return false;
95
+ if (segment?.startsWith(":")) {
96
+ if (candidate === "") return false;
97
+ continue;
98
+ }
99
+ if (segment !== candidate) return false;
100
+ }
101
+ return expected.length === actual.length;
102
+ }
103
+
104
+ // src/tourMachine.ts
105
+ var initialTourState = {
106
+ tourId: null,
107
+ stepIndex: 0,
108
+ status: "idle"
109
+ };
110
+ function tourReducer(state, action) {
111
+ switch (action.type) {
112
+ case "START":
113
+ return { tourId: action.tourId, stepIndex: action.stepIndex, status: "running" };
114
+ // Navigating away from a paused tour resumes it: next() and previous() are public API, and calling them is an explicit request to move on.
115
+ case "NEXT": {
116
+ if (state.status !== "running" && state.status !== "paused") return state;
117
+ const isLast = state.stepIndex >= action.stepCount - 1;
118
+ return isLast ? { ...state, status: "completed" } : { ...state, stepIndex: state.stepIndex + 1, status: "running" };
119
+ }
120
+ case "PREVIOUS":
121
+ if (state.status !== "running" && state.status !== "paused") return state;
122
+ return { ...state, stepIndex: Math.max(0, state.stepIndex - 1), status: "running" };
123
+ case "PAUSE":
124
+ return state.status === "running" ? { ...state, status: "paused" } : state;
125
+ case "RESUME":
126
+ return state.status === "paused" ? { ...state, status: "running" } : state;
127
+ case "STOP":
128
+ return initialTourState;
129
+ default:
130
+ return state;
131
+ }
132
+ }
133
+
134
+ // src/useTargetElement.ts
135
+ var import_react = require("react");
136
+
137
+ // src/selector.ts
138
+ function escapeAttributeValue(value) {
139
+ if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
140
+ return CSS.escape(value);
141
+ }
142
+ return value.replace(/["\\]/g, "\\$&");
143
+ }
144
+ function targetSelector(target, attribute) {
145
+ return `[${attribute}="${escapeAttributeValue(target)}"]`;
146
+ }
147
+
148
+ // src/useTargetElement.ts
149
+ var DEFAULT_TIMEOUT_MS = 5e3;
150
+ var EMPTY = { target: null, element: null, timedOut: false };
151
+ function useTargetElement(target, options = {}) {
152
+ const { timeoutMs = DEFAULT_TIMEOUT_MS, attribute = "data-guide" } = options;
153
+ const [state, setState] = (0, import_react.useState)(EMPTY);
154
+ (0, import_react.useEffect)(() => {
155
+ if (!target || typeof document === "undefined") {
156
+ setState({ target, element: null, timedOut: false });
157
+ return;
158
+ }
159
+ const selector = targetSelector(target, attribute);
160
+ const find = () => document.querySelector(selector);
161
+ const found = find();
162
+ if (found) {
163
+ setState({ target, element: found, timedOut: false });
164
+ return;
165
+ }
166
+ setState({ target, element: null, timedOut: false });
167
+ let timer;
168
+ const observer = new MutationObserver(() => {
169
+ const candidate = find();
170
+ if (!candidate) return;
171
+ observer.disconnect();
172
+ if (timer) clearTimeout(timer);
173
+ setState({ target, element: candidate, timedOut: false });
174
+ });
175
+ observer.observe(document.body, { childList: true, subtree: true, attributes: true });
176
+ timer = setTimeout(() => {
177
+ setState({ target, element: null, timedOut: true });
178
+ }, timeoutMs);
179
+ return () => {
180
+ observer.disconnect();
181
+ if (timer) clearTimeout(timer);
182
+ };
183
+ }, [target, timeoutMs, attribute]);
184
+ const current = state.target === target ? state : EMPTY;
185
+ return { element: current.element, timedOut: current.timedOut };
186
+ }
187
+
188
+ // src/useElementRect.ts
189
+ var import_react2 = require("react");
190
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? import_react2.useLayoutEffect : import_react2.useEffect;
191
+ function sameRect(a, b) {
192
+ return a.top === b.top && a.left === b.left && a.width === b.width && a.height === b.height;
193
+ }
194
+ function useElementRect(element) {
195
+ const [rect, setRect] = (0, import_react2.useState)(null);
196
+ useIsomorphicLayoutEffect(() => {
197
+ if (!element) {
198
+ setRect(null);
199
+ return;
200
+ }
201
+ const measure = () => {
202
+ const next = element.getBoundingClientRect();
203
+ setRect(
204
+ (previous) => previous && sameRect(previous, next) ? previous : { top: next.top, left: next.left, width: next.width, height: next.height }
205
+ );
206
+ };
207
+ measure();
208
+ const observer = typeof ResizeObserver !== "undefined" ? new ResizeObserver(measure) : null;
209
+ observer?.observe(element);
210
+ window.addEventListener("scroll", measure, true);
211
+ window.addEventListener("resize", measure);
212
+ return () => {
213
+ observer?.disconnect();
214
+ window.removeEventListener("scroll", measure, true);
215
+ window.removeEventListener("resize", measure);
216
+ };
217
+ }, [element]);
218
+ return rect;
219
+ }
220
+
221
+ // src/a11y.ts
222
+ var import_react3 = require("react");
223
+ var FOCUSABLE = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
224
+ function useFocusTrap(container, active, options = {}) {
225
+ const { initialFocus = "first" } = options;
226
+ (0, import_react3.useEffect)(() => {
227
+ if (!container || !active) return;
228
+ const previouslyFocused = document.activeElement;
229
+ const focusable = () => Array.from(container.querySelectorAll(FOCUSABLE));
230
+ const first = initialFocus === "container" ? void 0 : focusable()[0];
231
+ if (first) first.focus();
232
+ else container.focus();
233
+ const onKeyDown = (event) => {
234
+ if (event.key !== "Tab") return;
235
+ const elements = focusable();
236
+ if (elements.length === 0) return;
237
+ const firstElement = elements[0];
238
+ const lastElement = elements[elements.length - 1];
239
+ if (event.shiftKey && document.activeElement === firstElement) {
240
+ event.preventDefault();
241
+ lastElement.focus();
242
+ } else if (!event.shiftKey && document.activeElement === lastElement) {
243
+ event.preventDefault();
244
+ firstElement.focus();
245
+ }
246
+ };
247
+ document.addEventListener("keydown", onKeyDown, true);
248
+ return () => {
249
+ document.removeEventListener("keydown", onKeyDown, true);
250
+ previouslyFocused?.focus?.();
251
+ };
252
+ }, [container, active, initialFocus]);
253
+ }
254
+ function announcerNode() {
255
+ const existing = document.querySelector("[data-guide-announcer]");
256
+ if (existing) return existing;
257
+ const node = document.createElement("div");
258
+ node.setAttribute("data-guide-announcer", "");
259
+ node.setAttribute("aria-live", "polite");
260
+ node.setAttribute("aria-atomic", "true");
261
+ node.style.position = "absolute";
262
+ node.style.width = "1px";
263
+ node.style.height = "1px";
264
+ node.style.overflow = "hidden";
265
+ node.style.clip = "rect(0 0 0 0)";
266
+ node.style.whiteSpace = "nowrap";
267
+ document.body.appendChild(node);
268
+ return node;
269
+ }
270
+ function useAnnouncer() {
271
+ return (0, import_react3.useCallback)((message) => {
272
+ if (typeof document === "undefined") return;
273
+ announcerNode().textContent = message;
274
+ }, []);
275
+ }
276
+ function usePrefersReducedMotion() {
277
+ const [reduced, setReduced] = (0, import_react3.useState)(false);
278
+ (0, import_react3.useEffect)(() => {
279
+ if (typeof window === "undefined" || !window.matchMedia) return;
280
+ const query = window.matchMedia("(prefers-reduced-motion: reduce)");
281
+ setReduced(query.matches);
282
+ const onChange = (event) => setReduced(event.matches);
283
+ query.addEventListener("change", onChange);
284
+ return () => query.removeEventListener("change", onChange);
285
+ }, []);
286
+ return reduced;
287
+ }
288
+
289
+ // src/GuideProvider.tsx
290
+ var import_react4 = require("react");
291
+
292
+ // src/validateTour.ts
293
+ function findMissingTargets(tour, location, attribute = "data-guide") {
294
+ if (typeof document === "undefined") return [];
295
+ return tour.steps.filter((step) => !step.route || location === void 0 || matchRoute(step.route, location)).map((step) => step.target).filter((target) => !document.querySelector(targetSelector(target, attribute)));
296
+ }
297
+
298
+ // src/GuideProvider.tsx
299
+ var import_jsx_runtime = require("react/jsx-runtime");
300
+ var GuideContext = (0, import_react4.createContext)(null);
301
+ function resolveText(value, key, translate) {
302
+ if (value !== void 0) return value;
303
+ if (key === void 0) return "";
304
+ return translate ? translate(key) : key;
305
+ }
306
+ function GuideProvider({
307
+ tours,
308
+ children,
309
+ navigate,
310
+ location,
311
+ storage,
312
+ translate,
313
+ onEvent,
314
+ onMissingTarget = "wait",
315
+ targetTimeoutMs = 5e3
316
+ }) {
317
+ const toursById = (0, import_react4.useMemo)(() => {
318
+ const map = /* @__PURE__ */ new Map();
319
+ for (const candidate of tours) {
320
+ if (map.has(candidate.id)) {
321
+ throw new Error(`[guide] duplicate tour id: ${candidate.id}`);
322
+ }
323
+ map.set(candidate.id, candidate);
324
+ }
325
+ return map;
326
+ }, [tours]);
327
+ const [state, dispatch] = (0, import_react4.useReducer)(tourReducer, initialTourState);
328
+ const announce = useAnnouncer();
329
+ const focusOriginRef = (0, import_react4.useRef)(null);
330
+ const storageWarnedRef = (0, import_react4.useRef)(false);
331
+ const warnStorageFailure = (0, import_react4.useCallback)((error) => {
332
+ if (storageWarnedRef.current) return;
333
+ storageWarnedRef.current = true;
334
+ console.warn("[guide] storage failed; tour progress will not be persisted", error);
335
+ }, []);
336
+ const onEventRef = (0, import_react4.useRef)(onEvent);
337
+ onEventRef.current = onEvent;
338
+ const emit = (0, import_react4.useCallback)((event) => onEventRef.current?.(event), []);
339
+ const tour = state.tourId ? toursById.get(state.tourId) ?? null : null;
340
+ const step = tour ? tour.steps[state.stepIndex] ?? null : null;
341
+ const isActive = state.status === "running" || state.status === "paused";
342
+ const routeMatches = !step?.route || location === void 0 || matchRoute(step.route, location);
343
+ const { element, timedOut: targetTimedOut } = useTargetElement(
344
+ isActive && routeMatches && step ? step.target : null,
345
+ { timeoutMs: targetTimeoutMs }
346
+ );
347
+ const rect = useElementRect(element);
348
+ const waitingForRoute = isActive && !!step && !routeMatches;
349
+ const [routeTimeoutStep, setRouteTimeoutStep] = (0, import_react4.useState)(null);
350
+ (0, import_react4.useEffect)(() => {
351
+ if (!waitingForRoute) {
352
+ setRouteTimeoutStep(null);
353
+ return;
354
+ }
355
+ const timer = setTimeout(() => setRouteTimeoutStep(step), targetTimeoutMs);
356
+ return () => clearTimeout(timer);
357
+ }, [waitingForRoute, step, targetTimeoutMs]);
358
+ const timedOut = targetTimedOut || waitingForRoute && routeTimeoutStep === step;
359
+ const next = (0, import_react4.useCallback)(() => {
360
+ if (!tour) return;
361
+ const isLast = state.stepIndex >= tour.steps.length - 1;
362
+ dispatch({ type: "NEXT", stepCount: tour.steps.length });
363
+ if (isLast) emit({ type: "tour:complete", tourId: tour.id });
364
+ }, [tour, state.stepIndex, emit]);
365
+ const previous = (0, import_react4.useCallback)(() => dispatch({ type: "PREVIOUS" }), []);
366
+ const stop = (0, import_react4.useCallback)(() => {
367
+ if (tour) emit({ type: "tour:stop", tourId: tour.id, stepIndex: state.stepIndex });
368
+ dispatch({ type: "STOP" });
369
+ }, [tour, state.stepIndex, emit]);
370
+ const navigationRef = (0, import_react4.useRef)({
371
+ step: null,
372
+ destination: null
373
+ });
374
+ const start = (0, import_react4.useCallback)(
375
+ async (tourId, options) => {
376
+ if (state.tourId === tourId && state.status === "running") return;
377
+ const target = toursById.get(tourId);
378
+ if (!target) throw new Error(`[guide] unknown tour: ${tourId}`);
379
+ if (target.steps.length === 0) {
380
+ throw new Error(`[guide] tour has no steps: ${tourId}`);
381
+ }
382
+ if (typeof document !== "undefined") {
383
+ focusOriginRef.current = document.activeElement;
384
+ }
385
+ let stepIndex = options?.from ?? 0;
386
+ if (options?.from === void 0 && options?.resume !== false && storage) {
387
+ let progress = null;
388
+ try {
389
+ progress = await storage.read(tourId);
390
+ } catch (error) {
391
+ warnStorageFailure(error);
392
+ }
393
+ if (progress?.status === "in-progress") stepIndex = progress.stepIndex;
394
+ }
395
+ if (process.env.NODE_ENV !== "production") {
396
+ const missing = findMissingTargets(target, location);
397
+ if (missing.length > 0) {
398
+ console.warn(
399
+ `[guide] tour "${tourId}" declares targets that are not present on this page: ${missing.join(", ")}`
400
+ );
401
+ }
402
+ }
403
+ navigationRef.current = { step: null, destination: null };
404
+ dispatch({ type: "START", tourId, stepIndex });
405
+ emit({ type: "tour:start", tourId, stepIndex });
406
+ },
407
+ [toursById, storage, location, emit, state.tourId, state.status, warnStorageFailure]
408
+ );
409
+ (0, import_react4.useEffect)(() => {
410
+ if (!isActive || !step || routeMatches) return;
411
+ if (navigationRef.current.step !== step) {
412
+ navigationRef.current = { step, destination: null };
413
+ }
414
+ const destination = step.navigateTo ?? (step.route && isLiteralRoute(step.route) ? step.route : null);
415
+ if (!destination) return;
416
+ if (navigationRef.current.destination === destination) return;
417
+ if (!navigate) {
418
+ console.warn("[guide] a step declares a route but no navigate function was provided");
419
+ return;
420
+ }
421
+ navigationRef.current.destination = destination;
422
+ navigate(destination);
423
+ }, [isActive, step, routeMatches, navigate]);
424
+ (0, import_react4.useEffect)(() => {
425
+ if (!timedOut || !tour || !step) return;
426
+ emit({
427
+ type: "target:missing",
428
+ tourId: tour.id,
429
+ stepIndex: state.stepIndex,
430
+ target: step.target
431
+ });
432
+ const policy = step.onMissingTarget ?? onMissingTarget;
433
+ if (policy === "skip") dispatch({ type: "NEXT", stepCount: tour.steps.length });
434
+ else if (policy === "error") dispatch({ type: "STOP" });
435
+ else dispatch({ type: "PAUSE" });
436
+ }, [timedOut, tour, step, state.stepIndex, onMissingTarget, emit]);
437
+ (0, import_react4.useEffect)(() => {
438
+ if (state.status === "paused" && element) dispatch({ type: "RESUME" });
439
+ }, [state.status, element]);
440
+ (0, import_react4.useEffect)(() => {
441
+ if (state.status !== "running" || !tour || !step || !element) return;
442
+ emit({
443
+ type: "step:show",
444
+ tourId: tour.id,
445
+ stepIndex: state.stepIndex,
446
+ target: step.target
447
+ });
448
+ announce(`${state.stepIndex + 1} / ${tour.steps.length}`);
449
+ }, [state.status, state.stepIndex, tour, step, element, emit, announce]);
450
+ (0, import_react4.useEffect)(() => {
451
+ if (!storage || !state.tourId) return;
452
+ const status = state.status === "running" ? "in-progress" : state.status === "completed" ? "completed" : null;
453
+ if (!status) return;
454
+ try {
455
+ void Promise.resolve(
456
+ storage.write(state.tourId, { status, stepIndex: state.stepIndex })
457
+ ).catch(warnStorageFailure);
458
+ } catch (error) {
459
+ warnStorageFailure(error);
460
+ }
461
+ }, [storage, state.tourId, state.status, state.stepIndex, warnStorageFailure]);
462
+ (0, import_react4.useEffect)(() => {
463
+ if (state.status !== "idle" && state.status !== "completed") return;
464
+ const origin = focusOriginRef.current;
465
+ if (!origin) return;
466
+ focusOriginRef.current = null;
467
+ if (typeof document !== "undefined" && document.contains(origin)) origin.focus();
468
+ }, [state.status]);
469
+ const activeStep = (0, import_react4.useMemo)(() => {
470
+ if (!tour || !step || !isActive) return null;
471
+ return {
472
+ tourId: tour.id,
473
+ step,
474
+ stepIndex: state.stepIndex,
475
+ stepCount: tour.steps.length,
476
+ element,
477
+ rect,
478
+ title: resolveText(step.title, step.titleKey, translate),
479
+ body: resolveText(step.body, step.bodyKey, translate),
480
+ isFirst: state.stepIndex === 0,
481
+ isLast: state.stepIndex === tour.steps.length - 1,
482
+ next,
483
+ previous,
484
+ stop
485
+ };
486
+ }, [tour, step, isActive, state.stepIndex, element, rect, translate, next, previous, stop]);
487
+ const value = (0, import_react4.useMemo)(
488
+ () => ({ state, activeStep, start, next, previous, stop }),
489
+ [state, activeStep, start, next, previous, stop]
490
+ );
491
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GuideContext.Provider, { value, children });
492
+ }
493
+
494
+ // src/useTour.ts
495
+ var import_react5 = require("react");
496
+ function useTour(tourId) {
497
+ const context = (0, import_react5.useContext)(GuideContext);
498
+ if (!context) throw new Error("[guide] useTour must be used inside a GuideProvider");
499
+ const { state, start, next, previous, stop } = context;
500
+ const isCurrent = state.tourId === tourId;
501
+ return (0, import_react5.useMemo)(
502
+ () => ({
503
+ start: (options) => start(tourId, options),
504
+ next,
505
+ previous,
506
+ stop,
507
+ status: isCurrent ? state.status : "idle",
508
+ stepIndex: isCurrent ? state.stepIndex : 0
509
+ }),
510
+ [tourId, start, next, previous, stop, isCurrent, state.status, state.stepIndex]
511
+ );
512
+ }
513
+
514
+ // src/useGuideStep.ts
515
+ var import_react6 = require("react");
516
+ function useGuideStep() {
517
+ const context = (0, import_react6.useContext)(GuideContext);
518
+ if (!context) throw new Error("[guide] useGuideStep must be used inside a GuideProvider");
519
+ return context.activeStep;
520
+ }
521
+ // Annotate the CommonJS export names for ESM import in node:
522
+ 0 && (module.exports = {
523
+ GuideContext,
524
+ GuideProvider,
525
+ createBrowserStorage,
526
+ createMemoryStorage,
527
+ findMissingTargets,
528
+ initialTourState,
529
+ isLiteralRoute,
530
+ matchRoute,
531
+ tourReducer,
532
+ useAnnouncer,
533
+ useElementRect,
534
+ useFocusTrap,
535
+ useGuideStep,
536
+ usePrefersReducedMotion,
537
+ useTargetElement,
538
+ useTour
539
+ });
540
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/storage.ts","../src/matchRoute.ts","../src/tourMachine.ts","../src/useTargetElement.ts","../src/selector.ts","../src/useElementRect.ts","../src/a11y.ts","../src/GuideProvider.tsx","../src/validateTour.ts","../src/useTour.ts","../src/useGuideStep.ts"],"sourcesContent":["export * from './types'\nexport * from './storage'\nexport * from './matchRoute'\nexport * from './tourMachine'\nexport * from './useTargetElement'\nexport * from './useElementRect'\nexport * from './a11y'\nexport * from './GuideProvider'\nexport * from './useTour'\nexport * from './validateTour'\nexport * from './useGuideStep'\n","import type { GuideStorage, TourProgress } from './types'\n\nexport function createMemoryStorage(\n initial: Record<string, TourProgress> = {},\n): GuideStorage {\n const store = new Map<string, TourProgress>(Object.entries(initial))\n return {\n async read(tourId) {\n return store.get(tourId) ?? null\n },\n async write(tourId, progress) {\n store.set(tourId, progress)\n },\n }\n}\n\nexport function createBrowserStorage(namespace = 'guide'): GuideStorage {\n const key = (tourId: string) => `${namespace}:${tourId}`\n const available = () => typeof window !== 'undefined' && !!window.localStorage\n\n return {\n async read(tourId) {\n if (!available()) return null\n try {\n const raw = window.localStorage.getItem(key(tourId))\n return raw ? (JSON.parse(raw) as TourProgress) : null\n } catch {\n return null\n }\n },\n async write(tourId, progress) {\n if (!available()) return\n try {\n window.localStorage.setItem(key(tourId), JSON.stringify(progress))\n } catch {\n // quota exceeded or storage blocked: persistence is optional\n }\n },\n }\n}\n","function segments(value: string): string[] {\n const path = value.split('?')[0] ?? ''\n const trimmed = path.replace(/\\/+$/, '')\n return (trimmed === '' ? '/' : trimmed).split('/')\n}\n\nexport function isLiteralRoute(pattern: string): boolean {\n return !pattern.includes(':') && !pattern.includes('*')\n}\n\nexport function matchRoute(pattern: string, pathname: string): boolean {\n const expected = segments(pattern)\n const actual = segments(pathname)\n\n for (let index = 0; index < expected.length; index += 1) {\n const segment = expected[index]\n if (segment === '*') return true\n\n const candidate = actual[index]\n if (candidate === undefined) return false\n\n if (segment?.startsWith(':')) {\n if (candidate === '') return false\n continue\n }\n\n if (segment !== candidate) return false\n }\n\n return expected.length === actual.length\n}\n","import type { TourStatus } from './types'\n\nexport interface TourState {\n tourId: string | null\n stepIndex: number\n status: TourStatus\n}\n\nexport type TourAction =\n | { type: 'START'; tourId: string; stepIndex: number }\n | { type: 'NEXT'; stepCount: number }\n | { type: 'PREVIOUS' }\n | { type: 'PAUSE' }\n | { type: 'RESUME' }\n | { type: 'STOP' }\n\nexport const initialTourState: TourState = {\n tourId: null,\n stepIndex: 0,\n status: 'idle',\n}\n\nexport function tourReducer(state: TourState, action: TourAction): TourState {\n switch (action.type) {\n case 'START':\n return { tourId: action.tourId, stepIndex: action.stepIndex, status: 'running' }\n\n // Navigating away from a paused tour resumes it: next() and previous() are public API, and calling them is an explicit request to move on.\n case 'NEXT': {\n if (state.status !== 'running' && state.status !== 'paused') return state\n const isLast = state.stepIndex >= action.stepCount - 1\n return isLast\n ? { ...state, status: 'completed' }\n : { ...state, stepIndex: state.stepIndex + 1, status: 'running' }\n }\n\n case 'PREVIOUS':\n if (state.status !== 'running' && state.status !== 'paused') return state\n return { ...state, stepIndex: Math.max(0, state.stepIndex - 1), status: 'running' }\n\n case 'PAUSE':\n return state.status === 'running' ? { ...state, status: 'paused' } : state\n\n case 'RESUME':\n return state.status === 'paused' ? { ...state, status: 'running' } : state\n\n case 'STOP':\n return initialTourState\n\n default:\n return state\n }\n}\n","import { useEffect, useState } from 'react'\nimport { targetSelector } from './selector'\n\nconst DEFAULT_TIMEOUT_MS = 5000\n\nexport interface UseTargetElementOptions {\n timeoutMs?: number\n attribute?: string\n}\n\ninterface TargetState {\n target: string | null\n element: HTMLElement | null\n timedOut: boolean\n}\n\nconst EMPTY: TargetState = { target: null, element: null, timedOut: false }\n\nexport function useTargetElement(\n target: string | null,\n options: UseTargetElementOptions = {},\n): { element: HTMLElement | null; timedOut: boolean } {\n const { timeoutMs = DEFAULT_TIMEOUT_MS, attribute = 'data-guide' } = options\n const [state, setState] = useState<TargetState>(EMPTY)\n\n useEffect(() => {\n if (!target || typeof document === 'undefined') {\n setState({ target, element: null, timedOut: false })\n return\n }\n\n const selector = targetSelector(target, attribute)\n const find = () => document.querySelector<HTMLElement>(selector)\n\n const found = find()\n if (found) {\n setState({ target, element: found, timedOut: false })\n return\n }\n\n setState({ target, element: null, timedOut: false })\n\n let timer: ReturnType<typeof setTimeout> | undefined\n\n const observer = new MutationObserver(() => {\n const candidate = find()\n if (!candidate) return\n observer.disconnect()\n if (timer) clearTimeout(timer)\n setState({ target, element: candidate, timedOut: false })\n })\n\n observer.observe(document.body, { childList: true, subtree: true, attributes: true })\n\n timer = setTimeout(() => {\n // Do not disconnect: the wait policy must be able to resume if the target appears later.\n // The observer callback and the cleanup take care of disconnecting.\n setState({ target, element: null, timedOut: true })\n }, timeoutMs)\n\n return () => {\n observer.disconnect()\n if (timer) clearTimeout(timer)\n }\n }, [target, timeoutMs, attribute])\n\n // Only expose the state when it matches the requested target: otherwise the caller would read\n // the previous step's state until the effect runs, and would skip twice.\n const current = state.target === target ? state : EMPTY\n return { element: current.element, timedOut: current.timedOut }\n}\n","// Target selector construction, shared by runtime resolution and by development-time\n// validation: a target containing a quote must be escaped on both paths, otherwise validation\n// throws a SyntaxError where resolution works.\nexport function escapeAttributeValue(value: string): string {\n if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') {\n return CSS.escape(value)\n }\n return value.replace(/[\"\\\\]/g, '\\\\$&')\n}\n\nexport function targetSelector(target: string, attribute: string): string {\n return `[${attribute}=\"${escapeAttributeValue(target)}\"]`\n}\n","import { useEffect, useLayoutEffect, useState } from 'react'\nimport type { Rect } from './types'\n\n// Measure before paint: on a step change, a plain useEffect would let one frame through with\n// the spotlight still on the previous step's target.\nconst useIsomorphicLayoutEffect =\n typeof window !== 'undefined' ? useLayoutEffect : useEffect\n\nfunction sameRect(a: Rect, b: DOMRect): boolean {\n return a.top === b.top && a.left === b.left && a.width === b.width && a.height === b.height\n}\n\nexport function useElementRect(element: HTMLElement | null): Rect | null {\n const [rect, setRect] = useState<Rect | null>(null)\n\n useIsomorphicLayoutEffect(() => {\n if (!element) {\n setRect(null)\n return\n }\n\n const measure = () => {\n const next = element.getBoundingClientRect()\n setRect((previous) =>\n previous && sameRect(previous, next)\n ? previous\n : { top: next.top, left: next.left, width: next.width, height: next.height },\n )\n }\n\n measure()\n\n const observer =\n typeof ResizeObserver !== 'undefined' ? new ResizeObserver(measure) : null\n observer?.observe(element)\n\n window.addEventListener('scroll', measure, true)\n window.addEventListener('resize', measure)\n\n return () => {\n observer?.disconnect()\n window.removeEventListener('scroll', measure, true)\n window.removeEventListener('resize', measure)\n }\n }, [element])\n\n return rect\n}\n","import { useCallback, useEffect, useState } from 'react'\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\nexport interface UseFocusTrapOptions {\n /**\n * Element that receives focus on entry. 'first' takes the first focusable element; 'container'\n * takes the container itself, which must then carry tabIndex={-1}. Defaults to 'first'.\n */\n initialFocus?: 'first' | 'container'\n}\n\nexport function useFocusTrap(\n container: HTMLElement | null,\n active: boolean,\n options: UseFocusTrapOptions = {},\n): void {\n const { initialFocus = 'first' } = options\n\n useEffect(() => {\n if (!container || !active) return\n\n const previouslyFocused = document.activeElement as HTMLElement | null\n // No visibility filter: the selector already excludes disabled elements and elements out of\n // the tab order, and the popover mounts or unmounts its controls rather than hiding them.\n const focusable = () => Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE))\n\n // 'container' avoids putting focus on an actionable button: a reflex Enter after an arrow\n // key must not close the tour.\n const first = initialFocus === 'container' ? undefined : focusable()[0]\n if (first) first.focus()\n else container.focus()\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key !== 'Tab') return\n const elements = focusable()\n if (elements.length === 0) return\n\n const firstElement = elements[0]!\n const lastElement = elements[elements.length - 1]!\n\n if (event.shiftKey && document.activeElement === firstElement) {\n event.preventDefault()\n lastElement.focus()\n } else if (!event.shiftKey && document.activeElement === lastElement) {\n event.preventDefault()\n firstElement.focus()\n }\n }\n\n document.addEventListener('keydown', onKeyDown, true)\n\n return () => {\n document.removeEventListener('keydown', onKeyDown, true)\n previouslyFocused?.focus?.()\n }\n }, [container, active, initialFocus])\n}\n\nfunction announcerNode(): HTMLElement {\n const existing = document.querySelector<HTMLElement>('[data-guide-announcer]')\n if (existing) return existing\n\n const node = document.createElement('div')\n node.setAttribute('data-guide-announcer', '')\n node.setAttribute('aria-live', 'polite')\n node.setAttribute('aria-atomic', 'true')\n node.style.position = 'absolute'\n node.style.width = '1px'\n node.style.height = '1px'\n node.style.overflow = 'hidden'\n node.style.clip = 'rect(0 0 0 0)'\n node.style.whiteSpace = 'nowrap'\n document.body.appendChild(node)\n return node\n}\n\nexport function useAnnouncer(): (message: string) => void {\n return useCallback((message: string) => {\n if (typeof document === 'undefined') return\n announcerNode().textContent = message\n }, [])\n}\n\nexport function usePrefersReducedMotion(): boolean {\n const [reduced, setReduced] = useState(false)\n\n useEffect(() => {\n if (typeof window === 'undefined' || !window.matchMedia) return\n const query = window.matchMedia('(prefers-reduced-motion: reduce)')\n setReduced(query.matches)\n const onChange = (event: MediaQueryListEvent) => setReduced(event.matches)\n query.addEventListener('change', onChange)\n return () => query.removeEventListener('change', onChange)\n }, [])\n\n return reduced\n}\n","'use client'\n\nimport {\n createContext,\n useCallback,\n useEffect,\n useMemo,\n useReducer,\n useRef,\n useState,\n type ReactNode,\n} from 'react'\nimport type {\n GuideEvent,\n GuideStorage,\n MissingTargetPolicy,\n Rect,\n Step,\n Tour,\n TourProgress,\n Translate,\n} from './types'\nimport { initialTourState, tourReducer, type TourState } from './tourMachine'\nimport { isLiteralRoute, matchRoute } from './matchRoute'\nimport { useTargetElement } from './useTargetElement'\nimport { useElementRect } from './useElementRect'\nimport { useAnnouncer } from './a11y'\nimport { findMissingTargets } from './validateTour'\n\nexport interface ActiveStep {\n tourId: string\n step: Step\n stepIndex: number\n stepCount: number\n element: HTMLElement | null\n rect: Rect | null\n title: string\n body: string\n isFirst: boolean\n isLast: boolean\n next: () => void\n previous: () => void\n stop: () => void\n}\n\nexport interface GuideContextValue {\n state: TourState\n activeStep: ActiveStep | null\n start: (tourId: string, options?: { from?: number; resume?: boolean }) => Promise<void>\n next: () => void\n previous: () => void\n stop: () => void\n}\n\nexport const GuideContext = createContext<GuideContextValue | null>(null)\n\nexport interface GuideProviderProps {\n tours: Tour[]\n children: ReactNode\n navigate?: (path: string) => void\n location?: string\n storage?: GuideStorage\n translate?: Translate\n onEvent?: (event: GuideEvent) => void\n onMissingTarget?: MissingTargetPolicy\n targetTimeoutMs?: number\n}\n\nfunction resolveText(\n value: string | undefined,\n key: string | undefined,\n translate: Translate | undefined,\n): string {\n if (value !== undefined) return value\n if (key === undefined) return ''\n return translate ? translate(key) : key\n}\n\nexport function GuideProvider({\n tours,\n children,\n navigate,\n location,\n storage,\n translate,\n onEvent,\n onMissingTarget = 'wait',\n targetTimeoutMs = 5000,\n}: GuideProviderProps) {\n const toursById = useMemo(() => {\n const map = new Map<string, Tour>()\n for (const candidate of tours) {\n if (map.has(candidate.id)) {\n throw new Error(`[guide] duplicate tour id: ${candidate.id}`)\n }\n map.set(candidate.id, candidate)\n }\n return map\n }, [tours])\n\n const [state, dispatch] = useReducer(tourReducer, initialTourState)\n const announce = useAnnouncer()\n\n // Element that held focus when the tour started: the popover unmounts and remounts on every\n // step, so its own focus trap cannot restore focus to that origin.\n const focusOriginRef = useRef<HTMLElement | null>(null)\n const storageWarnedRef = useRef(false)\n\n const warnStorageFailure = useCallback((error: unknown) => {\n if (storageWarnedRef.current) return\n storageWarnedRef.current = true\n console.warn('[guide] storage failed; tour progress will not be persisted', error)\n }, [])\n\n const onEventRef = useRef(onEvent)\n onEventRef.current = onEvent\n const emit = useCallback((event: GuideEvent) => onEventRef.current?.(event), [])\n\n const tour = state.tourId ? (toursById.get(state.tourId) ?? null) : null\n const step = tour ? (tour.steps[state.stepIndex] ?? null) : null\n const isActive = state.status === 'running' || state.status === 'paused'\n\n const routeMatches =\n !step?.route || location === undefined || matchRoute(step.route, location)\n\n const { element, timedOut: targetTimedOut } = useTargetElement(\n isActive && routeMatches && step ? step.target : null,\n { timeoutMs: targetTimeoutMs },\n )\n const rect = useElementRect(element)\n\n // A step whose route never matches requests no target, so no timeout is running. Without this\n // timer, a wrong route pattern or a failed navigation would leave the tour running, invisible\n // and with no way out. The timer armed here is what makes the policy apply.\n const waitingForRoute = isActive && !!step && !routeMatches\n // The expired step is stored rather than a boolean: otherwise the next step would inherit the\n // previous one's expiry for one render and the policy would apply twice.\n const [routeTimeoutStep, setRouteTimeoutStep] = useState<Step | null>(null)\n\n useEffect(() => {\n if (!waitingForRoute) {\n setRouteTimeoutStep(null)\n return\n }\n const timer = setTimeout(() => setRouteTimeoutStep(step), targetTimeoutMs)\n return () => clearTimeout(timer)\n }, [waitingForRoute, step, targetTimeoutMs])\n\n const timedOut = targetTimedOut || (waitingForRoute && routeTimeoutStep === step)\n\n const next = useCallback(() => {\n if (!tour) return\n const isLast = state.stepIndex >= tour.steps.length - 1\n dispatch({ type: 'NEXT', stepCount: tour.steps.length })\n if (isLast) emit({ type: 'tour:complete', tourId: tour.id })\n }, [tour, state.stepIndex, emit])\n\n const previous = useCallback(() => dispatch({ type: 'PREVIOUS' }), [])\n\n const stop = useCallback(() => {\n if (tour) emit({ type: 'tour:stop', tourId: tour.id, stepIndex: state.stepIndex })\n dispatch({ type: 'STOP' })\n }, [tour, state.stepIndex, emit])\n\n // Delegated navigation: the step lives elsewhere, so we ask for the move.\n // The destination already requested for the current step is kept in a ref: without it, if the\n // route never matches, this effect would call navigate again on every render.\n const navigationRef = useRef<{ step: Step | null; destination: string | null }>({\n step: null,\n destination: null,\n })\n\n const start = useCallback(\n async (tourId: string, options?: { from?: number; resume?: boolean }) => {\n // Reentrancy: a second call while this same tour is running would re-read persistence and\n // could move the progress backwards. Switching to another tour stays allowed.\n if (state.tourId === tourId && state.status === 'running') return\n\n const target = toursById.get(tourId)\n if (!target) throw new Error(`[guide] unknown tour: ${tourId}`)\n if (target.steps.length === 0) {\n throw new Error(`[guide] tour has no steps: ${tourId}`)\n }\n\n if (typeof document !== 'undefined') {\n focusOriginRef.current = document.activeElement as HTMLElement | null\n }\n\n let stepIndex = options?.from ?? 0\n if (options?.from === undefined && options?.resume !== false && storage) {\n // Storage that fails must not block the tour: we start from the beginning.\n let progress: TourProgress | null = null\n try {\n progress = await storage.read(tourId)\n } catch (error) {\n warnStorageFailure(error)\n }\n if (progress?.status === 'in-progress') stepIndex = progress.stepIndex\n }\n\n if (process.env.NODE_ENV !== 'production') {\n const missing = findMissingTargets(target, location)\n if (missing.length > 0) {\n console.warn(\n `[guide] tour \"${tourId}\" declares targets that are not present on this page: ${missing.join(', ')}`,\n )\n }\n }\n\n // Restarting the same tour on the same step must navigate again: without this reset, the\n // destination already requested would stay remembered and the effect would skip navigate.\n navigationRef.current = { step: null, destination: null }\n\n dispatch({ type: 'START', tourId, stepIndex })\n emit({ type: 'tour:start', tourId, stepIndex })\n },\n [toursById, storage, location, emit, state.tourId, state.status, warnStorageFailure],\n )\n\n useEffect(() => {\n if (!isActive || !step || routeMatches) return\n\n if (navigationRef.current.step !== step) {\n navigationRef.current = { step, destination: null }\n }\n\n const destination =\n step.navigateTo ?? (step.route && isLiteralRoute(step.route) ? step.route : null)\n\n if (!destination) return\n if (navigationRef.current.destination === destination) return\n if (!navigate) {\n console.warn('[guide] a step declares a route but no navigate function was provided')\n return\n }\n navigationRef.current.destination = destination\n navigate(destination)\n }, [isActive, step, routeMatches, navigate])\n\n // Target not found: apply the policy.\n useEffect(() => {\n if (!timedOut || !tour || !step) return\n\n emit({\n type: 'target:missing',\n tourId: tour.id,\n stepIndex: state.stepIndex,\n target: step.target,\n })\n\n const policy = step.onMissingTarget ?? onMissingTarget\n if (policy === 'skip') dispatch({ type: 'NEXT', stepCount: tour.steps.length })\n else if (policy === 'error') dispatch({ type: 'STOP' })\n else dispatch({ type: 'PAUSE' })\n }, [timedOut, tour, step, state.stepIndex, onMissingTarget, emit])\n\n // Automatic resume when the target reappears after a pause.\n useEffect(() => {\n if (state.status === 'paused' && element) dispatch({ type: 'RESUME' })\n }, [state.status, element])\n\n // Step actually on screen.\n useEffect(() => {\n if (state.status !== 'running' || !tour || !step || !element) return\n emit({\n type: 'step:show',\n tourId: tour.id,\n stepIndex: state.stepIndex,\n target: step.target,\n })\n announce(`${state.stepIndex + 1} / ${tour.steps.length}`)\n }, [state.status, state.stepIndex, tour, step, element, emit, announce])\n\n // Progress persistence. A write that fails breaks nothing: the progress is simply not kept.\n useEffect(() => {\n if (!storage || !state.tourId) return\n const status =\n state.status === 'running'\n ? 'in-progress'\n : state.status === 'completed'\n ? 'completed'\n : null\n if (!status) return\n try {\n void Promise.resolve(\n storage.write(state.tourId, { status, stepIndex: state.stepIndex }),\n ).catch(warnStorageFailure)\n } catch (error) {\n warnStorageFailure(error)\n }\n }, [storage, state.tourId, state.status, state.stepIndex, warnStorageFailure])\n\n // Focus returns to its origin once the tour is stopped or completed.\n useEffect(() => {\n if (state.status !== 'idle' && state.status !== 'completed') return\n const origin = focusOriginRef.current\n if (!origin) return\n focusOriginRef.current = null\n if (typeof document !== 'undefined' && document.contains(origin)) origin.focus()\n }, [state.status])\n\n const activeStep = useMemo<ActiveStep | null>(() => {\n if (!tour || !step || !isActive) return null\n return {\n tourId: tour.id,\n step,\n stepIndex: state.stepIndex,\n stepCount: tour.steps.length,\n element,\n rect,\n title: resolveText(step.title, step.titleKey, translate),\n body: resolveText(step.body, step.bodyKey, translate),\n isFirst: state.stepIndex === 0,\n isLast: state.stepIndex === tour.steps.length - 1,\n next,\n previous,\n stop,\n }\n }, [tour, step, isActive, state.stepIndex, element, rect, translate, next, previous, stop])\n\n const value = useMemo<GuideContextValue>(\n () => ({ state, activeStep, start, next, previous, stop }),\n [state, activeStep, start, next, previous, stop],\n )\n\n return <GuideContext.Provider value={value}>{children}</GuideContext.Provider>\n}\n","import type { Tour } from './types'\nimport { matchRoute } from './matchRoute'\nimport { targetSelector } from './selector'\n\nexport function findMissingTargets(\n tour: Tour,\n location: string | undefined,\n attribute = 'data-guide',\n): string[] {\n if (typeof document === 'undefined') return []\n\n return tour.steps\n .filter((step) => !step.route || location === undefined || matchRoute(step.route, location))\n .map((step) => step.target)\n .filter((target) => !document.querySelector(targetSelector(target, attribute)))\n}\n","'use client'\n\nimport { useContext, useMemo } from 'react'\nimport { GuideContext } from './GuideProvider'\nimport type { TourStatus } from './types'\n\nexport interface UseTourResult {\n start: (options?: { from?: number; resume?: boolean }) => Promise<void>\n next: () => void\n previous: () => void\n stop: () => void\n status: TourStatus\n stepIndex: number\n}\n\nexport function useTour(tourId: string): UseTourResult {\n const context = useContext(GuideContext)\n if (!context) throw new Error('[guide] useTour must be used inside a GuideProvider')\n\n const { state, start, next, previous, stop } = context\n const isCurrent = state.tourId === tourId\n\n return useMemo(\n () => ({\n start: (options) => start(tourId, options),\n next,\n previous,\n stop,\n status: isCurrent ? state.status : 'idle',\n stepIndex: isCurrent ? state.stepIndex : 0,\n }),\n [tourId, start, next, previous, stop, isCurrent, state.status, state.stepIndex],\n )\n}\n","'use client'\n\nimport { useContext } from 'react'\nimport { GuideContext, type ActiveStep } from './GuideProvider'\n\nexport function useGuideStep(): ActiveStep | null {\n const context = useContext(GuideContext)\n if (!context) throw new Error('[guide] useGuideStep must be used inside a GuideProvider')\n return context.activeStep\n}\n"],"mappings":"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","names":["import_react","import_react","import_react","import_react","import_react"]}