@flowsterix/react 0.3.0 → 0.4.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.
@@ -1,6 +1,11 @@
1
1
  import {
2
- useTanStackRouterTourAdapter
3
- } from "./chunk-LQFOZS4Y.mjs";
2
+ createPathString,
3
+ notifyRouteChange
4
+ } from "./chunk-B44EX7YT.mjs";
5
+
6
+ // src/router/tanstackRouterAdapter.tsx
7
+ import { useRouterState } from "@tanstack/react-router";
8
+ import { useEffect as useEffect2 } from "react";
4
9
 
5
10
  // src/router/tanstackRouterSync.tsx
6
11
  import * as TanStackRouter from "@tanstack/react-router";
@@ -41,10 +46,25 @@ var TanStackRouterSync = ({
41
46
  return null;
42
47
  };
43
48
 
49
+ // src/router/tanstackRouterAdapter.tsx
50
+ var useTanStackRouterTourAdapter = () => {
51
+ const location = useRouterState({
52
+ select: (state) => state.location
53
+ });
54
+ useEffect2(() => {
55
+ const resolvedPathname = typeof location.pathname === "string" && location.pathname.length > 0 ? location.pathname : "/";
56
+ const resolvedSearch = "searchStr" in location && typeof location.searchStr === "string" ? location.searchStr : typeof location.search === "string" ? location.search : "";
57
+ const resolvedHash = typeof location.hash === "string" ? location.hash : "";
58
+ const path = typeof location.href === "string" && location.href.length > 0 ? location.href : createPathString(resolvedPathname, resolvedSearch, resolvedHash);
59
+ notifyRouteChange(path);
60
+ }, [location]);
61
+ };
62
+
44
63
  export {
45
64
  setTourRouter,
46
65
  setTanStackRouter,
47
66
  getTourRouter,
48
67
  getTanStackRouter,
49
- TanStackRouterSync
68
+ TanStackRouterSync,
69
+ useTanStackRouterTourAdapter
50
70
  };
@@ -222,6 +222,12 @@ var notifyRouteChange = (path) => {
222
222
  var subscribeToRouteChanges = (listener) => {
223
223
  return routeGatingChannel.subscribe(listener);
224
224
  };
225
+ var matchRoute = (params) => {
226
+ const { pattern, path } = params;
227
+ if (!pattern) return true;
228
+ if (typeof pattern === "string") return path === pattern;
229
+ return pattern.test(path);
230
+ };
225
231
 
226
232
  // src/router/utils.ts
227
233
  var ensurePrefix = (value, prefix) => value.startsWith(prefix) ? value : `${prefix}${value}`;
@@ -278,5 +284,6 @@ export {
278
284
  getCurrentRoutePath,
279
285
  notifyRouteChange,
280
286
  subscribeToRouteChanges,
287
+ matchRoute,
281
288
  createPathString
282
289
  };
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,QAAQ,EACR,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,SAAS,EAET,YAAY,EAEZ,gBAAgB,EAChB,IAAI,EACJ,cAAc,EAEd,mBAAmB,EACpB,MAAM,kBAAkB,CAAA;AAUzB,OAAO,KAAK,EACV,QAAQ,EACR,iBAAiB,EACjB,SAAS,EACT,cAAc,EACf,MAAM,OAAO,CAAA;AAUd,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAE1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAajE,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAA;IACvC,QAAQ,EAAE,SAAS,CAAA;IACnB,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,oBAAoB,CAAC,EAAE,gBAAgB,CAAA;IACvC,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,SAAS,CAAC,EAAE,qBAAqB,CAAC,SAAS,CAAC,CAAA;IAC5C,mBAAmB,CAAC,EAAE,uBAAuB,CAAA;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,mDAAmD;IACnD,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;IAC5B,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAA;CACxD;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC,CAAA;IAC7C,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,KAAK,EAAE,SAAS,GAAG,IAAI,CAAA;IACvB,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAA;IAClC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,KAAK,YAAY,CAAC,SAAS,CAAC,CAAA;IAClF,IAAI,EAAE,MAAM,YAAY,CAAC,SAAS,CAAC,CAAA;IACnC,IAAI,EAAE,MAAM,YAAY,CAAC,SAAS,CAAC,CAAA;IACnC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,KAAK,YAAY,CAAC,SAAS,CAAC,CAAA;IAC5D,KAAK,EAAE,MAAM,YAAY,CAAC,SAAS,CAAC,CAAA;IACpC,MAAM,EAAE,MAAM,YAAY,CAAC,SAAS,CAAC,CAAA;IACrC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,gBAAgB,KAAK,YAAY,CAAC,SAAS,CAAC,CAAA;IAC9D,QAAQ,EAAE,MAAM,YAAY,CAAC,SAAS,CAAC,CAAA;IACvC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,CAAA;IAC9C,YAAY,EAAE,OAAO,CAAA;IACrB,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IACzC,WAAW,EAAE,MAAM,IAAI,CAAA;IACvB,SAAS,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAClC,gBAAgB;IAChB,YAAY,EAAE,QAAQ,CAAC,cAAc,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC,CAAA;IAC/D,mBAAmB,EAAE,uBAAuB,CAAA;IAC5C,cAAc,EAAE,OAAO,CAAA;CACxB;AAeD,eAAO,MAAM,YAAY,GAAI,kTAe1B,iBAAiB,CAAC,iBAAiB,CAAC,4CAmkBtC,CAAA;AAED,eAAO,MAAM,OAAO,QAAO,gBAM1B,CAAA;AAED,eAAO,MAAM,aAAa,GACxB,SAAS,SAAS,OAAO,CAAC,MAAM,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,EAE9D,OAAO,SAAS,EAChB,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,KAAK,IAAI,SAQ7D,CAAA"}
package/dist/index.cjs CHANGED
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
 
30
20
  // src/index.tsx
@@ -32,7 +22,6 @@ var index_exports = {};
32
22
  __export(index_exports, {
33
23
  AnimationAdapterProvider: () => AnimationAdapterProvider,
34
24
  OverlayBackdrop: () => OverlayBackdrop,
35
- TanStackRouterSync: () => TanStackRouterSync,
36
25
  TourFocusManager: () => TourFocusManager,
37
26
  TourPopoverPortal: () => TourPopoverPortal,
38
27
  TourProvider: () => TourProvider,
@@ -41,12 +30,8 @@ __export(index_exports, {
41
30
  defaultAnimationAdapter: () => defaultAnimationAdapter,
42
31
  defaultLabels: () => defaultLabels,
43
32
  getCurrentRoutePath: () => getCurrentRoutePath,
44
- getTanStackRouter: () => getTanStackRouter,
45
- getTourRouter: () => getTourRouter,
46
33
  notifyRouteChange: () => notifyRouteChange,
47
34
  reducedMotionAnimationAdapter: () => reducedMotionAnimationAdapter,
48
- setTanStackRouter: () => setTanStackRouter,
49
- setTourRouter: () => setTourRouter,
50
35
  subscribeToRouteChanges: () => subscribeToRouteChanges,
51
36
  useAdvanceRules: () => useAdvanceRules,
52
37
  useAnimationAdapter: () => useAnimationAdapter,
@@ -60,7 +45,6 @@ __export(index_exports, {
60
45
  useHudTargetIssue: () => useHudTargetIssue,
61
46
  usePreferredAnimationAdapter: () => usePreferredAnimationAdapter,
62
47
  useRadixDialogAdapter: () => useRadixDialogAdapter,
63
- useTanStackRouterTourAdapter: () => useTanStackRouterTourAdapter,
64
48
  useTour: () => useTour,
65
49
  useTourControls: () => useTourControls,
66
50
  useTourEvents: () => useTourEvents,
@@ -321,6 +305,127 @@ var supportsMasking = () => {
321
305
  return cachedMaskSupport;
322
306
  };
323
307
 
308
+ // src/router/routeGating.ts
309
+ var DEFAULT_POLL_MS = 150;
310
+ var normalizePathname = (pathname) => {
311
+ if (typeof pathname !== "string" || pathname.length === 0) {
312
+ return "/";
313
+ }
314
+ return pathname.startsWith("/") ? pathname : `/${pathname}`;
315
+ };
316
+ var normalizePrefixedSegment = (value, prefix) => {
317
+ if (typeof value !== "string" || value.length === 0) {
318
+ return "";
319
+ }
320
+ return value.startsWith(prefix) ? value : `${prefix}${value}`;
321
+ };
322
+ var getWindowPath = () => {
323
+ if (!isBrowser) return "/";
324
+ const { pathname, search, hash } = window.location;
325
+ return normalizePathname(pathname) + normalizePrefixedSegment(search, "?") + normalizePrefixedSegment(hash, "#");
326
+ };
327
+ var normalizeExternalPath = (path) => {
328
+ if (path.length === 0) {
329
+ return "/";
330
+ }
331
+ try {
332
+ const parsed = new URL(path, "http://flowsterix.local");
333
+ return normalizePathname(parsed.pathname) + normalizePrefixedSegment(parsed.search, "?") + normalizePrefixedSegment(parsed.hash, "#");
334
+ } catch {
335
+ const [withoutHash, hash = ""] = path.split("#");
336
+ const [base, search = ""] = withoutHash.split("?");
337
+ return normalizePathname(base) + normalizePrefixedSegment(search ? `?${search}` : "", "?") + normalizePrefixedSegment(hash ? `#${hash}` : "", "#");
338
+ }
339
+ };
340
+ var RouteGatingChannel = class {
341
+ #listeners = /* @__PURE__ */ new Set();
342
+ #currentPath = getWindowPath();
343
+ #teardown = null;
344
+ #attachDefaultListeners() {
345
+ if (!isBrowser) return;
346
+ if (this.#teardown) return;
347
+ let lastPath = getWindowPath();
348
+ const emitIfChanged = () => {
349
+ const nextPath = getWindowPath();
350
+ if (nextPath === lastPath) return;
351
+ lastPath = nextPath;
352
+ this.notify(nextPath);
353
+ };
354
+ const handler = () => emitIfChanged();
355
+ window.addEventListener("popstate", handler);
356
+ window.addEventListener("hashchange", handler);
357
+ const pollId = window.setInterval(emitIfChanged, DEFAULT_POLL_MS);
358
+ this.#teardown = () => {
359
+ window.removeEventListener("popstate", handler);
360
+ window.removeEventListener("hashchange", handler);
361
+ window.clearInterval(pollId);
362
+ this.#teardown = null;
363
+ };
364
+ }
365
+ #detachDefaultListeners() {
366
+ if (this.#listeners.size > 0) return;
367
+ this.#teardown?.();
368
+ this.#teardown = null;
369
+ }
370
+ getCurrentPath() {
371
+ if (isBrowser) {
372
+ this.#currentPath = getWindowPath();
373
+ }
374
+ return this.#currentPath;
375
+ }
376
+ notify(path) {
377
+ const resolved = typeof path === "string" && path.length > 0 ? normalizeExternalPath(path) : this.getCurrentPath();
378
+ if (resolved === this.#currentPath) {
379
+ this.#currentPath = resolved;
380
+ return;
381
+ }
382
+ this.#currentPath = resolved;
383
+ for (const listener of Array.from(this.#listeners)) {
384
+ try {
385
+ listener(resolved);
386
+ } catch (error) {
387
+ console.warn("[tour][route-gating] listener error", error);
388
+ }
389
+ }
390
+ }
391
+ subscribe(listener) {
392
+ if (this.#listeners.has(listener)) {
393
+ return () => {
394
+ this.#listeners.delete(listener);
395
+ this.#detachDefaultListeners();
396
+ };
397
+ }
398
+ this.#listeners.add(listener);
399
+ if (this.#listeners.size === 1) {
400
+ this.#attachDefaultListeners();
401
+ }
402
+ const current = this.getCurrentPath();
403
+ try {
404
+ listener(current);
405
+ } catch (error) {
406
+ console.warn("[tour][route-gating] listener error", error);
407
+ }
408
+ return () => {
409
+ this.#listeners.delete(listener);
410
+ this.#detachDefaultListeners();
411
+ };
412
+ }
413
+ };
414
+ var routeGatingChannel = new RouteGatingChannel();
415
+ var getCurrentRoutePath = () => routeGatingChannel.getCurrentPath();
416
+ var notifyRouteChange = (path) => {
417
+ routeGatingChannel.notify(path);
418
+ };
419
+ var subscribeToRouteChanges = (listener) => {
420
+ return routeGatingChannel.subscribe(listener);
421
+ };
422
+ var matchRoute = (params) => {
423
+ const { pattern, path } = params;
424
+ if (!pattern) return true;
425
+ if (typeof pattern === "string") return path === pattern;
426
+ return pattern.test(path);
427
+ };
428
+
324
429
  // src/context.tsx
325
430
  var import_jsx_runtime2 = require("react/jsx-runtime");
326
431
  var TourContext = (0, import_react4.createContext)(void 0);
@@ -368,9 +473,7 @@ var TourProvider = ({
368
473
  );
369
474
  const [debugEnabled, setDebugEnabled] = (0, import_react4.useState)(defaultDebug);
370
475
  const [delayInfo, setDelayInfo] = (0, import_react4.useState)(null);
371
- const autoStartFlow = (0, import_react4.useMemo)(() => {
372
- return flows.find((flow) => flow.autoStart);
373
- }, [flows]);
476
+ const [eligibleAutoStart, setEligibleAutoStart] = (0, import_react4.useState)(null);
374
477
  const teardownStore = (0, import_react4.useCallback)(() => {
375
478
  unsubscribeRef.current?.();
376
479
  unsubscribeRef.current = null;
@@ -574,48 +677,102 @@ var TourProvider = ({
574
677
  [ensureStore, resolveResumeStrategy, runResumeHooks]
575
678
  );
576
679
  (0, import_react4.useEffect)(() => {
577
- if (!autoStartFlow) {
578
- autoStartRequestedRef.current = null;
680
+ const autoStartFlows = flows.filter((f) => f.autoStart);
681
+ if (autoStartFlows.length === 0) {
682
+ setEligibleAutoStart(null);
683
+ return;
684
+ }
685
+ if (!storageAdapter && !fallbackStorageRef.current && isBrowser) {
686
+ fallbackStorageRef.current = (0, import_core.createLocalStorageAdapter)();
687
+ }
688
+ const resolvedStorageAdapter = storageAdapter ?? fallbackStorageRef.current;
689
+ if (!resolvedStorageAdapter) {
690
+ setEligibleAutoStart({
691
+ flow: autoStartFlows[0],
692
+ resolvedState: null,
693
+ stepIndex: 0
694
+ });
579
695
  return;
580
696
  }
581
- if (activeFlowId) return;
582
- if (autoStartRequestedRef.current === autoStartFlow.id) return;
583
- autoStartRequestedRef.current = autoStartFlow.id;
584
697
  let cancelled = false;
585
- const maybeAutoStart = async () => {
586
- if (!storageAdapter && !fallbackStorageRef.current && isBrowser) {
587
- fallbackStorageRef.current = (0, import_core.createLocalStorageAdapter)();
588
- }
589
- const resolvedStorageAdapter = storageAdapter ? storageAdapter : fallbackStorageRef.current;
590
- if (!resolvedStorageAdapter) {
591
- startFlow(autoStartFlow.id, { resume: true });
592
- return;
593
- }
594
- const storageKey = storageNamespace ? `${storageNamespace}:${autoStartFlow.id}` : `${DEFAULT_STORAGE_PREFIX}:${autoStartFlow.id}`;
595
- const snapshot = await (0, import_core.resolveMaybePromise)(
596
- resolvedStorageAdapter.get(storageKey)
698
+ const findEligible = async () => {
699
+ const storageKeys = autoStartFlows.map(
700
+ (f) => storageNamespace ? `${storageNamespace}:${f.id}` : `${DEFAULT_STORAGE_PREFIX}:${f.id}`
701
+ );
702
+ const snapshots = await Promise.all(
703
+ storageKeys.map(
704
+ (key) => (0, import_core.resolveMaybePromise)(resolvedStorageAdapter.get(key))
705
+ )
597
706
  );
598
707
  if (cancelled) return;
599
- const currentVersionStr = (0, import_core.serializeVersion)(autoStartFlow.version);
600
- const storedVersionStr = typeof snapshot?.version === "number" ? (0, import_core.serializeVersion)({ major: snapshot.version, minor: 0 }) : snapshot?.version;
601
- if (snapshot && storedVersionStr === currentVersionStr) {
602
- const storedState = snapshot.value;
603
- const isFinished = storedState.status === "completed";
604
- const isSkipped = storedState.status === "cancelled" && storedState.cancelReason === "skipped";
605
- if (isFinished || isSkipped) {
708
+ for (let i = 0; i < autoStartFlows.length; i++) {
709
+ const flow = autoStartFlows[i];
710
+ const snapshot = snapshots[i];
711
+ if (!snapshot) {
712
+ setEligibleAutoStart({ flow, resolvedState: null, stepIndex: 0 });
606
713
  return;
607
714
  }
715
+ const storedVersionStr = typeof snapshot.version === "number" ? (0, import_core.serializeVersion)({ major: snapshot.version, minor: 0 }) : snapshot.version;
716
+ const storedVersion = (0, import_core.parseVersion)(storedVersionStr);
717
+ const stepIdMap = (0, import_core.buildStepIdMap)(flow);
718
+ const { state: resolvedState } = (0, import_core.handleVersionMismatch)({
719
+ storedState: snapshot.value,
720
+ storedVersion,
721
+ definition: flow,
722
+ currentVersion: flow.version,
723
+ stepIdMap,
724
+ now: () => Date.now()
725
+ });
726
+ if (resolvedState.status === "completed") continue;
727
+ if (resolvedState.status === "cancelled" && resolvedState.cancelReason === "skipped") {
728
+ continue;
729
+ }
730
+ const stepIndex = Math.max(0, resolvedState.stepIndex);
731
+ setEligibleAutoStart({ flow, resolvedState, stepIndex });
732
+ return;
608
733
  }
609
- startFlow(autoStartFlow.id, { resume: true });
734
+ setEligibleAutoStart(null);
610
735
  };
611
- void maybeAutoStart();
736
+ void findEligible();
612
737
  return () => {
613
738
  cancelled = true;
739
+ };
740
+ }, [flows, storageAdapter, storageNamespace]);
741
+ (0, import_react4.useEffect)(() => {
742
+ if (!eligibleAutoStart) {
743
+ autoStartRequestedRef.current = null;
744
+ return;
745
+ }
746
+ if (activeFlowId) return;
747
+ if (autoStartRequestedRef.current === eligibleAutoStart.flow.id) return;
748
+ const { flow, stepIndex } = eligibleAutoStart;
749
+ const step = flow.steps[stepIndex];
750
+ if (!step?.route) {
751
+ autoStartRequestedRef.current = flow.id;
752
+ startFlow(flow.id, { resume: true });
753
+ return;
754
+ }
755
+ const currentPath = getCurrentRoutePath();
756
+ if (matchRoute({ pattern: step.route, path: currentPath })) {
757
+ autoStartRequestedRef.current = flow.id;
758
+ startFlow(flow.id, { resume: true });
759
+ return;
760
+ }
761
+ const unsubscribe = subscribeToRouteChanges((path) => {
762
+ if (activeFlowId) return;
763
+ if (autoStartRequestedRef.current === flow.id) return;
764
+ if (matchRoute({ pattern: step.route, path })) {
765
+ autoStartRequestedRef.current = flow.id;
766
+ startFlow(flow.id, { resume: true });
767
+ }
768
+ });
769
+ return () => {
770
+ unsubscribe();
614
771
  if (!activeFlowId) {
615
772
  autoStartRequestedRef.current = null;
616
773
  }
617
774
  };
618
- }, [activeFlowId, autoStartFlow, startFlow, storageAdapter, storageNamespace]);
775
+ }, [activeFlowId, eligibleAutoStart, startFlow]);
619
776
  const next = (0, import_react4.useCallback)(() => getActiveStore().next(), [getActiveStore]);
620
777
  const back = (0, import_react4.useCallback)(() => getActiveStore().back(), [getActiveStore]);
621
778
  const goToStep = (0, import_react4.useCallback)(
@@ -1509,123 +1666,6 @@ var import_react9 = require("react");
1509
1666
 
1510
1667
  // src/hooks/useAdvanceRules.ts
1511
1668
  var import_react6 = require("react");
1512
-
1513
- // src/router/routeGating.ts
1514
- var DEFAULT_POLL_MS = 150;
1515
- var normalizePathname = (pathname) => {
1516
- if (typeof pathname !== "string" || pathname.length === 0) {
1517
- return "/";
1518
- }
1519
- return pathname.startsWith("/") ? pathname : `/${pathname}`;
1520
- };
1521
- var normalizePrefixedSegment = (value, prefix) => {
1522
- if (typeof value !== "string" || value.length === 0) {
1523
- return "";
1524
- }
1525
- return value.startsWith(prefix) ? value : `${prefix}${value}`;
1526
- };
1527
- var getWindowPath = () => {
1528
- if (!isBrowser) return "/";
1529
- const { pathname, search, hash } = window.location;
1530
- return normalizePathname(pathname) + normalizePrefixedSegment(search, "?") + normalizePrefixedSegment(hash, "#");
1531
- };
1532
- var normalizeExternalPath = (path) => {
1533
- if (path.length === 0) {
1534
- return "/";
1535
- }
1536
- try {
1537
- const parsed = new URL(path, "http://flowsterix.local");
1538
- return normalizePathname(parsed.pathname) + normalizePrefixedSegment(parsed.search, "?") + normalizePrefixedSegment(parsed.hash, "#");
1539
- } catch {
1540
- const [withoutHash, hash = ""] = path.split("#");
1541
- const [base, search = ""] = withoutHash.split("?");
1542
- return normalizePathname(base) + normalizePrefixedSegment(search ? `?${search}` : "", "?") + normalizePrefixedSegment(hash ? `#${hash}` : "", "#");
1543
- }
1544
- };
1545
- var RouteGatingChannel = class {
1546
- #listeners = /* @__PURE__ */ new Set();
1547
- #currentPath = getWindowPath();
1548
- #teardown = null;
1549
- #attachDefaultListeners() {
1550
- if (!isBrowser) return;
1551
- if (this.#teardown) return;
1552
- let lastPath = getWindowPath();
1553
- const emitIfChanged = () => {
1554
- const nextPath = getWindowPath();
1555
- if (nextPath === lastPath) return;
1556
- lastPath = nextPath;
1557
- this.notify(nextPath);
1558
- };
1559
- const handler = () => emitIfChanged();
1560
- window.addEventListener("popstate", handler);
1561
- window.addEventListener("hashchange", handler);
1562
- const pollId = window.setInterval(emitIfChanged, DEFAULT_POLL_MS);
1563
- this.#teardown = () => {
1564
- window.removeEventListener("popstate", handler);
1565
- window.removeEventListener("hashchange", handler);
1566
- window.clearInterval(pollId);
1567
- this.#teardown = null;
1568
- };
1569
- }
1570
- #detachDefaultListeners() {
1571
- if (this.#listeners.size > 0) return;
1572
- this.#teardown?.();
1573
- this.#teardown = null;
1574
- }
1575
- getCurrentPath() {
1576
- if (isBrowser) {
1577
- this.#currentPath = getWindowPath();
1578
- }
1579
- return this.#currentPath;
1580
- }
1581
- notify(path) {
1582
- const resolved = typeof path === "string" && path.length > 0 ? normalizeExternalPath(path) : this.getCurrentPath();
1583
- if (resolved === this.#currentPath) {
1584
- this.#currentPath = resolved;
1585
- return;
1586
- }
1587
- this.#currentPath = resolved;
1588
- for (const listener of Array.from(this.#listeners)) {
1589
- try {
1590
- listener(resolved);
1591
- } catch (error) {
1592
- console.warn("[tour][route-gating] listener error", error);
1593
- }
1594
- }
1595
- }
1596
- subscribe(listener) {
1597
- if (this.#listeners.has(listener)) {
1598
- return () => {
1599
- this.#listeners.delete(listener);
1600
- this.#detachDefaultListeners();
1601
- };
1602
- }
1603
- this.#listeners.add(listener);
1604
- if (this.#listeners.size === 1) {
1605
- this.#attachDefaultListeners();
1606
- }
1607
- const current = this.getCurrentPath();
1608
- try {
1609
- listener(current);
1610
- } catch (error) {
1611
- console.warn("[tour][route-gating] listener error", error);
1612
- }
1613
- return () => {
1614
- this.#listeners.delete(listener);
1615
- this.#detachDefaultListeners();
1616
- };
1617
- }
1618
- };
1619
- var routeGatingChannel = new RouteGatingChannel();
1620
- var getCurrentRoutePath = () => routeGatingChannel.getCurrentPath();
1621
- var notifyRouteChange = (path) => {
1622
- routeGatingChannel.notify(path);
1623
- };
1624
- var subscribeToRouteChanges = (listener) => {
1625
- return routeGatingChannel.subscribe(listener);
1626
- };
1627
-
1628
- // src/hooks/useAdvanceRules.ts
1629
1669
  var DEFAULT_POLL_MS2 = 250;
1630
1670
  var isListenerTarget = (value) => {
1631
1671
  return !!value && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function";
@@ -3406,7 +3446,7 @@ var TourPopoverPortal = ({
3406
3446
  padding: FLOATING_OFFSET,
3407
3447
  alignment: autoAlignment
3408
3448
  })
3409
- ] : [(0, import_dom13.flip)({ padding: FLOATING_OFFSET })],
3449
+ ] : [(0, import_dom13.flip)({ padding: FLOATING_OFFSET, fallbackStrategy: "bestFit" })],
3410
3450
  (0, import_dom13.shift)({ padding: FLOATING_OFFSET })
3411
3451
  ];
3412
3452
  const updatePosition = async () => {
@@ -4128,66 +4168,10 @@ var createPathString = (pathname, search, hash) => {
4128
4168
  const hashPart = toHashString(hash);
4129
4169
  return `${normalizedPath}${searchPart}${hashPart}`;
4130
4170
  };
4131
-
4132
- // src/router/tanstackRouterAdapter.tsx
4133
- var import_react_router = require("@tanstack/react-router");
4134
- var import_react23 = require("react");
4135
- var useTanStackRouterTourAdapter = () => {
4136
- const location = (0, import_react_router.useRouterState)({
4137
- select: (state) => state.location
4138
- });
4139
- (0, import_react23.useEffect)(() => {
4140
- const resolvedPathname = typeof location.pathname === "string" && location.pathname.length > 0 ? location.pathname : "/";
4141
- const resolvedSearch = "searchStr" in location && typeof location.searchStr === "string" ? location.searchStr : typeof location.search === "string" ? location.search : "";
4142
- const resolvedHash = typeof location.hash === "string" ? location.hash : "";
4143
- const path = typeof location.href === "string" && location.href.length > 0 ? location.href : createPathString(resolvedPathname, resolvedSearch, resolvedHash);
4144
- notifyRouteChange(path);
4145
- }, [location]);
4146
- };
4147
-
4148
- // src/router/tanstackRouterSync.tsx
4149
- var TanStackRouter = __toESM(require("@tanstack/react-router"), 1);
4150
- var import_react24 = require("react");
4151
- var currentRouter = null;
4152
- var setTourRouter = (router) => {
4153
- currentRouter = router;
4154
- };
4155
- var setTanStackRouter = setTourRouter;
4156
- var getTourRouter = () => {
4157
- return currentRouter;
4158
- };
4159
- var getTanStackRouter = getTourRouter;
4160
- var TanStackRouterSync = ({
4161
- onRouterAvailable
4162
- }) => {
4163
- const useRouter2 = TanStackRouter.useRouter;
4164
- if (typeof useRouter2 !== "function") {
4165
- if (typeof console !== "undefined") {
4166
- console.warn(
4167
- "[tour][router] TanStackRouterSync requires @tanstack/react-router. Call this component only inside TanStack Router environments."
4168
- );
4169
- }
4170
- return null;
4171
- }
4172
- useTanStackRouterTourAdapter();
4173
- const router = useRouter2();
4174
- (0, import_react24.useEffect)(() => {
4175
- setTourRouter(router);
4176
- onRouterAvailable?.(router);
4177
- return () => {
4178
- if (getTourRouter() === router) {
4179
- setTourRouter(null);
4180
- }
4181
- onRouterAvailable?.(null);
4182
- };
4183
- }, [router, onRouterAvailable]);
4184
- return null;
4185
- };
4186
4171
  // Annotate the CommonJS export names for ESM import in node:
4187
4172
  0 && (module.exports = {
4188
4173
  AnimationAdapterProvider,
4189
4174
  OverlayBackdrop,
4190
- TanStackRouterSync,
4191
4175
  TourFocusManager,
4192
4176
  TourPopoverPortal,
4193
4177
  TourProvider,
@@ -4196,12 +4180,8 @@ var TanStackRouterSync = ({
4196
4180
  defaultAnimationAdapter,
4197
4181
  defaultLabels,
4198
4182
  getCurrentRoutePath,
4199
- getTanStackRouter,
4200
- getTourRouter,
4201
4183
  notifyRouteChange,
4202
4184
  reducedMotionAnimationAdapter,
4203
- setTanStackRouter,
4204
- setTourRouter,
4205
4185
  subscribeToRouteChanges,
4206
4186
  useAdvanceRules,
4207
4187
  useAnimationAdapter,
@@ -4215,7 +4195,6 @@ var TanStackRouterSync = ({
4215
4195
  useHudTargetIssue,
4216
4196
  usePreferredAnimationAdapter,
4217
4197
  useRadixDialogAdapter,
4218
- useTanStackRouterTourAdapter,
4219
4198
  useTour,
4220
4199
  useTourControls,
4221
4200
  useTourEvents,
package/dist/index.d.ts CHANGED
@@ -41,5 +41,6 @@ export type { UseHiddenTargetFallbackConfig, UseHiddenTargetFallbackResult, } fr
41
41
  export { useViewportRect } from './hooks/useViewportRect';
42
42
  export { createWaitForPredicateController } from './hooks/waitForPredicate';
43
43
  export type { WaitForPredicateController, WaitForPredicateControllerOptions, } from './hooks/waitForPredicate';
44
- export { createPathString, getCurrentRoutePath, getTanStackRouter, getTourRouter, notifyRouteChange, setTanStackRouter, setTourRouter, subscribeToRouteChanges, TanStackRouterSync, useTanStackRouterTourAdapter, } from './router';
44
+ export { getCurrentRoutePath, notifyRouteChange, subscribeToRouteChanges, } from './router/routeGating';
45
+ export { createPathString } from './router/utils';
45
46
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,13 +1,3 @@
1
- import {
2
- TanStackRouterSync,
3
- getTanStackRouter,
4
- getTourRouter,
5
- setTanStackRouter,
6
- setTourRouter
7
- } from "./chunk-B6OJ26VH.mjs";
8
- import {
9
- useTanStackRouterTourAdapter
10
- } from "./chunk-LQFOZS4Y.mjs";
11
1
  import {
12
2
  createPathString,
13
3
  expandRect,
@@ -16,16 +6,20 @@ import {
16
6
  getScrollParents,
17
7
  getViewportRect,
18
8
  isBrowser,
9
+ matchRoute,
19
10
  notifyRouteChange,
20
11
  portalHost,
21
12
  subscribeToRouteChanges,
22
13
  supportsMasking
23
- } from "./chunk-WTGQUDPT.mjs";
14
+ } from "./chunk-B44EX7YT.mjs";
24
15
 
25
16
  // src/context.tsx
26
17
  import {
18
+ buildStepIdMap,
27
19
  createFlowStore,
28
20
  createLocalStorageAdapter,
21
+ handleVersionMismatch,
22
+ parseVersion,
29
23
  resolveMaybePromise,
30
24
  serializeVersion
31
25
  } from "@flowsterix/core";
@@ -220,9 +214,7 @@ var TourProvider = ({
220
214
  );
221
215
  const [debugEnabled, setDebugEnabled] = useState2(defaultDebug);
222
216
  const [delayInfo, setDelayInfo] = useState2(null);
223
- const autoStartFlow = useMemo2(() => {
224
- return flows.find((flow) => flow.autoStart);
225
- }, [flows]);
217
+ const [eligibleAutoStart, setEligibleAutoStart] = useState2(null);
226
218
  const teardownStore = useCallback(() => {
227
219
  unsubscribeRef.current?.();
228
220
  unsubscribeRef.current = null;
@@ -426,48 +418,102 @@ var TourProvider = ({
426
418
  [ensureStore, resolveResumeStrategy, runResumeHooks]
427
419
  );
428
420
  useEffect2(() => {
429
- if (!autoStartFlow) {
430
- autoStartRequestedRef.current = null;
421
+ const autoStartFlows = flows.filter((f) => f.autoStart);
422
+ if (autoStartFlows.length === 0) {
423
+ setEligibleAutoStart(null);
424
+ return;
425
+ }
426
+ if (!storageAdapter && !fallbackStorageRef.current && isBrowser) {
427
+ fallbackStorageRef.current = createLocalStorageAdapter();
428
+ }
429
+ const resolvedStorageAdapter = storageAdapter ?? fallbackStorageRef.current;
430
+ if (!resolvedStorageAdapter) {
431
+ setEligibleAutoStart({
432
+ flow: autoStartFlows[0],
433
+ resolvedState: null,
434
+ stepIndex: 0
435
+ });
431
436
  return;
432
437
  }
433
- if (activeFlowId) return;
434
- if (autoStartRequestedRef.current === autoStartFlow.id) return;
435
- autoStartRequestedRef.current = autoStartFlow.id;
436
438
  let cancelled = false;
437
- const maybeAutoStart = async () => {
438
- if (!storageAdapter && !fallbackStorageRef.current && isBrowser) {
439
- fallbackStorageRef.current = createLocalStorageAdapter();
440
- }
441
- const resolvedStorageAdapter = storageAdapter ? storageAdapter : fallbackStorageRef.current;
442
- if (!resolvedStorageAdapter) {
443
- startFlow(autoStartFlow.id, { resume: true });
444
- return;
445
- }
446
- const storageKey = storageNamespace ? `${storageNamespace}:${autoStartFlow.id}` : `${DEFAULT_STORAGE_PREFIX}:${autoStartFlow.id}`;
447
- const snapshot = await resolveMaybePromise(
448
- resolvedStorageAdapter.get(storageKey)
439
+ const findEligible = async () => {
440
+ const storageKeys = autoStartFlows.map(
441
+ (f) => storageNamespace ? `${storageNamespace}:${f.id}` : `${DEFAULT_STORAGE_PREFIX}:${f.id}`
442
+ );
443
+ const snapshots = await Promise.all(
444
+ storageKeys.map(
445
+ (key) => resolveMaybePromise(resolvedStorageAdapter.get(key))
446
+ )
449
447
  );
450
448
  if (cancelled) return;
451
- const currentVersionStr = serializeVersion(autoStartFlow.version);
452
- const storedVersionStr = typeof snapshot?.version === "number" ? serializeVersion({ major: snapshot.version, minor: 0 }) : snapshot?.version;
453
- if (snapshot && storedVersionStr === currentVersionStr) {
454
- const storedState = snapshot.value;
455
- const isFinished = storedState.status === "completed";
456
- const isSkipped = storedState.status === "cancelled" && storedState.cancelReason === "skipped";
457
- if (isFinished || isSkipped) {
449
+ for (let i = 0; i < autoStartFlows.length; i++) {
450
+ const flow = autoStartFlows[i];
451
+ const snapshot = snapshots[i];
452
+ if (!snapshot) {
453
+ setEligibleAutoStart({ flow, resolvedState: null, stepIndex: 0 });
458
454
  return;
459
455
  }
456
+ const storedVersionStr = typeof snapshot.version === "number" ? serializeVersion({ major: snapshot.version, minor: 0 }) : snapshot.version;
457
+ const storedVersion = parseVersion(storedVersionStr);
458
+ const stepIdMap = buildStepIdMap(flow);
459
+ const { state: resolvedState } = handleVersionMismatch({
460
+ storedState: snapshot.value,
461
+ storedVersion,
462
+ definition: flow,
463
+ currentVersion: flow.version,
464
+ stepIdMap,
465
+ now: () => Date.now()
466
+ });
467
+ if (resolvedState.status === "completed") continue;
468
+ if (resolvedState.status === "cancelled" && resolvedState.cancelReason === "skipped") {
469
+ continue;
470
+ }
471
+ const stepIndex = Math.max(0, resolvedState.stepIndex);
472
+ setEligibleAutoStart({ flow, resolvedState, stepIndex });
473
+ return;
460
474
  }
461
- startFlow(autoStartFlow.id, { resume: true });
475
+ setEligibleAutoStart(null);
462
476
  };
463
- void maybeAutoStart();
477
+ void findEligible();
464
478
  return () => {
465
479
  cancelled = true;
480
+ };
481
+ }, [flows, storageAdapter, storageNamespace]);
482
+ useEffect2(() => {
483
+ if (!eligibleAutoStart) {
484
+ autoStartRequestedRef.current = null;
485
+ return;
486
+ }
487
+ if (activeFlowId) return;
488
+ if (autoStartRequestedRef.current === eligibleAutoStart.flow.id) return;
489
+ const { flow, stepIndex } = eligibleAutoStart;
490
+ const step = flow.steps[stepIndex];
491
+ if (!step?.route) {
492
+ autoStartRequestedRef.current = flow.id;
493
+ startFlow(flow.id, { resume: true });
494
+ return;
495
+ }
496
+ const currentPath = getCurrentRoutePath();
497
+ if (matchRoute({ pattern: step.route, path: currentPath })) {
498
+ autoStartRequestedRef.current = flow.id;
499
+ startFlow(flow.id, { resume: true });
500
+ return;
501
+ }
502
+ const unsubscribe = subscribeToRouteChanges((path) => {
503
+ if (activeFlowId) return;
504
+ if (autoStartRequestedRef.current === flow.id) return;
505
+ if (matchRoute({ pattern: step.route, path })) {
506
+ autoStartRequestedRef.current = flow.id;
507
+ startFlow(flow.id, { resume: true });
508
+ }
509
+ });
510
+ return () => {
511
+ unsubscribe();
466
512
  if (!activeFlowId) {
467
513
  autoStartRequestedRef.current = null;
468
514
  }
469
515
  };
470
- }, [activeFlowId, autoStartFlow, startFlow, storageAdapter, storageNamespace]);
516
+ }, [activeFlowId, eligibleAutoStart, startFlow]);
471
517
  const next = useCallback(() => getActiveStore().next(), [getActiveStore]);
472
518
  const back = useCallback(() => getActiveStore().back(), [getActiveStore]);
473
519
  const goToStep = useCallback(
@@ -3147,7 +3193,7 @@ var TourPopoverPortal = ({
3147
3193
  padding: FLOATING_OFFSET,
3148
3194
  alignment: autoAlignment
3149
3195
  })
3150
- ] : [flip({ padding: FLOATING_OFFSET })],
3196
+ ] : [flip({ padding: FLOATING_OFFSET, fallbackStrategy: "bestFit" })],
3151
3197
  shift({ padding: FLOATING_OFFSET })
3152
3198
  ];
3153
3199
  const updatePosition = async () => {
@@ -3829,7 +3875,6 @@ var useHudMotion = () => {
3829
3875
  export {
3830
3876
  AnimationAdapterProvider,
3831
3877
  OverlayBackdrop,
3832
- TanStackRouterSync,
3833
3878
  TourFocusManager,
3834
3879
  TourPopoverPortal,
3835
3880
  TourProvider,
@@ -3838,12 +3883,8 @@ export {
3838
3883
  defaultAnimationAdapter,
3839
3884
  defaultLabels,
3840
3885
  getCurrentRoutePath,
3841
- getTanStackRouter,
3842
- getTourRouter,
3843
3886
  notifyRouteChange,
3844
3887
  reducedMotionAnimationAdapter,
3845
- setTanStackRouter,
3846
- setTourRouter,
3847
3888
  subscribeToRouteChanges,
3848
3889
  useAdvanceRules,
3849
3890
  useAnimationAdapter,
@@ -3857,7 +3898,6 @@ export {
3857
3898
  useHudTargetIssue,
3858
3899
  usePreferredAnimationAdapter,
3859
3900
  useRadixDialogAdapter,
3860
- useTanStackRouterTourAdapter,
3861
3901
  useTour,
3862
3902
  useTourControls,
3863
3903
  useTourEvents,
@@ -35,6 +35,7 @@ __export(router_exports, {
35
35
  getCurrentRoutePath: () => getCurrentRoutePath,
36
36
  getTanStackRouter: () => getTanStackRouter,
37
37
  getTourRouter: () => getTourRouter,
38
+ matchRoute: () => matchRoute,
38
39
  notifyRouteChange: () => notifyRouteChange,
39
40
  routeGatingChannel: () => routeGatingChannel,
40
41
  setTanStackRouter: () => setTanStackRouter,
@@ -161,6 +162,12 @@ var notifyRouteChange = (path) => {
161
162
  var subscribeToRouteChanges = (listener) => {
162
163
  return routeGatingChannel.subscribe(listener);
163
164
  };
165
+ var matchRoute = (params) => {
166
+ const { pattern, path } = params;
167
+ if (!pattern) return true;
168
+ if (typeof pattern === "string") return path === pattern;
169
+ return pattern.test(path);
170
+ };
164
171
 
165
172
  // src/router/utils.ts
166
173
  var ensurePrefix = (value, prefix) => value.startsWith(prefix) ? value : `${prefix}${value}`;
@@ -207,23 +214,11 @@ var createPathString = (pathname, search, hash) => {
207
214
 
208
215
  // src/router/tanstackRouterAdapter.tsx
209
216
  var import_react_router = require("@tanstack/react-router");
210
- var import_react = require("react");
211
- var useTanStackRouterTourAdapter = () => {
212
- const location = (0, import_react_router.useRouterState)({
213
- select: (state) => state.location
214
- });
215
- (0, import_react.useEffect)(() => {
216
- const resolvedPathname = typeof location.pathname === "string" && location.pathname.length > 0 ? location.pathname : "/";
217
- const resolvedSearch = "searchStr" in location && typeof location.searchStr === "string" ? location.searchStr : typeof location.search === "string" ? location.search : "";
218
- const resolvedHash = typeof location.hash === "string" ? location.hash : "";
219
- const path = typeof location.href === "string" && location.href.length > 0 ? location.href : createPathString(resolvedPathname, resolvedSearch, resolvedHash);
220
- notifyRouteChange(path);
221
- }, [location]);
222
- };
217
+ var import_react2 = require("react");
223
218
 
224
219
  // src/router/tanstackRouterSync.tsx
225
220
  var TanStackRouter = __toESM(require("@tanstack/react-router"), 1);
226
- var import_react2 = require("react");
221
+ var import_react = require("react");
227
222
  var currentRouter = null;
228
223
  var setTourRouter = (router) => {
229
224
  currentRouter = router;
@@ -247,7 +242,7 @@ var TanStackRouterSync = ({
247
242
  }
248
243
  useTanStackRouterTourAdapter();
249
244
  const router = useRouter2();
250
- (0, import_react2.useEffect)(() => {
245
+ (0, import_react.useEffect)(() => {
251
246
  setTourRouter(router);
252
247
  onRouterAvailable?.(router);
253
248
  return () => {
@@ -259,6 +254,20 @@ var TanStackRouterSync = ({
259
254
  }, [router, onRouterAvailable]);
260
255
  return null;
261
256
  };
257
+
258
+ // src/router/tanstackRouterAdapter.tsx
259
+ var useTanStackRouterTourAdapter = () => {
260
+ const location = (0, import_react_router.useRouterState)({
261
+ select: (state) => state.location
262
+ });
263
+ (0, import_react2.useEffect)(() => {
264
+ const resolvedPathname = typeof location.pathname === "string" && location.pathname.length > 0 ? location.pathname : "/";
265
+ const resolvedSearch = "searchStr" in location && typeof location.searchStr === "string" ? location.searchStr : typeof location.search === "string" ? location.search : "";
266
+ const resolvedHash = typeof location.hash === "string" ? location.hash : "";
267
+ const path = typeof location.href === "string" && location.href.length > 0 ? location.href : createPathString(resolvedPathname, resolvedSearch, resolvedHash);
268
+ notifyRouteChange(path);
269
+ }, [location]);
270
+ };
262
271
  // Annotate the CommonJS export names for ESM import in node:
263
272
  0 && (module.exports = {
264
273
  TanStackRouterSync,
@@ -266,6 +275,7 @@ var TanStackRouterSync = ({
266
275
  getCurrentRoutePath,
267
276
  getTanStackRouter,
268
277
  getTourRouter,
278
+ matchRoute,
269
279
  notifyRouteChange,
270
280
  routeGatingChannel,
271
281
  setTanStackRouter,
@@ -1,4 +1,4 @@
1
- export { getCurrentRoutePath, notifyRouteChange, routeGatingChannel, subscribeToRouteChanges, } from './routeGating';
1
+ export { getCurrentRoutePath, matchRoute, notifyRouteChange, routeGatingChannel, subscribeToRouteChanges, } from './routeGating';
2
2
  export { createPathString } from './utils';
3
3
  export { useTanStackRouterTourAdapter } from './tanstackRouterAdapter';
4
4
  export { getTanStackRouter, getTourRouter, setTanStackRouter, setTourRouter, TanStackRouterSync, } from './tanstackRouterSync';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE1C,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AAEtE,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GACnB,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE1C,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AAEtE,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GACnB,MAAM,sBAAsB,CAAA"}
@@ -3,24 +3,24 @@ import {
3
3
  getTanStackRouter,
4
4
  getTourRouter,
5
5
  setTanStackRouter,
6
- setTourRouter
7
- } from "../chunk-B6OJ26VH.mjs";
8
- import {
6
+ setTourRouter,
9
7
  useTanStackRouterTourAdapter
10
- } from "../chunk-LQFOZS4Y.mjs";
8
+ } from "../chunk-2ZX2Y3JL.mjs";
11
9
  import {
12
10
  createPathString,
13
11
  getCurrentRoutePath,
12
+ matchRoute,
14
13
  notifyRouteChange,
15
14
  routeGatingChannel,
16
15
  subscribeToRouteChanges
17
- } from "../chunk-WTGQUDPT.mjs";
16
+ } from "../chunk-B44EX7YT.mjs";
18
17
  export {
19
18
  TanStackRouterSync,
20
19
  createPathString,
21
20
  getCurrentRoutePath,
22
21
  getTanStackRouter,
23
22
  getTourRouter,
23
+ matchRoute,
24
24
  notifyRouteChange,
25
25
  routeGatingChannel,
26
26
  setTanStackRouter,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createPathString,
3
3
  notifyRouteChange
4
- } from "../chunk-WTGQUDPT.mjs";
4
+ } from "../chunk-B44EX7YT.mjs";
5
5
 
6
6
  // src/router/nextAppRouterAdapter.tsx
7
7
  import * as NextNavigation from "next/navigation";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createPathString,
3
3
  notifyRouteChange
4
- } from "../chunk-WTGQUDPT.mjs";
4
+ } from "../chunk-B44EX7YT.mjs";
5
5
 
6
6
  // src/router/nextPagesRouterAdapter.tsx
7
7
  import * as NextRouter from "next/router";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createPathString,
3
3
  notifyRouteChange
4
- } from "../chunk-WTGQUDPT.mjs";
4
+ } from "../chunk-B44EX7YT.mjs";
5
5
 
6
6
  // src/router/reactRouterAdapter.tsx
7
7
  import { useEffect } from "react";
@@ -9,5 +9,9 @@ export declare const routeGatingChannel: RouteGatingChannel;
9
9
  export declare const getCurrentRoutePath: () => string;
10
10
  export declare const notifyRouteChange: (path?: string) => void;
11
11
  export declare const subscribeToRouteChanges: (listener: RouteChangeListener) => () => void;
12
+ export declare const matchRoute: (params: {
13
+ pattern: string | RegExp | undefined;
14
+ path: string;
15
+ }) => boolean;
12
16
  export {};
13
17
  //# sourceMappingURL=routeGating.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"routeGating.d.ts","sourceRoot":"","sources":["../../src/router/routeGating.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,mBAAmB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;AAsDxD,cAAM,kBAAkB;;IAsCtB,cAAc,IAAI,MAAM;IAOxB,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM;IAmBpB,SAAS,CAAC,QAAQ,EAAE,mBAAmB;CAyBxC;AAED,eAAO,MAAM,kBAAkB,oBAA2B,CAAA;AAE1D,eAAO,MAAM,mBAAmB,cAA4C,CAAA;AAE5E,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,SAE9C,CAAA;AAED,eAAO,MAAM,uBAAuB,GAAI,UAAU,mBAAmB,eAEpE,CAAA"}
1
+ {"version":3,"file":"routeGating.d.ts","sourceRoot":"","sources":["../../src/router/routeGating.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,mBAAmB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;AAsDxD,cAAM,kBAAkB;;IAsCtB,cAAc,IAAI,MAAM;IAOxB,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM;IAmBpB,SAAS,CAAC,QAAQ,EAAE,mBAAmB;CAyBxC;AAED,eAAO,MAAM,kBAAkB,oBAA2B,CAAA;AAE1D,eAAO,MAAM,mBAAmB,cAA4C,CAAA;AAE5E,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,SAE9C,CAAA;AAED,eAAO,MAAM,uBAAuB,GAAI,UAAU,mBAAmB,eAEpE,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,QAAQ;IACjC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IACpC,IAAI,EAAE,MAAM,CAAA;CACb,KAAG,OAKH,CAAA"}
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,16 +17,29 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/router/tanstackRouterAdapter.tsx
21
31
  var tanstackRouterAdapter_exports = {};
22
32
  __export(tanstackRouterAdapter_exports, {
33
+ TanStackRouterSync: () => TanStackRouterSync,
34
+ getTanStackRouter: () => getTanStackRouter,
35
+ getTourRouter: () => getTourRouter,
36
+ setTanStackRouter: () => setTanStackRouter,
37
+ setTourRouter: () => setTourRouter,
23
38
  useTanStackRouterTourAdapter: () => useTanStackRouterTourAdapter
24
39
  });
25
40
  module.exports = __toCommonJS(tanstackRouterAdapter_exports);
26
41
  var import_react_router = require("@tanstack/react-router");
27
- var import_react = require("react");
42
+ var import_react2 = require("react");
28
43
 
29
44
  // src/utils/dom.ts
30
45
  var isBrowser = typeof window !== "undefined" && typeof document !== "undefined";
@@ -183,12 +198,51 @@ var createPathString = (pathname, search, hash) => {
183
198
  return `${normalizedPath}${searchPart}${hashPart}`;
184
199
  };
185
200
 
201
+ // src/router/tanstackRouterSync.tsx
202
+ var TanStackRouter = __toESM(require("@tanstack/react-router"), 1);
203
+ var import_react = require("react");
204
+ var currentRouter = null;
205
+ var setTourRouter = (router) => {
206
+ currentRouter = router;
207
+ };
208
+ var setTanStackRouter = setTourRouter;
209
+ var getTourRouter = () => {
210
+ return currentRouter;
211
+ };
212
+ var getTanStackRouter = getTourRouter;
213
+ var TanStackRouterSync = ({
214
+ onRouterAvailable
215
+ }) => {
216
+ const useRouter2 = TanStackRouter.useRouter;
217
+ if (typeof useRouter2 !== "function") {
218
+ if (typeof console !== "undefined") {
219
+ console.warn(
220
+ "[tour][router] TanStackRouterSync requires @tanstack/react-router. Call this component only inside TanStack Router environments."
221
+ );
222
+ }
223
+ return null;
224
+ }
225
+ useTanStackRouterTourAdapter();
226
+ const router = useRouter2();
227
+ (0, import_react.useEffect)(() => {
228
+ setTourRouter(router);
229
+ onRouterAvailable?.(router);
230
+ return () => {
231
+ if (getTourRouter() === router) {
232
+ setTourRouter(null);
233
+ }
234
+ onRouterAvailable?.(null);
235
+ };
236
+ }, [router, onRouterAvailable]);
237
+ return null;
238
+ };
239
+
186
240
  // src/router/tanstackRouterAdapter.tsx
187
241
  var useTanStackRouterTourAdapter = () => {
188
242
  const location = (0, import_react_router.useRouterState)({
189
243
  select: (state) => state.location
190
244
  });
191
- (0, import_react.useEffect)(() => {
245
+ (0, import_react2.useEffect)(() => {
192
246
  const resolvedPathname = typeof location.pathname === "string" && location.pathname.length > 0 ? location.pathname : "/";
193
247
  const resolvedSearch = "searchStr" in location && typeof location.searchStr === "string" ? location.searchStr : typeof location.search === "string" ? location.search : "";
194
248
  const resolvedHash = typeof location.hash === "string" ? location.hash : "";
@@ -198,5 +252,10 @@ var useTanStackRouterTourAdapter = () => {
198
252
  };
199
253
  // Annotate the CommonJS export names for ESM import in node:
200
254
  0 && (module.exports = {
255
+ TanStackRouterSync,
256
+ getTanStackRouter,
257
+ getTourRouter,
258
+ setTanStackRouter,
259
+ setTourRouter,
201
260
  useTanStackRouterTourAdapter
202
261
  });
@@ -1,2 +1,4 @@
1
+ export { getTanStackRouter, getTourRouter, setTanStackRouter, setTourRouter, TanStackRouterSync, } from './tanstackRouterSync';
2
+ export type { TanStackRouterSyncProps } from './tanstackRouterSync';
1
3
  export declare const useTanStackRouterTourAdapter: () => void;
2
4
  //# sourceMappingURL=tanstackRouterAdapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tanstackRouterAdapter.d.ts","sourceRoot":"","sources":["../../src/router/tanstackRouterAdapter.tsx"],"names":[],"mappings":"AAMA,eAAO,MAAM,4BAA4B,YAyBxC,CAAA"}
1
+ {"version":3,"file":"tanstackRouterAdapter.d.ts","sourceRoot":"","sources":["../../src/router/tanstackRouterAdapter.tsx"],"names":[],"mappings":"AAOA,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GACnB,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAEnE,eAAO,MAAM,4BAA4B,YAyBxC,CAAA"}
@@ -1,7 +1,17 @@
1
1
  import {
2
+ TanStackRouterSync,
3
+ getTanStackRouter,
4
+ getTourRouter,
5
+ setTanStackRouter,
6
+ setTourRouter,
2
7
  useTanStackRouterTourAdapter
3
- } from "../chunk-LQFOZS4Y.mjs";
4
- import "../chunk-WTGQUDPT.mjs";
8
+ } from "../chunk-2ZX2Y3JL.mjs";
9
+ import "../chunk-B44EX7YT.mjs";
5
10
  export {
11
+ TanStackRouterSync,
12
+ getTanStackRouter,
13
+ getTourRouter,
14
+ setTanStackRouter,
15
+ setTourRouter,
6
16
  useTanStackRouterTourAdapter
7
17
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowsterix/react",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "React bindings for Flowsterix - guided tours and onboarding flows",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -64,7 +64,7 @@
64
64
  ],
65
65
  "dependencies": {
66
66
  "@floating-ui/dom": "^1.7.4",
67
- "@flowsterix/core": "0.3.0"
67
+ "@flowsterix/core": "0.4.0"
68
68
  },
69
69
  "peerDependencies": {
70
70
  "react": ">=18",
@@ -1,24 +0,0 @@
1
- import {
2
- createPathString,
3
- notifyRouteChange
4
- } from "./chunk-WTGQUDPT.mjs";
5
-
6
- // src/router/tanstackRouterAdapter.tsx
7
- import { useRouterState } from "@tanstack/react-router";
8
- import { useEffect } from "react";
9
- var useTanStackRouterTourAdapter = () => {
10
- const location = useRouterState({
11
- select: (state) => state.location
12
- });
13
- useEffect(() => {
14
- const resolvedPathname = typeof location.pathname === "string" && location.pathname.length > 0 ? location.pathname : "/";
15
- const resolvedSearch = "searchStr" in location && typeof location.searchStr === "string" ? location.searchStr : typeof location.search === "string" ? location.search : "";
16
- const resolvedHash = typeof location.hash === "string" ? location.hash : "";
17
- const path = typeof location.href === "string" && location.href.length > 0 ? location.href : createPathString(resolvedPathname, resolvedSearch, resolvedHash);
18
- notifyRouteChange(path);
19
- }, [location]);
20
- };
21
-
22
- export {
23
- useTanStackRouterTourAdapter
24
- };