@flowsterix/react 0.9.0 → 0.10.1

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 CHANGED
@@ -21,12 +21,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  AnimationAdapterProvider: () => AnimationAdapterProvider,
24
+ DialogRegistryProvider: () => DialogRegistryProvider,
24
25
  OverlayBackdrop: () => OverlayBackdrop,
25
26
  TourFocusManager: () => TourFocusManager,
26
27
  TourPopoverPortal: () => TourPopoverPortal,
27
28
  TourProvider: () => TourProvider,
28
29
  createPathString: () => createPathString,
29
- createRadixDialogHelpers: () => createRadixDialogHelpers,
30
30
  createWaitForPredicateController: () => createWaitForPredicateController,
31
31
  defaultAnimationAdapter: () => defaultAnimationAdapter,
32
32
  defaultLabels: () => defaultLabels,
@@ -38,6 +38,8 @@ __export(index_exports, {
38
38
  useAnimationAdapter: () => useAnimationAdapter,
39
39
  useBodyScrollLock: () => useBodyScrollLock,
40
40
  useDelayAdvance: () => useDelayAdvance,
41
+ useDialogRegistry: () => useDialogRegistry,
42
+ useDialogRegistryOptional: () => useDialogRegistryOptional,
41
43
  useHiddenTargetFallback: () => useHiddenTargetFallback,
42
44
  useHudDescription: () => useHudDescription,
43
45
  useHudMotion: () => useHudMotion,
@@ -46,6 +48,7 @@ __export(index_exports, {
46
48
  useHudTargetIssue: () => useHudTargetIssue,
47
49
  usePreferredAnimationAdapter: () => usePreferredAnimationAdapter,
48
50
  useRadixDialogAdapter: () => useRadixDialogAdapter,
51
+ useRadixTourDialog: () => useRadixTourDialog,
49
52
  useTour: () => useTour,
50
53
  useTourControls: () => useTourControls,
51
54
  useTourEvents: () => useTourEvents,
@@ -61,7 +64,7 @@ module.exports = __toCommonJS(index_exports);
61
64
 
62
65
  // src/context.tsx
63
66
  var import_core = require("@flowsterix/core");
64
- var import_react4 = require("react");
67
+ var import_react6 = require("react");
65
68
 
66
69
  // src/labels.ts
67
70
  var import_react = require("react");
@@ -92,20 +95,166 @@ function useTourLabels() {
92
95
  return (0, import_react.useContext)(LabelsContext);
93
96
  }
94
97
 
95
- // src/motion/animationAdapter.tsx
96
- var import_react2 = require("motion/react");
97
- var import_react3 = require("react");
98
+ // src/dialog/DialogRegistryContext.tsx
99
+ var import_react2 = require("react");
98
100
  var import_jsx_runtime = require("react/jsx-runtime");
101
+ var DialogRegistryContext = (0, import_react2.createContext)(void 0);
102
+ var DialogRegistryProvider = ({ children }) => {
103
+ const controllersRef = (0, import_react2.useRef)(/* @__PURE__ */ new Map());
104
+ const register = (0, import_react2.useCallback)(
105
+ (dialogId, controller) => {
106
+ controllersRef.current.set(dialogId, controller);
107
+ },
108
+ []
109
+ );
110
+ const unregister = (0, import_react2.useCallback)((dialogId) => {
111
+ controllersRef.current.delete(dialogId);
112
+ }, []);
113
+ const getController = (0, import_react2.useCallback)((dialogId) => {
114
+ return controllersRef.current.get(dialogId);
115
+ }, []);
116
+ const isRegistered = (0, import_react2.useCallback)((dialogId) => {
117
+ return controllersRef.current.has(dialogId);
118
+ }, []);
119
+ const value = (0, import_react2.useMemo)(
120
+ () => ({
121
+ register,
122
+ unregister,
123
+ getController,
124
+ isRegistered
125
+ }),
126
+ [register, unregister, getController, isRegistered]
127
+ );
128
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogRegistryContext.Provider, { value, children });
129
+ };
130
+ var useDialogRegistry = () => {
131
+ const context = (0, import_react2.useContext)(DialogRegistryContext);
132
+ if (!context) {
133
+ throw new Error(
134
+ "useDialogRegistry must be used within a DialogRegistryProvider"
135
+ );
136
+ }
137
+ return context;
138
+ };
139
+ var useDialogRegistryOptional = () => {
140
+ return (0, import_react2.useContext)(DialogRegistryContext);
141
+ };
142
+
143
+ // src/hooks/useDialogAutomation.ts
144
+ var import_react3 = require("react");
145
+ var resolveAutoOpen = (config) => {
146
+ if (!config) return { onEnter: true, onResume: true };
147
+ const { autoOpen } = config;
148
+ if (autoOpen === false) return { onEnter: false, onResume: false };
149
+ if (autoOpen === true || autoOpen === void 0) {
150
+ return { onEnter: true, onResume: true };
151
+ }
152
+ return {
153
+ onEnter: autoOpen.onEnter ?? true,
154
+ onResume: autoOpen.onResume ?? true
155
+ };
156
+ };
157
+ var useDialogAutomation = (params) => {
158
+ const { flow, state, events, registry, onDialogNotMounted } = params;
159
+ const previousDialogIdRef = (0, import_react3.useRef)(void 0);
160
+ (0, import_react3.useEffect)(() => {
161
+ if (!events || !flow || !registry) return;
162
+ const unsubscribeEnter = events.on("stepEnter", (payload) => {
163
+ const step = payload.currentStep;
164
+ const dialogId = step.dialogId;
165
+ const previousDialogId = previousDialogIdRef.current;
166
+ if (previousDialogId && previousDialogId !== dialogId && flow.dialogs?.[previousDialogId]) {
167
+ const config = flow.dialogs[previousDialogId];
168
+ const autoClose = config.autoClose ?? "differentDialog";
169
+ if (autoClose === "always" || autoClose === "differentDialog") {
170
+ const controller = registry.getController(previousDialogId);
171
+ if (controller) {
172
+ requestAnimationFrame(() => {
173
+ controller.close();
174
+ });
175
+ }
176
+ }
177
+ }
178
+ if (dialogId && flow.dialogs?.[dialogId]) {
179
+ const config = flow.dialogs[dialogId];
180
+ const autoOpenConfig = resolveAutoOpen(config);
181
+ const isResume = payload.reason === "resume";
182
+ const shouldAutoOpen = isResume ? autoOpenConfig.onResume : autoOpenConfig.onEnter;
183
+ if (shouldAutoOpen) {
184
+ const controller = registry.getController(dialogId);
185
+ if (controller) {
186
+ requestAnimationFrame(() => {
187
+ controller.open();
188
+ });
189
+ } else if (onDialogNotMounted) {
190
+ onDialogNotMounted(dialogId, step.id);
191
+ }
192
+ }
193
+ }
194
+ previousDialogIdRef.current = dialogId;
195
+ });
196
+ const unsubscribeExit = events.on("stepExit", (payload) => {
197
+ const step = payload.previousStep;
198
+ const dialogId = step.dialogId;
199
+ const nextStep = payload.currentStep;
200
+ if (nextStep?.dialogId === dialogId) return;
201
+ if (dialogId && flow.dialogs?.[dialogId]) {
202
+ const config = flow.dialogs[dialogId];
203
+ const autoClose = config.autoClose ?? "differentDialog";
204
+ if (autoClose === "never") return;
205
+ const controller = registry.getController(dialogId);
206
+ if (controller) {
207
+ requestAnimationFrame(() => {
208
+ controller.close();
209
+ });
210
+ }
211
+ }
212
+ });
213
+ const handleFlowEnd = () => {
214
+ const dialogId = previousDialogIdRef.current;
215
+ if (dialogId && flow.dialogs?.[dialogId]) {
216
+ const config = flow.dialogs[dialogId];
217
+ const autoClose = config.autoClose ?? "differentDialog";
218
+ if (autoClose !== "never") {
219
+ const controller = registry.getController(dialogId);
220
+ controller?.close();
221
+ }
222
+ }
223
+ previousDialogIdRef.current = void 0;
224
+ };
225
+ const unsubscribePause = events.on("flowPause", handleFlowEnd);
226
+ const unsubscribeCancel = events.on("flowCancel", handleFlowEnd);
227
+ const unsubscribeComplete = events.on("flowComplete", handleFlowEnd);
228
+ return () => {
229
+ unsubscribeEnter();
230
+ unsubscribeExit();
231
+ unsubscribePause();
232
+ unsubscribeCancel();
233
+ unsubscribeComplete();
234
+ };
235
+ }, [events, flow, registry, onDialogNotMounted]);
236
+ (0, import_react3.useEffect)(() => {
237
+ if (!flow || !state || state.status !== "running") return;
238
+ if (state.stepIndex < 0 || state.stepIndex >= flow.steps.length) return;
239
+ const currentStep = flow.steps[state.stepIndex];
240
+ previousDialogIdRef.current = currentStep.dialogId;
241
+ }, [flow, state]);
242
+ };
243
+
244
+ // src/motion/animationAdapter.tsx
245
+ var import_react4 = require("motion/react");
246
+ var import_react5 = require("react");
247
+ var import_jsx_runtime2 = require("react/jsx-runtime");
99
248
  var defaultAdapter = {
100
249
  components: {
101
- MotionDiv: import_react2.motion.div,
102
- MotionSection: import_react2.motion.section,
103
- MotionSvg: import_react2.motion.svg,
104
- MotionDefs: import_react2.motion.defs,
105
- MotionMask: import_react2.motion.mask,
106
- MotionRect: import_react2.motion.rect,
107
- MotionSpan: import_react2.motion.span,
108
- MotionButton: import_react2.motion.button
250
+ MotionDiv: import_react4.motion.div,
251
+ MotionSection: import_react4.motion.section,
252
+ MotionSvg: import_react4.motion.svg,
253
+ MotionDefs: import_react4.motion.defs,
254
+ MotionMask: import_react4.motion.mask,
255
+ MotionRect: import_react4.motion.rect,
256
+ MotionSpan: import_react4.motion.span,
257
+ MotionButton: import_react4.motion.button
109
258
  },
110
259
  transitions: {
111
260
  overlayHighlight: {
@@ -138,16 +287,16 @@ var defaultAdapter = {
138
287
  }
139
288
  }
140
289
  };
141
- var AnimationAdapterContext = (0, import_react3.createContext)(defaultAdapter);
290
+ var AnimationAdapterContext = (0, import_react5.createContext)(defaultAdapter);
142
291
  var AnimationAdapterProvider = ({
143
292
  adapter,
144
293
  children
145
294
  }) => {
146
- const value = (0, import_react3.useMemo)(() => adapter ?? defaultAdapter, [adapter]);
147
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AnimationAdapterContext.Provider, { value, children });
295
+ const value = (0, import_react5.useMemo)(() => adapter ?? defaultAdapter, [adapter]);
296
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AnimationAdapterContext.Provider, { value, children });
148
297
  };
149
298
  var useAnimationAdapter = () => {
150
- return (0, import_react3.useContext)(AnimationAdapterContext);
299
+ return (0, import_react5.useContext)(AnimationAdapterContext);
151
300
  };
152
301
  var defaultAnimationAdapter = defaultAdapter;
153
302
  var reducedMotionAnimationAdapter = {
@@ -187,11 +336,11 @@ var usePreferredAnimationAdapter = (options) => {
187
336
  reducedMotionAdapter: reducedOption = reducedMotionAnimationAdapter,
188
337
  enabled = true
189
338
  } = options ?? {};
190
- const [prefersReduced, setPrefersReduced] = (0, import_react3.useState)(() => {
339
+ const [prefersReduced, setPrefersReduced] = (0, import_react5.useState)(() => {
191
340
  if (!enabled || typeof window === "undefined") return false;
192
341
  return window.matchMedia(REDUCED_MOTION_QUERY).matches;
193
342
  });
194
- (0, import_react3.useEffect)(() => {
343
+ (0, import_react5.useEffect)(() => {
195
344
  if (!enabled || typeof window === "undefined") return;
196
345
  const mediaQuery = window.matchMedia(REDUCED_MOTION_QUERY);
197
346
  const handleChange = (event) => {
@@ -439,11 +588,11 @@ var matchRoute = (params) => {
439
588
  };
440
589
 
441
590
  // src/context.tsx
442
- var import_jsx_runtime2 = require("react/jsx-runtime");
443
- var TourContext = (0, import_react4.createContext)(void 0);
591
+ var import_jsx_runtime3 = require("react/jsx-runtime");
592
+ var TourContext = (0, import_react6.createContext)(void 0);
444
593
  var DEFAULT_STORAGE_PREFIX = "tour";
445
594
  var useFlowMap = (flows) => {
446
- return (0, import_react4.useMemo)(() => {
595
+ return (0, import_react6.useMemo)(() => {
447
596
  const map = /* @__PURE__ */ new Map();
448
597
  for (const flow of flows) {
449
598
  map.set(flow.id, flow);
@@ -467,25 +616,25 @@ var TourProvider = ({
467
616
  labels: labelsProp,
468
617
  onVersionMismatch
469
618
  }) => {
470
- const mergedLabels = (0, import_react4.useMemo)(
619
+ const mergedLabels = (0, import_react6.useMemo)(
471
620
  () => ({ ...defaultLabels, ...labelsProp }),
472
621
  [labelsProp]
473
622
  );
474
623
  const flowMap = useFlowMap(flows);
475
- const storeRef = (0, import_react4.useRef)(null);
476
- const unsubscribeRef = (0, import_react4.useRef)(null);
477
- const stepHooksUnsubscribeRef = (0, import_react4.useRef)(null);
478
- const fallbackStorageRef = (0, import_react4.useRef)(void 0);
479
- const pendingResumeRef = (0, import_react4.useRef)(/* @__PURE__ */ new Set());
480
- const autoStartRequestedRef = (0, import_react4.useRef)(null);
481
- const [activeFlowId, setActiveFlowId] = (0, import_react4.useState)(null);
482
- const [state, setState] = (0, import_react4.useState)(null);
483
- const [events, setEvents] = (0, import_react4.useState)(
624
+ const storeRef = (0, import_react6.useRef)(null);
625
+ const unsubscribeRef = (0, import_react6.useRef)(null);
626
+ const stepHooksUnsubscribeRef = (0, import_react6.useRef)(null);
627
+ const fallbackStorageRef = (0, import_react6.useRef)(void 0);
628
+ const pendingResumeRef = (0, import_react6.useRef)(/* @__PURE__ */ new Set());
629
+ const autoStartRequestedRef = (0, import_react6.useRef)(null);
630
+ const [activeFlowId, setActiveFlowId] = (0, import_react6.useState)(null);
631
+ const [state, setState] = (0, import_react6.useState)(null);
632
+ const [events, setEvents] = (0, import_react6.useState)(
484
633
  null
485
634
  );
486
- const [debugEnabled, setDebugEnabled] = (0, import_react4.useState)(defaultDebug);
487
- const [delayInfo, setDelayInfo] = (0, import_react4.useState)(null);
488
- const teardownStore = (0, import_react4.useCallback)(() => {
635
+ const [debugEnabled, setDebugEnabled] = (0, import_react6.useState)(defaultDebug);
636
+ const [delayInfo, setDelayInfo] = (0, import_react6.useState)(null);
637
+ const teardownStore = (0, import_react6.useCallback)(() => {
489
638
  unsubscribeRef.current?.();
490
639
  unsubscribeRef.current = null;
491
640
  stepHooksUnsubscribeRef.current?.();
@@ -495,7 +644,7 @@ var TourProvider = ({
495
644
  setDelayInfo(null);
496
645
  pendingResumeRef.current.clear();
497
646
  }, []);
498
- (0, import_react4.useEffect)(() => {
647
+ (0, import_react6.useEffect)(() => {
499
648
  return () => {
500
649
  teardownStore();
501
650
  setState(null);
@@ -503,7 +652,7 @@ var TourProvider = ({
503
652
  setActiveFlowId(null);
504
653
  };
505
654
  }, [teardownStore]);
506
- (0, import_react4.useEffect)(() => {
655
+ (0, import_react6.useEffect)(() => {
507
656
  if (!activeFlowId) return;
508
657
  const definition = flowMap.get(activeFlowId);
509
658
  if (!definition) {
@@ -526,7 +675,7 @@ var TourProvider = ({
526
675
  console.warn(`[tour][step] ${phase} hook failed`, error);
527
676
  }
528
677
  };
529
- const ensureStore = (0, import_react4.useCallback)(
678
+ const ensureStore = (0, import_react6.useCallback)(
530
679
  (flowId) => {
531
680
  const existing = storeRef.current;
532
681
  if (existing && existing.definition.id === flowId) {
@@ -585,7 +734,7 @@ var TourProvider = ({
585
734
  teardownStore
586
735
  ]
587
736
  );
588
- const getActiveStore = (0, import_react4.useCallback)(() => {
737
+ const getActiveStore = (0, import_react6.useCallback)(() => {
589
738
  const store = storeRef.current;
590
739
  if (!store) {
591
740
  throw new Error(
@@ -597,7 +746,7 @@ var TourProvider = ({
597
746
  const isPromiseLike2 = (value) => {
598
747
  return typeof value === "object" && value !== null && typeof value.then === "function";
599
748
  };
600
- const invokeStepHook = (0, import_react4.useCallback)(
749
+ const invokeStepHook = (0, import_react6.useCallback)(
601
750
  async (hook, context, phase) => {
602
751
  if (!hook) return;
603
752
  try {
@@ -611,7 +760,7 @@ var TourProvider = ({
611
760
  },
612
761
  []
613
762
  );
614
- const runResumeHooks = (0, import_react4.useCallback)(
763
+ const runResumeHooks = (0, import_react6.useCallback)(
615
764
  async (definition, flowState, strategy) => {
616
765
  if (flowState.status !== "running") return;
617
766
  if (strategy === "current") {
@@ -651,13 +800,13 @@ var TourProvider = ({
651
800
  },
652
801
  [invokeStepHook]
653
802
  );
654
- const resolveResumeStrategy = (0, import_react4.useCallback)(
803
+ const resolveResumeStrategy = (0, import_react6.useCallback)(
655
804
  (definition, options) => {
656
805
  return options?.resumeStrategy ?? definition.resumeStrategy ?? "chain";
657
806
  },
658
807
  []
659
808
  );
660
- const startFlow = (0, import_react4.useCallback)(
809
+ const startFlow = (0, import_react6.useCallback)(
661
810
  (flowId, options) => {
662
811
  const store = ensureStore(flowId);
663
812
  const previousState = store.getState();
@@ -686,8 +835,8 @@ var TourProvider = ({
686
835
  },
687
836
  [ensureStore, resolveResumeStrategy, runResumeHooks]
688
837
  );
689
- const [eligibleFlows, setEligibleFlows] = (0, import_react4.useState)([]);
690
- (0, import_react4.useEffect)(() => {
838
+ const [eligibleFlows, setEligibleFlows] = (0, import_react6.useState)([]);
839
+ (0, import_react6.useEffect)(() => {
691
840
  const autoStartFlows = flows.filter((f) => f.autoStart);
692
841
  if (autoStartFlows.length === 0) {
693
842
  setEligibleFlows([]);
@@ -751,7 +900,7 @@ var TourProvider = ({
751
900
  cancelled = true;
752
901
  };
753
902
  }, [flows, storageAdapter, storageNamespace]);
754
- (0, import_react4.useEffect)(() => {
903
+ (0, import_react6.useEffect)(() => {
755
904
  if (eligibleFlows.length === 0) {
756
905
  autoStartRequestedRef.current = null;
757
906
  return;
@@ -786,14 +935,14 @@ var TourProvider = ({
786
935
  }
787
936
  };
788
937
  }, [activeFlowId, eligibleFlows, startFlow]);
789
- const next = (0, import_react4.useCallback)(() => getActiveStore().next(), [getActiveStore]);
790
- const back = (0, import_react4.useCallback)(() => getActiveStore().back(), [getActiveStore]);
791
- const goToStep = (0, import_react4.useCallback)(
938
+ const next = (0, import_react6.useCallback)(() => getActiveStore().next(), [getActiveStore]);
939
+ const back = (0, import_react6.useCallback)(() => getActiveStore().back(), [getActiveStore]);
940
+ const goToStep = (0, import_react6.useCallback)(
792
941
  (step) => getActiveStore().goToStep(step),
793
942
  [getActiveStore]
794
943
  );
795
- const pause = (0, import_react4.useCallback)(() => getActiveStore().pause(), [getActiveStore]);
796
- const resume = (0, import_react4.useCallback)(() => {
944
+ const pause = (0, import_react6.useCallback)(() => getActiveStore().pause(), [getActiveStore]);
945
+ const resume = (0, import_react6.useCallback)(() => {
797
946
  const store = getActiveStore();
798
947
  const previousState = store.getState();
799
948
  if (previousState.status === "paused") {
@@ -811,27 +960,31 @@ var TourProvider = ({
811
960
  }
812
961
  return result;
813
962
  }, [getActiveStore, resolveResumeStrategy, runResumeHooks]);
814
- const cancel = (0, import_react4.useCallback)(
963
+ const cancel = (0, import_react6.useCallback)(
815
964
  (reason) => getActiveStore().cancel(reason),
816
965
  [getActiveStore]
817
966
  );
818
- const complete = (0, import_react4.useCallback)(
967
+ const complete = (0, import_react6.useCallback)(
819
968
  () => getActiveStore().complete(),
820
969
  [getActiveStore]
821
970
  );
822
- const advanceStep = (0, import_react4.useCallback)(
971
+ const advanceStep = (0, import_react6.useCallback)(
823
972
  (stepId) => getActiveStore().advanceStep(stepId),
824
973
  [getActiveStore]
825
974
  );
826
- const toggleDebug = (0, import_react4.useCallback)(() => {
975
+ const toggleDebug = (0, import_react6.useCallback)(() => {
827
976
  setDebugEnabled((previous) => !previous);
828
977
  }, []);
829
- const activeStep = (0, import_react4.useMemo)(() => {
978
+ const activeStep = (0, import_react6.useMemo)(() => {
830
979
  if (!state || !storeRef.current) return null;
831
980
  if (state.stepIndex < 0) return null;
832
981
  return storeRef.current.definition.steps[state.stepIndex] ?? null;
833
982
  }, [state]);
834
- (0, import_react4.useEffect)(() => {
983
+ const activeDialogConfig = (0, import_react6.useMemo)(() => {
984
+ if (!activeStep?.dialogId || !storeRef.current) return void 0;
985
+ return storeRef.current.definition.dialogs?.[activeStep.dialogId];
986
+ }, [activeStep]);
987
+ (0, import_react6.useEffect)(() => {
835
988
  if (!activeFlowId) return;
836
989
  if (!pendingResumeRef.current.has(activeFlowId)) return;
837
990
  if (!state || state.status !== "running") return;
@@ -846,12 +999,13 @@ var TourProvider = ({
846
999
  pendingResumeRef.current.delete(activeFlowId);
847
1000
  void runResumeHooks(definition, state, resumeStrategy);
848
1001
  }, [activeFlowId, flowMap, resolveResumeStrategy, runResumeHooks, state]);
849
- const contextValue = (0, import_react4.useMemo)(
1002
+ const contextValue = (0, import_react6.useMemo)(
850
1003
  () => ({
851
1004
  flows: flowMap,
852
1005
  activeFlowId,
853
1006
  state,
854
1007
  activeStep,
1008
+ activeDialogConfig,
855
1009
  startFlow,
856
1010
  next,
857
1011
  back,
@@ -873,6 +1027,7 @@ var TourProvider = ({
873
1027
  [
874
1028
  activeFlowId,
875
1029
  activeStep,
1030
+ activeDialogConfig,
876
1031
  advanceStep,
877
1032
  back,
878
1033
  cancel,
@@ -899,10 +1054,41 @@ var TourProvider = ({
899
1054
  reducedMotionAdapter,
900
1055
  enabled: autoDetectReducedMotion
901
1056
  });
902
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AnimationAdapterProvider, { adapter: resolvedAnimationAdapter, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LabelsProvider, { value: mergedLabels, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TourContext.Provider, { value: contextValue, children }) }) });
1057
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AnimationAdapterProvider, { adapter: resolvedAnimationAdapter, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LabelsProvider, { value: mergedLabels, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DialogRegistryProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(TourContext.Provider, { value: contextValue, children: [
1058
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1059
+ DialogAutomationBridge,
1060
+ {
1061
+ flow: activeFlowId ? flowMap.get(activeFlowId) : void 0,
1062
+ state,
1063
+ events
1064
+ }
1065
+ ),
1066
+ children
1067
+ ] }) }) }) });
1068
+ };
1069
+ var DialogAutomationBridge = ({
1070
+ flow,
1071
+ state,
1072
+ events
1073
+ }) => {
1074
+ const registry = useDialogRegistryOptional();
1075
+ useDialogAutomation({
1076
+ flow,
1077
+ state,
1078
+ events,
1079
+ registry,
1080
+ onDialogNotMounted: (dialogId, stepId) => {
1081
+ if (process.env.NODE_ENV !== "production") {
1082
+ console.warn(
1083
+ `[tour] Step "${stepId}" references dialogId "${dialogId}" but no dialog is mounted with that ID. Ensure your dialog uses useTourDialog({ dialogId: "${dialogId}" }).`
1084
+ );
1085
+ }
1086
+ }
1087
+ });
1088
+ return null;
903
1089
  };
904
1090
  var useTour = () => {
905
- const context = (0, import_react4.useContext)(TourContext);
1091
+ const context = (0, import_react6.useContext)(TourContext);
906
1092
  if (!context) {
907
1093
  throw new Error("useTour must be used within a TourProvider");
908
1094
  }
@@ -910,14 +1096,14 @@ var useTour = () => {
910
1096
  };
911
1097
  var useTourEvents = (event, handler) => {
912
1098
  const { events } = useTour();
913
- (0, import_react4.useEffect)(() => {
1099
+ (0, import_react6.useEffect)(() => {
914
1100
  if (!events) return;
915
1101
  return events.on(event, handler);
916
1102
  }, [event, events, handler]);
917
1103
  };
918
1104
 
919
1105
  // src/hooks/useTourTarget.ts
920
- var import_react5 = require("react");
1106
+ var import_react7 = require("react");
921
1107
 
922
1108
  // src/hooks/scrollMargin.ts
923
1109
  var DEFAULT_SCROLL_MARGIN = 16;
@@ -1220,12 +1406,12 @@ var resolveStepTarget = (target) => {
1220
1406
  };
1221
1407
  var useTourTarget = () => {
1222
1408
  const { activeStep, state, activeFlowId, flows } = useTour();
1223
- const [targetInfo, setTargetInfo] = (0, import_react5.useState)(INITIAL_TARGET_INFO);
1224
- const autoScrollStateRef = (0, import_react5.useRef)({ stepId: null, checks: 0, stalledChecks: 0, done: false, lastRect: null });
1225
- const autoScrollRafRef = (0, import_react5.useRef)(null);
1226
- const autoScrollTimeoutRef = (0, import_react5.useRef)(null);
1227
- const lastRectRef = (0, import_react5.useRef)(null);
1228
- const initialScrollStepRef = (0, import_react5.useRef)(null);
1409
+ const [targetInfo, setTargetInfo] = (0, import_react7.useState)(INITIAL_TARGET_INFO);
1410
+ const autoScrollStateRef = (0, import_react7.useRef)({ stepId: null, checks: 0, stalledChecks: 0, done: false, lastRect: null });
1411
+ const autoScrollRafRef = (0, import_react7.useRef)(null);
1412
+ const autoScrollTimeoutRef = (0, import_react7.useRef)(null);
1413
+ const lastRectRef = (0, import_react7.useRef)(null);
1414
+ const initialScrollStepRef = (0, import_react7.useRef)(null);
1229
1415
  const cancelAutoScrollLoop = () => {
1230
1416
  if (!isBrowser) return;
1231
1417
  if (autoScrollTimeoutRef.current !== null) {
@@ -1237,7 +1423,7 @@ var useTourTarget = () => {
1237
1423
  autoScrollRafRef.current = null;
1238
1424
  }
1239
1425
  };
1240
- (0, import_react5.useEffect)(() => {
1426
+ (0, import_react7.useEffect)(() => {
1241
1427
  if (!activeStep) {
1242
1428
  initialScrollStepRef.current = null;
1243
1429
  }
@@ -1245,7 +1431,7 @@ var useTourTarget = () => {
1245
1431
  initialScrollStepRef.current = null;
1246
1432
  };
1247
1433
  }, [activeStep?.id]);
1248
- (0, import_react5.useLayoutEffect)(() => {
1434
+ (0, import_react7.useLayoutEffect)(() => {
1249
1435
  if (!isBrowser) return;
1250
1436
  if (!activeStep) return;
1251
1437
  if (targetInfo.status !== "ready") return;
@@ -1277,7 +1463,7 @@ var useTourTarget = () => {
1277
1463
  targetInfo.status,
1278
1464
  targetInfo.rectSource
1279
1465
  ]);
1280
- (0, import_react5.useEffect)(() => {
1466
+ (0, import_react7.useEffect)(() => {
1281
1467
  if (!activeStep || !state || state.status !== "running") {
1282
1468
  setTargetInfo(INITIAL_TARGET_INFO);
1283
1469
  autoScrollStateRef.current = {
@@ -1600,7 +1786,7 @@ var useTourTarget = () => {
1600
1786
  waitForPredicateController = null;
1601
1787
  };
1602
1788
  }, [activeStep, activeFlowId, flows, state]);
1603
- (0, import_react5.useEffect)(() => {
1789
+ (0, import_react7.useEffect)(() => {
1604
1790
  if (!isBrowser) return;
1605
1791
  if (!activeStep) {
1606
1792
  cancelAutoScrollLoop();
@@ -1681,10 +1867,10 @@ var useTourTarget = () => {
1681
1867
  };
1682
1868
 
1683
1869
  // src/hooks/useHudState.ts
1684
- var import_react10 = require("react");
1870
+ var import_react12 = require("react");
1685
1871
 
1686
1872
  // src/hooks/useAdvanceRules.ts
1687
- var import_react6 = require("react");
1873
+ var import_react8 = require("react");
1688
1874
  var DEFAULT_POLL_MS2 = 250;
1689
1875
  var isListenerTarget = (value) => {
1690
1876
  return !!value && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function";
@@ -1723,7 +1909,7 @@ var useAdvanceRules = (target) => {
1723
1909
  complete,
1724
1910
  setDelayInfo
1725
1911
  } = useTour();
1726
- (0, import_react6.useEffect)(() => {
1912
+ (0, import_react8.useEffect)(() => {
1727
1913
  if (!isBrowser) return;
1728
1914
  if (!state || state.status !== "running") return;
1729
1915
  if (!activeStep) return;
@@ -1894,7 +2080,7 @@ var useAdvanceRules = (target) => {
1894
2080
  };
1895
2081
 
1896
2082
  // src/hooks/useHiddenTargetFallback.ts
1897
- var import_react7 = require("react");
2083
+ var import_react9 = require("react");
1898
2084
  var DEFAULT_DELAY_MS = 900;
1899
2085
  var DEFAULT_GRACE_PERIOD_MS = 400;
1900
2086
  var useHiddenTargetFallback = ({
@@ -1903,11 +2089,11 @@ var useHiddenTargetFallback = ({
1903
2089
  viewportRect,
1904
2090
  onSkip
1905
2091
  }) => {
1906
- const [usingScreenFallback, setUsingScreenFallback] = (0, import_react7.useState)(false);
1907
- const [isInGracePeriod, setIsInGracePeriod] = (0, import_react7.useState)(false);
1908
- const timeoutRef = (0, import_react7.useRef)(null);
1909
- const graceTimeoutRef = (0, import_react7.useRef)(null);
1910
- const skipTriggeredRef = (0, import_react7.useRef)(false);
2092
+ const [usingScreenFallback, setUsingScreenFallback] = (0, import_react9.useState)(false);
2093
+ const [isInGracePeriod, setIsInGracePeriod] = (0, import_react9.useState)(false);
2094
+ const timeoutRef = (0, import_react9.useRef)(null);
2095
+ const graceTimeoutRef = (0, import_react9.useRef)(null);
2096
+ const skipTriggeredRef = (0, import_react9.useRef)(false);
1911
2097
  const hiddenMode = step?.targetBehavior?.hidden ?? "screen";
1912
2098
  const hiddenDelayMs = Math.max(
1913
2099
  0,
@@ -1925,7 +2111,7 @@ var useHiddenTargetFallback = ({
1925
2111
  graceTimeoutRef.current = null;
1926
2112
  }
1927
2113
  };
1928
- (0, import_react7.useEffect)(() => {
2114
+ (0, import_react9.useEffect)(() => {
1929
2115
  skipTriggeredRef.current = false;
1930
2116
  setUsingScreenFallback(false);
1931
2117
  setIsInGracePeriod(false);
@@ -1936,7 +2122,7 @@ var useHiddenTargetFallback = ({
1936
2122
  clearGraceTimeout();
1937
2123
  };
1938
2124
  }, [step?.id]);
1939
- (0, import_react7.useEffect)(() => {
2125
+ (0, import_react9.useEffect)(() => {
1940
2126
  if (!isBrowser) return void 0;
1941
2127
  if (!step) return void 0;
1942
2128
  clearPendingTimeout();
@@ -1982,7 +2168,7 @@ var useHiddenTargetFallback = ({
1982
2168
  hiddenDelayMs,
1983
2169
  onSkip
1984
2170
  ]);
1985
- const resolvedTarget = (0, import_react7.useMemo)(() => {
2171
+ const resolvedTarget = (0, import_react9.useMemo)(() => {
1986
2172
  if (!usingScreenFallback) {
1987
2173
  return target;
1988
2174
  }
@@ -2004,7 +2190,7 @@ var useHiddenTargetFallback = ({
2004
2190
  };
2005
2191
 
2006
2192
  // src/hooks/useRouteMismatch.ts
2007
- var import_react8 = require("react");
2193
+ var import_react10 = require("react");
2008
2194
 
2009
2195
  // src/router/utils.ts
2010
2196
  var ensurePrefix = (value, prefix) => value.startsWith(prefix) ? value : `${prefix}${value}`;
@@ -2051,8 +2237,8 @@ var createPathString = (pathname, search, hash) => {
2051
2237
 
2052
2238
  // src/hooks/useRouteMismatch.ts
2053
2239
  var useRouteMismatch = (step) => {
2054
- const [currentPath, setCurrentPath] = (0, import_react8.useState)(() => getCurrentRoutePath());
2055
- (0, import_react8.useEffect)(() => {
2240
+ const [currentPath, setCurrentPath] = (0, import_react10.useState)(() => getCurrentRoutePath());
2241
+ (0, import_react10.useEffect)(() => {
2056
2242
  return subscribeToRouteChanges((path) => {
2057
2243
  setCurrentPath(path);
2058
2244
  });
@@ -2067,13 +2253,13 @@ var useRouteMismatch = (step) => {
2067
2253
  };
2068
2254
 
2069
2255
  // src/hooks/useViewportRect.ts
2070
- var import_react9 = require("react");
2256
+ var import_react11 = require("react");
2071
2257
  var useViewportRect = () => {
2072
- const [viewport, setViewport] = (0, import_react9.useState)(
2258
+ const [viewport, setViewport] = (0, import_react11.useState)(
2073
2259
  () => getViewportRect()
2074
2260
  );
2075
- const rafRef = (0, import_react9.useRef)(null);
2076
- (0, import_react9.useEffect)(() => {
2261
+ const rafRef = (0, import_react11.useRef)(null);
2262
+ (0, import_react11.useEffect)(() => {
2077
2263
  if (!isBrowser) return;
2078
2264
  const updateViewport = () => {
2079
2265
  rafRef.current = null;
@@ -2115,12 +2301,12 @@ var normalizeFlowFilter = (value) => {
2115
2301
  };
2116
2302
  var useHudState = (options = {}) => {
2117
2303
  const { flowId } = options;
2118
- const flowFilter = (0, import_react10.useMemo)(() => normalizeFlowFilter(flowId), [flowId]);
2304
+ const flowFilter = (0, import_react12.useMemo)(() => normalizeFlowFilter(flowId), [flowId]);
2119
2305
  const { state, activeStep, activeFlowId, flows, next, complete, pause, resume } = useTour();
2120
2306
  const target = useTourTarget();
2121
2307
  const viewportRect = useViewportRect();
2122
2308
  useAdvanceRules(target);
2123
- const matchesFlowFilter = (0, import_react10.useMemo)(() => {
2309
+ const matchesFlowFilter = (0, import_react12.useMemo)(() => {
2124
2310
  if (!flowFilter || flowFilter.length === 0) return true;
2125
2311
  if (!activeFlowId) return false;
2126
2312
  return flowFilter.includes(activeFlowId);
@@ -2128,15 +2314,15 @@ var useHudState = (options = {}) => {
2128
2314
  const isRunning = state?.status === "running";
2129
2315
  const runningState = isRunning && matchesFlowFilter ? state : null;
2130
2316
  const runningStep = runningState && activeStep ? activeStep : null;
2131
- const [shouldRender, setShouldRender] = (0, import_react10.useState)(
2317
+ const [shouldRender, setShouldRender] = (0, import_react12.useState)(
2132
2318
  Boolean(runningStep)
2133
2319
  );
2134
- (0, import_react10.useEffect)(() => {
2320
+ (0, import_react12.useEffect)(() => {
2135
2321
  if (runningStep) {
2136
2322
  setShouldRender(true);
2137
2323
  }
2138
2324
  }, [runningStep?.id]);
2139
- (0, import_react10.useEffect)(() => {
2325
+ (0, import_react12.useEffect)(() => {
2140
2326
  if (!shouldRender) return;
2141
2327
  if (runningStep) return;
2142
2328
  if (target.status !== "idle") return;
@@ -2148,19 +2334,19 @@ var useHudState = (options = {}) => {
2148
2334
  };
2149
2335
  }, [runningStep, shouldRender, target.status]);
2150
2336
  const { isRouteMismatch, currentPath } = useRouteMismatch(activeStep);
2151
- const pausedForMissingTargetRef = (0, import_react10.useRef)(null);
2152
- (0, import_react10.useEffect)(() => {
2337
+ const pausedForMissingTargetRef = (0, import_react12.useRef)(null);
2338
+ (0, import_react12.useEffect)(() => {
2153
2339
  if (!isRouteMismatch) return;
2154
2340
  if (!runningState || runningState.status !== "running") return;
2155
2341
  pause();
2156
2342
  }, [isRouteMismatch, runningState, pause]);
2157
- (0, import_react10.useEffect)(() => {
2343
+ (0, import_react12.useEffect)(() => {
2158
2344
  if (isRouteMismatch) return;
2159
2345
  if (pausedForMissingTargetRef.current !== null) return;
2160
2346
  if (!state || state.status !== "paused") return;
2161
2347
  resume();
2162
2348
  }, [isRouteMismatch, state, resume]);
2163
- const skipHiddenStep = (0, import_react10.useCallback)(() => {
2349
+ const skipHiddenStep = (0, import_react12.useCallback)(() => {
2164
2350
  if (!runningState || runningState.status !== "running") return;
2165
2351
  if (!activeFlowId) return;
2166
2352
  const flow = flows.get(activeFlowId);
@@ -2178,7 +2364,7 @@ var useHudState = (options = {}) => {
2178
2364
  viewportRect,
2179
2365
  onSkip: skipHiddenStep
2180
2366
  });
2181
- (0, import_react10.useEffect)(() => {
2367
+ (0, import_react12.useEffect)(() => {
2182
2368
  if (isRouteMismatch) return;
2183
2369
  if (activeStep?.route !== void 0) return;
2184
2370
  if (isInGracePeriod) return;
@@ -2197,14 +2383,14 @@ var useHudState = (options = {}) => {
2197
2383
  currentPath,
2198
2384
  pause
2199
2385
  ]);
2200
- (0, import_react10.useEffect)(() => {
2386
+ (0, import_react12.useEffect)(() => {
2201
2387
  if (pausedForMissingTargetRef.current === null) return;
2202
2388
  if (!state || state.status !== "paused") return;
2203
2389
  if (currentPath === pausedForMissingTargetRef.current) return;
2204
2390
  pausedForMissingTargetRef.current = null;
2205
2391
  resume();
2206
2392
  }, [currentPath, state, resume]);
2207
- (0, import_react10.useEffect)(() => {
2393
+ (0, import_react12.useEffect)(() => {
2208
2394
  pausedForMissingTargetRef.current = null;
2209
2395
  }, [activeStep?.id]);
2210
2396
  const canRenderStep = Boolean(runningStep && runningState);
@@ -2229,24 +2415,24 @@ var useHudState = (options = {}) => {
2229
2415
  };
2230
2416
 
2231
2417
  // src/hooks/useHudDescription.ts
2232
- var import_react11 = require("react");
2418
+ var import_react13 = require("react");
2233
2419
  var sanitizeForId = (value) => {
2234
2420
  const normalized = value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
2235
2421
  return normalized.length > 0 ? normalized : "step";
2236
2422
  };
2237
2423
  var useHudDescription = (options) => {
2238
2424
  const { step, fallbackAriaDescribedBy } = options;
2239
- const targetDescription = (0, import_react11.useMemo)(() => {
2425
+ const targetDescription = (0, import_react13.useMemo)(() => {
2240
2426
  if (!step) return null;
2241
2427
  if (typeof step.target !== "object") return null;
2242
2428
  const description = step.target.description;
2243
2429
  return typeof description === "string" ? description : null;
2244
2430
  }, [step]);
2245
- const descriptionId = (0, import_react11.useMemo)(() => {
2431
+ const descriptionId = (0, import_react13.useMemo)(() => {
2246
2432
  if (!step || !targetDescription) return void 0;
2247
2433
  return `tour-step-${sanitizeForId(step.id)}-description`;
2248
2434
  }, [step, targetDescription]);
2249
- const combinedAriaDescribedBy = (0, import_react11.useMemo)(() => {
2435
+ const combinedAriaDescribedBy = (0, import_react13.useMemo)(() => {
2250
2436
  const parts = [fallbackAriaDescribedBy, descriptionId].filter(Boolean);
2251
2437
  return parts.length > 0 ? parts.join(" ") : void 0;
2252
2438
  }, [descriptionId, fallbackAriaDescribedBy]);
@@ -2258,10 +2444,10 @@ var useHudDescription = (options) => {
2258
2444
  };
2259
2445
 
2260
2446
  // src/hooks/useHudShortcuts.ts
2261
- var import_react13 = require("react");
2447
+ var import_react15 = require("react");
2262
2448
 
2263
2449
  // src/hooks/useTourControls.ts
2264
- var import_react12 = require("react");
2450
+ var import_react14 = require("react");
2265
2451
  var hasManualAdvance = (rules) => rules.some((rule) => rule.type === "manual");
2266
2452
  var didPreviousAdvanceViaRoute = (rules) => rules.some((rule) => rule.type === "route");
2267
2453
  var useTourControls = () => {
@@ -2276,7 +2462,7 @@ var useTourControls = () => {
2276
2462
  flows,
2277
2463
  activeStep
2278
2464
  } = tour;
2279
- const computed = (0, import_react12.useMemo)(() => {
2465
+ const computed = (0, import_react14.useMemo)(() => {
2280
2466
  if (!state || state.status !== "running" || !activeStep) {
2281
2467
  return {
2282
2468
  isActive: false,
@@ -2325,11 +2511,11 @@ var useTourControls = () => {
2325
2511
  } = computed;
2326
2512
  const canGoBack = showBackButton && !backDisabled;
2327
2513
  const canGoNext = showNextButton && !nextDisabled;
2328
- const goBack = (0, import_react12.useCallback)(() => {
2514
+ const goBack = (0, import_react14.useCallback)(() => {
2329
2515
  if (!canGoBack) return;
2330
2516
  back();
2331
2517
  }, [back, canGoBack]);
2332
- const goNext = (0, import_react12.useCallback)(() => {
2518
+ const goNext = (0, import_react14.useCallback)(() => {
2333
2519
  if (!canGoNext) return;
2334
2520
  if (isLast) {
2335
2521
  complete();
@@ -2337,7 +2523,7 @@ var useTourControls = () => {
2337
2523
  next();
2338
2524
  }
2339
2525
  }, [canGoNext, complete, isLast, next]);
2340
- return (0, import_react12.useMemo)(
2526
+ return (0, import_react14.useMemo)(
2341
2527
  () => ({
2342
2528
  showBackButton,
2343
2529
  backDisabled,
@@ -2382,7 +2568,7 @@ var useHudShortcuts = (target, options) => {
2382
2568
  const escapeEnabled = options?.escape ?? true;
2383
2569
  const { state } = useTour();
2384
2570
  const { cancel, canGoBack, goBack, canGoNext, goNext, isActive } = useTourControls();
2385
- (0, import_react13.useEffect)(() => {
2571
+ (0, import_react15.useEffect)(() => {
2386
2572
  if (!isBrowser) return void 0;
2387
2573
  if (!enabled) return void 0;
2388
2574
  if (!target) return void 0;
@@ -2446,10 +2632,10 @@ var useHudShortcuts = (target, options) => {
2446
2632
  };
2447
2633
 
2448
2634
  // src/hooks/useTourHud.ts
2449
- var import_react16 = require("react");
2635
+ var import_react18 = require("react");
2450
2636
 
2451
2637
  // src/hooks/useBodyScrollLock.ts
2452
- var import_react14 = require("react");
2638
+ var import_react16 = require("react");
2453
2639
  var lockCount = 0;
2454
2640
  var previousOverflow = null;
2455
2641
  var acquireLock = () => {
@@ -2470,7 +2656,7 @@ var releaseLock = () => {
2470
2656
  }
2471
2657
  };
2472
2658
  var useBodyScrollLock = (enabled) => {
2473
- (0, import_react14.useEffect)(() => {
2659
+ (0, import_react16.useEffect)(() => {
2474
2660
  if (!enabled) return;
2475
2661
  acquireLock();
2476
2662
  return () => {
@@ -2480,7 +2666,7 @@ var useBodyScrollLock = (enabled) => {
2480
2666
  };
2481
2667
 
2482
2668
  // src/hooks/useHudTargetIssue.ts
2483
- var import_react15 = require("react");
2669
+ var import_react17 = require("react");
2484
2670
  var deriveTargetIssue = (params) => {
2485
2671
  const { target, labels } = params;
2486
2672
  if (target.isScreen) return null;
@@ -2513,12 +2699,12 @@ var deriveTargetIssue = (params) => {
2513
2699
  var useHudTargetIssue = (target, options) => {
2514
2700
  const labels = useTourLabels();
2515
2701
  const delayMs = Math.max(0, options?.delayMs ?? 500);
2516
- const [armed, setArmed] = (0, import_react15.useState)(false);
2517
- const rawIssue = (0, import_react15.useMemo)(
2702
+ const [armed, setArmed] = (0, import_react17.useState)(false);
2703
+ const rawIssue = (0, import_react17.useMemo)(
2518
2704
  () => deriveTargetIssue({ target, labels }),
2519
2705
  [target.isScreen, target.rectSource, target.status, target.visibility, labels]
2520
2706
  );
2521
- (0, import_react15.useEffect)(() => {
2707
+ (0, import_react17.useEffect)(() => {
2522
2708
  if (!rawIssue) {
2523
2709
  setArmed(false);
2524
2710
  return;
@@ -2552,7 +2738,7 @@ var useTourHud = (options = {}) => {
2552
2738
  const { backdropInteraction, lockBodyScroll } = useTour();
2553
2739
  const hudState = useHudState();
2554
2740
  const disableDefaultHud = hudState.hudRenderMode === "none";
2555
- const [popoverNode, setPopoverNode] = (0, import_react16.useState)(null);
2741
+ const [popoverNode, setPopoverNode] = (0, import_react18.useState)(null);
2556
2742
  const popoverOptions = hudState.flowHudOptions?.popover;
2557
2743
  const description = useHudDescription({
2558
2744
  step: hudState.runningStep,
@@ -2576,7 +2762,7 @@ var useTourHud = (options = {}) => {
2576
2762
  radius: overlayRadius,
2577
2763
  interactionMode: hudState.flowHudOptions?.backdrop?.interaction ?? backdropInteraction
2578
2764
  };
2579
- const popover = (0, import_react16.useMemo)(() => {
2765
+ const popover = (0, import_react18.useMemo)(() => {
2580
2766
  return {
2581
2767
  offset: popoverOptions?.offset ?? 32,
2582
2768
  role: popoverOptions?.role ?? "dialog",
@@ -2588,13 +2774,13 @@ var useTourHud = (options = {}) => {
2588
2774
  placement: hudState.runningStep?.placement
2589
2775
  };
2590
2776
  }, [hudState.runningStep?.placement, popoverOptions]);
2591
- const descriptionResult = (0, import_react16.useMemo)(() => {
2777
+ const descriptionResult = (0, import_react18.useMemo)(() => {
2592
2778
  return {
2593
2779
  ...description,
2594
2780
  text: description.targetDescription
2595
2781
  };
2596
2782
  }, [description]);
2597
- const focusManager = (0, import_react16.useMemo)(
2783
+ const focusManager = (0, import_react18.useMemo)(
2598
2784
  () => ({
2599
2785
  active: hudState.focusTrapActive,
2600
2786
  target: hudState.hudTarget,
@@ -2624,7 +2810,7 @@ var useTourHud = (options = {}) => {
2624
2810
  };
2625
2811
 
2626
2812
  // src/hooks/useTourOverlay.ts
2627
- var import_react17 = require("react");
2813
+ var import_react19 = require("react");
2628
2814
  var DEFAULT_PADDING = 12;
2629
2815
  var DEFAULT_RADIUS = 12;
2630
2816
  var DEFAULT_EDGE_BUFFER = 0;
@@ -2637,9 +2823,9 @@ var useTourOverlay = (options) => {
2637
2823
  interactionMode = "passthrough",
2638
2824
  isInGracePeriod = false
2639
2825
  } = options;
2640
- const hasShownRef = (0, import_react17.useRef)(false);
2641
- const lastReadyTargetRef = (0, import_react17.useRef)(null);
2642
- (0, import_react17.useEffect)(() => {
2826
+ const hasShownRef = (0, import_react19.useRef)(false);
2827
+ const lastReadyTargetRef = (0, import_react19.useRef)(null);
2828
+ (0, import_react19.useEffect)(() => {
2643
2829
  if (!isBrowser) return;
2644
2830
  if (target.status === "ready") {
2645
2831
  hasShownRef.current = true;
@@ -2689,15 +2875,15 @@ var useTourOverlay = (options) => {
2689
2875
  height: highlightHeight,
2690
2876
  radius: highlightRadius
2691
2877
  } : null;
2692
- const maskCapable = (0, import_react17.useMemo)(() => supportsMasking(), []);
2878
+ const maskCapable = (0, import_react19.useMemo)(() => supportsMasking(), []);
2693
2879
  const isActive = target.status === "ready" || target.status === "resolving" && cachedTarget !== null || isInGracePeriod;
2694
2880
  const shouldMask = maskCapable && isActive;
2695
- const maskId = (0, import_react17.useMemo)(
2881
+ const maskId = (0, import_react19.useMemo)(
2696
2882
  () => `tour-overlay-mask-${Math.random().toString(36).slice(2, 10)}`,
2697
2883
  []
2698
2884
  );
2699
2885
  const maskUrl = shouldMask ? `url(#${maskId})` : void 0;
2700
- const fallbackSegments = (0, import_react17.useMemo)(() => {
2886
+ const fallbackSegments = (0, import_react19.useMemo)(() => {
2701
2887
  if (!isActive || shouldMask || !hasHighlightBounds || !highlightRect) {
2702
2888
  return null;
2703
2889
  }
@@ -2750,7 +2936,7 @@ var useTourOverlay = (options) => {
2750
2936
  viewport.height,
2751
2937
  viewport.width
2752
2938
  ]);
2753
- const blockerSegments = (0, import_react17.useMemo)(() => {
2939
+ const blockerSegments = (0, import_react19.useMemo)(() => {
2754
2940
  if (interactionMode !== "block") {
2755
2941
  return null;
2756
2942
  }
@@ -2878,37 +3064,202 @@ var useRadixDialogAdapter = (options = {}) => {
2878
3064
  var waitForDom = () => new Promise(
2879
3065
  (resolve) => requestAnimationFrame(() => setTimeout(resolve, 0))
2880
3066
  );
2881
- var createRadixDialogHelpers = (params) => {
2882
- const { contentSelector, triggerSelector } = params;
2883
- const isOpen = () => {
2884
- if (typeof document === "undefined") return false;
2885
- return document.querySelector(contentSelector) !== null;
2886
- };
2887
- const open = async () => {
2888
- if (typeof document === "undefined") return;
2889
- if (isOpen()) return;
2890
- await waitForDom();
2891
- if (isOpen()) return;
2892
- const trigger = document.querySelector(triggerSelector);
2893
- trigger?.click();
2894
- await waitForDom();
3067
+
3068
+ // src/hooks/useRadixTourDialog.ts
3069
+ var import_react20 = require("react");
3070
+ var resolveAutoOpen2 = (config) => {
3071
+ if (!config) return { onEnter: true, onResume: true };
3072
+ const { autoOpen } = config;
3073
+ if (autoOpen === false) return { onEnter: false, onResume: false };
3074
+ if (autoOpen === true || autoOpen === void 0) {
3075
+ return { onEnter: true, onResume: true };
3076
+ }
3077
+ return {
3078
+ onEnter: autoOpen.onEnter ?? true,
3079
+ onResume: autoOpen.onResume ?? true
2895
3080
  };
2896
- const close = async () => {
2897
- if (typeof document === "undefined") return;
2898
- if (!isOpen()) return;
2899
- document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape" }));
2900
- await waitForDom();
3081
+ };
3082
+ var useRadixTourDialog = (params) => {
3083
+ const { dialogId } = params;
3084
+ const { activeFlowId, state, flows, goToStep, events } = useTour();
3085
+ const registry = useDialogRegistryOptional();
3086
+ const { suspendExternalFocusTrap } = useTourFocusDominance();
3087
+ const [internalOpen, setInternalOpen] = (0, import_react20.useState)(false);
3088
+ const lastStepIndexRef = (0, import_react20.useRef)(-1);
3089
+ const isResumeRef = (0, import_react20.useRef)(false);
3090
+ const flow = activeFlowId ? flows.get(activeFlowId) : void 0;
3091
+ const dialogConfig = flow?.dialogs?.[dialogId];
3092
+ const currentStep = flow && state && state.stepIndex >= 0 ? flow.steps[state.stepIndex] : void 0;
3093
+ const isStepActive = currentStep?.dialogId === dialogId;
3094
+ const autoOpenConfig = resolveAutoOpen2(dialogConfig);
3095
+ const autoClose = dialogConfig?.autoClose ?? "differentDialog";
3096
+ const shouldBeOpen = (0, import_react20.useMemo)(() => {
3097
+ if (!isStepActive) return false;
3098
+ return true;
3099
+ }, [isStepActive]);
3100
+ (0, import_react20.useEffect)(() => {
3101
+ if (!events) return;
3102
+ const unsubscribe = events.on("flowResume", () => {
3103
+ isResumeRef.current = true;
3104
+ });
3105
+ return unsubscribe;
3106
+ }, [events]);
3107
+ (0, import_react20.useEffect)(() => {
3108
+ if (!state || state.status !== "running") return;
3109
+ if (!flow) return;
3110
+ const currentStepIndex = state.stepIndex;
3111
+ const previousStepIndex = lastStepIndexRef.current;
3112
+ const wasResume = isResumeRef.current;
3113
+ isResumeRef.current = false;
3114
+ if (previousStepIndex === -1 && currentStepIndex >= 0) {
3115
+ lastStepIndexRef.current = currentStepIndex;
3116
+ if (isStepActive) {
3117
+ const shouldAutoOpen = wasResume ? autoOpenConfig.onResume : autoOpenConfig.onEnter;
3118
+ if (shouldAutoOpen) {
3119
+ setInternalOpen(true);
3120
+ }
3121
+ }
3122
+ return;
3123
+ }
3124
+ if (previousStepIndex === currentStepIndex) return;
3125
+ lastStepIndexRef.current = currentStepIndex;
3126
+ const previousStep = previousStepIndex >= 0 ? flow.steps[previousStepIndex] : void 0;
3127
+ const wasActive = previousStep?.dialogId === dialogId;
3128
+ if (isStepActive && !wasActive) {
3129
+ const shouldAutoOpen = wasResume ? autoOpenConfig.onResume : autoOpenConfig.onEnter;
3130
+ if (shouldAutoOpen) {
3131
+ setInternalOpen(true);
3132
+ }
3133
+ }
3134
+ if (wasActive && !isStepActive) {
3135
+ if (autoClose === "always" || autoClose === "differentDialog") {
3136
+ setInternalOpen(false);
3137
+ }
3138
+ }
3139
+ }, [
3140
+ state,
3141
+ flow,
3142
+ dialogId,
3143
+ isStepActive,
3144
+ autoOpenConfig.onEnter,
3145
+ autoOpenConfig.onResume,
3146
+ autoClose
3147
+ ]);
3148
+ (0, import_react20.useEffect)(() => {
3149
+ if (!events) return;
3150
+ const unsubscribeEnter = events.on("stepEnter", (payload) => {
3151
+ const step = payload.currentStep;
3152
+ if (step.dialogId !== dialogId) return;
3153
+ const isResume = payload.reason === "resume";
3154
+ const shouldAutoOpen = isResume ? autoOpenConfig.onResume : autoOpenConfig.onEnter;
3155
+ if (shouldAutoOpen) {
3156
+ requestAnimationFrame(() => {
3157
+ setInternalOpen(true);
3158
+ });
3159
+ }
3160
+ });
3161
+ const unsubscribeExit = events.on("stepExit", (payload) => {
3162
+ const step = payload.previousStep;
3163
+ if (step.dialogId !== dialogId) return;
3164
+ const nextStep = payload.currentStep;
3165
+ if (nextStep?.dialogId === dialogId) {
3166
+ return;
3167
+ }
3168
+ if (autoClose === "always" || autoClose === "differentDialog") {
3169
+ requestAnimationFrame(() => {
3170
+ setInternalOpen(false);
3171
+ });
3172
+ }
3173
+ });
3174
+ return () => {
3175
+ unsubscribeEnter();
3176
+ unsubscribeExit();
3177
+ };
3178
+ }, [events, dialogId, autoOpenConfig, autoClose]);
3179
+ const handleDismiss = (0, import_react20.useCallback)(() => {
3180
+ if (!dialogConfig) return;
3181
+ setInternalOpen(false);
3182
+ goToStep(dialogConfig.onDismissGoToStepId);
3183
+ }, [dialogConfig, goToStep]);
3184
+ const onOpenChange = (0, import_react20.useCallback)(
3185
+ (open) => {
3186
+ if (open) {
3187
+ setInternalOpen(true);
3188
+ } else {
3189
+ if (isStepActive && dialogConfig) {
3190
+ handleDismiss();
3191
+ } else {
3192
+ setInternalOpen(false);
3193
+ }
3194
+ }
3195
+ },
3196
+ [isStepActive, dialogConfig, handleDismiss]
3197
+ );
3198
+ (0, import_react20.useEffect)(() => {
3199
+ if (!registry) return;
3200
+ const controller = {
3201
+ open: () => setInternalOpen(true),
3202
+ close: () => setInternalOpen(false),
3203
+ isOpen: () => internalOpen
3204
+ };
3205
+ registry.register(dialogId, controller);
3206
+ return () => registry.unregister(dialogId);
3207
+ }, [registry, dialogId, internalOpen]);
3208
+ const preventDismiss = (0, import_react20.useCallback)(
3209
+ (event) => {
3210
+ if (suspendExternalFocusTrap) {
3211
+ event.preventDefault();
3212
+ }
3213
+ },
3214
+ [suspendExternalFocusTrap]
3215
+ );
3216
+ const handleEscapeKeyDown = (0, import_react20.useCallback)(
3217
+ (event) => {
3218
+ if (isStepActive && dialogConfig) {
3219
+ event.preventDefault();
3220
+ handleDismiss();
3221
+ }
3222
+ },
3223
+ [isStepActive, dialogConfig, handleDismiss]
3224
+ );
3225
+ const handleInteractOutside = (0, import_react20.useCallback)(
3226
+ (event) => {
3227
+ if (suspendExternalFocusTrap) {
3228
+ event.preventDefault();
3229
+ return;
3230
+ }
3231
+ if (isStepActive && dialogConfig) {
3232
+ event.preventDefault();
3233
+ handleDismiss();
3234
+ }
3235
+ },
3236
+ [suspendExternalFocusTrap, isStepActive, dialogConfig, handleDismiss]
3237
+ );
3238
+ return {
3239
+ isStepActive,
3240
+ shouldBeOpen,
3241
+ onOpenChange,
3242
+ dialogProps: {
3243
+ open: internalOpen,
3244
+ onOpenChange,
3245
+ modal: !suspendExternalFocusTrap
3246
+ },
3247
+ contentProps: {
3248
+ trapFocus: !suspendExternalFocusTrap,
3249
+ onInteractOutside: handleInteractOutside,
3250
+ onFocusOutside: preventDismiss,
3251
+ onEscapeKeyDown: handleEscapeKeyDown
3252
+ }
2901
3253
  };
2902
- return { isOpen, open, close };
2903
3254
  };
2904
3255
 
2905
3256
  // src/hooks/useDelayAdvance.ts
2906
- var import_react18 = require("react");
3257
+ var import_react21 = require("react");
2907
3258
  var getTimestamp = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
2908
3259
  var useDelayAdvance = () => {
2909
3260
  const { delayInfo, activeStep, state } = useTour();
2910
- const [now, setNow] = (0, import_react18.useState)(() => getTimestamp());
2911
- (0, import_react18.useEffect)(() => {
3261
+ const [now, setNow] = (0, import_react21.useState)(() => getTimestamp());
3262
+ (0, import_react21.useEffect)(() => {
2912
3263
  if (!delayInfo) return;
2913
3264
  if (!activeStep || activeStep.id !== delayInfo.stepId) return;
2914
3265
  if (!state || state.status !== "running") return;
@@ -2925,12 +3276,12 @@ var useDelayAdvance = () => {
2925
3276
  }
2926
3277
  };
2927
3278
  }, [delayInfo, activeStep, state]);
2928
- (0, import_react18.useEffect)(() => {
3279
+ (0, import_react21.useEffect)(() => {
2929
3280
  if (!delayInfo) {
2930
3281
  setNow(getTimestamp());
2931
3282
  }
2932
3283
  }, [delayInfo]);
2933
- return (0, import_react18.useMemo)(() => {
3284
+ return (0, import_react21.useMemo)(() => {
2934
3285
  const matchingStep = !!delayInfo && !!activeStep && activeStep.id === delayInfo.stepId;
2935
3286
  const isRunning = matchingStep && state?.status === "running";
2936
3287
  if (!delayInfo) {
@@ -2983,10 +3334,10 @@ var useDelayAdvance = () => {
2983
3334
  };
2984
3335
 
2985
3336
  // src/components/OverlayBackdrop.tsx
2986
- var import_react19 = require("react");
3337
+ var import_react22 = require("react");
2987
3338
  var import_react_dom = require("react-dom");
2988
- var import_react20 = require("motion/react");
2989
- var import_jsx_runtime3 = require("react/jsx-runtime");
3339
+ var import_react23 = require("motion/react");
3340
+ var import_jsx_runtime4 = require("react/jsx-runtime");
2990
3341
  var styles = {
2991
3342
  root: {
2992
3343
  position: "fixed",
@@ -3072,9 +3423,9 @@ var OverlayBackdrop = ({
3072
3423
  viewport
3073
3424
  } = overlay;
3074
3425
  const hasHighlightBounds = Boolean(highlight.rect);
3075
- const prevScreenTargetRef = (0, import_react19.useRef)(null);
3426
+ const prevScreenTargetRef = (0, import_react22.useRef)(null);
3076
3427
  const shouldSnapHighlight = prevScreenTargetRef.current === true && !highlight.isScreen && hasHighlightBounds;
3077
- (0, import_react19.useEffect)(() => {
3428
+ (0, import_react22.useEffect)(() => {
3078
3429
  prevScreenTargetRef.current = highlight.isScreen;
3079
3430
  }, [highlight.isScreen]);
3080
3431
  const resolvedBlur = typeof blurAmount === "number" ? `${blurAmount}px` : "0px";
@@ -3134,7 +3485,7 @@ var OverlayBackdrop = ({
3134
3485
  overlayStyle.backgroundColor = color;
3135
3486
  }
3136
3487
  return (0, import_react_dom.createPortal)(
3137
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3488
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3138
3489
  MotionDiv,
3139
3490
  {
3140
3491
  className: rootClassName,
@@ -3142,7 +3493,7 @@ var OverlayBackdrop = ({
3142
3493
  "aria-hidden": ariaHidden,
3143
3494
  "data-tour-overlay": "",
3144
3495
  children: [
3145
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react20.AnimatePresence, { mode: "popLayout", children: shouldMask ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3496
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react23.AnimatePresence, { mode: "popLayout", children: shouldMask ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3146
3497
  MotionSvg,
3147
3498
  {
3148
3499
  width: "0",
@@ -3154,7 +3505,7 @@ var OverlayBackdrop = ({
3154
3505
  animate: { opacity: 1 },
3155
3506
  exit: { opacity: 0 },
3156
3507
  transition: overlayTransition,
3157
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MotionDefs, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3508
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MotionDefs, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3158
3509
  MotionMask,
3159
3510
  {
3160
3511
  id: maskId ?? void 0,
@@ -3166,7 +3517,7 @@ var OverlayBackdrop = ({
3166
3517
  animate: { width: viewport.width, height: viewport.height },
3167
3518
  transition: highlightTransition,
3168
3519
  children: [
3169
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3520
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3170
3521
  MotionRect,
3171
3522
  {
3172
3523
  x: "0",
@@ -3182,7 +3533,7 @@ var OverlayBackdrop = ({
3182
3533
  exit: { opacity: 0 }
3183
3534
  }
3184
3535
  ),
3185
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3536
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3186
3537
  MotionRect,
3187
3538
  {
3188
3539
  initial: false,
@@ -3201,7 +3552,7 @@ var OverlayBackdrop = ({
3201
3552
  },
3202
3553
  "tour-mask"
3203
3554
  ) : null }),
3204
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react20.AnimatePresence, { mode: "popLayout", children: showBaseOverlay ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3555
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react23.AnimatePresence, { mode: "popLayout", children: showBaseOverlay ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3205
3556
  MotionDiv,
3206
3557
  {
3207
3558
  className: overlayClassName,
@@ -3229,7 +3580,7 @@ var OverlayBackdrop = ({
3229
3580
  },
3230
3581
  "tour-overlay"
3231
3582
  ) : null }),
3232
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react20.AnimatePresence, { mode: "popLayout", children: fallbackSegments ? fallbackSegments.map((segment) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3583
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react23.AnimatePresence, { mode: "popLayout", children: fallbackSegments ? fallbackSegments.map((segment) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3233
3584
  MotionDiv,
3234
3585
  {
3235
3586
  className: segmentClassName,
@@ -3259,13 +3610,13 @@ var OverlayBackdrop = ({
3259
3610
  },
3260
3611
  `tour-overlay-fallback-${segment.key}`
3261
3612
  )) : null }),
3262
- showInteractionBlocker && blockerSegments ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3613
+ showInteractionBlocker && blockerSegments ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3263
3614
  "div",
3264
3615
  {
3265
3616
  style: { ...styles.blockerContainer, zIndex },
3266
3617
  "data-tour-overlay-layer": "interaction-blocker",
3267
3618
  "aria-hidden": true,
3268
- children: blockerSegments.map((segment) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3619
+ children: blockerSegments.map((segment) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3269
3620
  "div",
3270
3621
  {
3271
3622
  style: {
@@ -3280,7 +3631,7 @@ var OverlayBackdrop = ({
3280
3631
  ))
3281
3632
  }
3282
3633
  ) : null,
3283
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react20.AnimatePresence, { mode: "popLayout", children: showHighlightRing && isActive && hasHighlightBounds ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3634
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react23.AnimatePresence, { mode: "popLayout", children: showHighlightRing && isActive && hasHighlightBounds ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3284
3635
  MotionDiv,
3285
3636
  {
3286
3637
  className: ringClassName,
@@ -3311,7 +3662,7 @@ var OverlayBackdrop = ({
3311
3662
  };
3312
3663
 
3313
3664
  // src/components/TourPopoverPortal.tsx
3314
- var import_react21 = require("react");
3665
+ var import_react24 = require("react");
3315
3666
  var import_react_dom2 = require("react-dom");
3316
3667
  var import_dom13 = require("@floating-ui/dom");
3317
3668
  var FLOATING_OFFSET = 8;
@@ -3372,12 +3723,12 @@ var TourPopoverPortal = ({
3372
3723
  const popoverContentTransition = transitionsOverride?.popoverContent ?? adapter.transitions.popoverContent ?? DEFAULT_POPOVER_CONTENT_TRANSITION;
3373
3724
  const viewport = useViewportRect();
3374
3725
  const prefersMobileLayout = viewport.width <= MOBILE_BREAKPOINT || viewport.height <= MOBILE_HEIGHT_BREAKPOINT;
3375
- const prefersMobileRef = (0, import_react21.useRef)(prefersMobileLayout);
3376
- (0, import_react21.useEffect)(() => {
3726
+ const prefersMobileRef = (0, import_react24.useRef)(prefersMobileLayout);
3727
+ (0, import_react24.useEffect)(() => {
3377
3728
  prefersMobileRef.current = prefersMobileLayout;
3378
3729
  }, [prefersMobileLayout]);
3379
- const lastReadyTargetRef = (0, import_react21.useRef)(null);
3380
- (0, import_react21.useEffect)(() => {
3730
+ const lastReadyTargetRef = (0, import_react24.useRef)(null);
3731
+ (0, import_react24.useEffect)(() => {
3381
3732
  if (target.status === "ready" && target.rect) {
3382
3733
  lastReadyTargetRef.current = {
3383
3734
  rect: { ...target.rect },
@@ -3393,7 +3744,7 @@ var TourPopoverPortal = ({
3393
3744
  const shouldHidePopover = !resolvedRect && !target.isScreen;
3394
3745
  const fallbackRect = resolvedRect ?? viewport;
3395
3746
  const fallbackIsScreen = resolvedIsScreen;
3396
- const [floatingSize, setFloatingSize] = (0, import_react21.useState)(null);
3747
+ const [floatingSize, setFloatingSize] = (0, import_react24.useState)(null);
3397
3748
  const clampVertical = (value) => Math.min(viewport.height - 24, Math.max(24, value));
3398
3749
  const clampHorizontal = (value) => Math.min(viewport.width - 24, Math.max(24, value));
3399
3750
  const screenCenteredTop = viewport.height / 2 - (floatingSize?.height ?? 0) / 2;
@@ -3404,7 +3755,7 @@ var TourPopoverPortal = ({
3404
3755
  const leftBase = fallbackIsScreen ? screenCenteredLeft : fallbackRect.left + fallbackRect.width / 2 - floatingWidth / 2;
3405
3756
  const left = clampHorizontal(leftBase);
3406
3757
  const fallbackTransform = "translate3d(0px, 0px, 0px)";
3407
- const fallbackPosition = (0, import_react21.useMemo)(
3758
+ const fallbackPosition = (0, import_react24.useMemo)(
3408
3759
  () => ({
3409
3760
  top,
3410
3761
  left,
@@ -3412,7 +3763,7 @@ var TourPopoverPortal = ({
3412
3763
  }),
3413
3764
  [fallbackTransform, left, top]
3414
3765
  );
3415
- const centerInitialPosition = (0, import_react21.useMemo)(
3766
+ const centerInitialPosition = (0, import_react24.useMemo)(
3416
3767
  () => ({
3417
3768
  top: viewport.height / 2,
3418
3769
  left: viewport.width / 2,
@@ -3420,23 +3771,23 @@ var TourPopoverPortal = ({
3420
3771
  }),
3421
3772
  [viewport.height, viewport.width]
3422
3773
  );
3423
- const floatingRef = (0, import_react21.useRef)(null);
3424
- const cachedFloatingPositionRef = (0, import_react21.useRef)(null);
3425
- const appliedFloatingCacheRef = (0, import_react21.useRef)(null);
3426
- const deferredScreenSnapRef = (0, import_react21.useRef)(null);
3427
- const [layoutMode, setLayoutMode] = (0, import_react21.useState)(
3774
+ const floatingRef = (0, import_react24.useRef)(null);
3775
+ const cachedFloatingPositionRef = (0, import_react24.useRef)(null);
3776
+ const appliedFloatingCacheRef = (0, import_react24.useRef)(null);
3777
+ const deferredScreenSnapRef = (0, import_react24.useRef)(null);
3778
+ const [layoutMode, setLayoutMode] = (0, import_react24.useState)(
3428
3779
  () => prefersMobileLayout ? "mobile" : "floating"
3429
3780
  );
3430
- const [floatingPosition, setFloatingPosition] = (0, import_react21.useState)(fallbackPosition);
3431
- const [dragPosition, setDragPosition] = (0, import_react21.useState)(null);
3432
- const [isDragging, setIsDragging] = (0, import_react21.useState)(false);
3433
- const dragStateRef = (0, import_react21.useRef)(null);
3434
- const overflowRetryRef = (0, import_react21.useRef)({
3781
+ const [floatingPosition, setFloatingPosition] = (0, import_react24.useState)(fallbackPosition);
3782
+ const [dragPosition, setDragPosition] = (0, import_react24.useState)(null);
3783
+ const [isDragging, setIsDragging] = (0, import_react24.useState)(false);
3784
+ const dragStateRef = (0, import_react24.useRef)(null);
3785
+ const overflowRetryRef = (0, import_react24.useRef)({
3435
3786
  stepId: null,
3436
3787
  attempts: 0
3437
3788
  });
3438
- const overflowRetryTimeoutRef = (0, import_react21.useRef)(null);
3439
- (0, import_react21.useLayoutEffect)(() => {
3789
+ const overflowRetryTimeoutRef = (0, import_react24.useRef)(null);
3790
+ (0, import_react24.useLayoutEffect)(() => {
3440
3791
  if (!isBrowser) return;
3441
3792
  const node = floatingRef.current;
3442
3793
  if (!node) return;
@@ -3455,25 +3806,25 @@ var TourPopoverPortal = ({
3455
3806
  const autoAlignment = resolvedPlacement.endsWith(
3456
3807
  "-start"
3457
3808
  ) ? "start" : resolvedPlacement.endsWith("-end") ? "end" : void 0;
3458
- (0, import_react21.useEffect)(() => {
3809
+ (0, import_react24.useEffect)(() => {
3459
3810
  setDragPosition(null);
3460
3811
  setLayoutMode(prefersMobileRef.current ? "mobile" : "floating");
3461
3812
  cachedFloatingPositionRef.current = null;
3462
3813
  appliedFloatingCacheRef.current = null;
3463
3814
  }, [target.stepId]);
3464
- (0, import_react21.useEffect)(() => {
3815
+ (0, import_react24.useEffect)(() => {
3465
3816
  if (layoutMode !== "manual") {
3466
3817
  setDragPosition(null);
3467
3818
  }
3468
3819
  }, [layoutMode]);
3469
- (0, import_react21.useEffect)(() => {
3820
+ (0, import_react24.useEffect)(() => {
3470
3821
  cachedFloatingPositionRef.current = floatingPosition;
3471
3822
  const cacheKey = getFloatingCacheKey(target);
3472
3823
  if (cacheKey) {
3473
3824
  floatingPositionCache.set(cacheKey, floatingPosition);
3474
3825
  }
3475
3826
  }, [floatingPosition, target.isScreen, target.stepId]);
3476
- const dockedPosition = (0, import_react21.useMemo)(
3827
+ const dockedPosition = (0, import_react24.useMemo)(
3477
3828
  () => ({
3478
3829
  top: viewport.height - DOCKED_MARGIN,
3479
3830
  left: viewport.width - DOCKED_MARGIN,
@@ -3481,7 +3832,7 @@ var TourPopoverPortal = ({
3481
3832
  }),
3482
3833
  [viewport.height, viewport.width]
3483
3834
  );
3484
- const mobilePosition = (0, import_react21.useMemo)(
3835
+ const mobilePosition = (0, import_react24.useMemo)(
3485
3836
  () => ({
3486
3837
  top: viewport.height - MOBILE_HORIZONTAL_GUTTER,
3487
3838
  left: viewport.width / 2,
@@ -3489,17 +3840,17 @@ var TourPopoverPortal = ({
3489
3840
  }),
3490
3841
  [viewport.height, viewport.width]
3491
3842
  );
3492
- (0, import_react21.useEffect)(() => {
3843
+ (0, import_react24.useEffect)(() => {
3493
3844
  if (layoutMode === "docked") {
3494
3845
  setFloatingPosition(dockedPosition);
3495
3846
  }
3496
3847
  }, [dockedPosition, layoutMode]);
3497
- (0, import_react21.useEffect)(() => {
3848
+ (0, import_react24.useEffect)(() => {
3498
3849
  if (layoutMode === "mobile") {
3499
3850
  setFloatingPosition(mobilePosition);
3500
3851
  }
3501
3852
  }, [layoutMode, mobilePosition]);
3502
- (0, import_react21.useEffect)(() => {
3853
+ (0, import_react24.useEffect)(() => {
3503
3854
  if (prefersMobileLayout) {
3504
3855
  if (layoutMode !== "mobile") {
3505
3856
  setLayoutMode("mobile");
@@ -3512,7 +3863,7 @@ var TourPopoverPortal = ({
3512
3863
  setFloatingPosition(fallbackPosition);
3513
3864
  }
3514
3865
  }, [fallbackPosition, layoutMode, prefersMobileLayout]);
3515
- (0, import_react21.useEffect)(() => {
3866
+ (0, import_react24.useEffect)(() => {
3516
3867
  if (layoutMode !== "floating") return;
3517
3868
  const stepId = target.stepId;
3518
3869
  if (!stepId) return;
@@ -3536,7 +3887,7 @@ var TourPopoverPortal = ({
3536
3887
  target.stepId
3537
3888
  ]);
3538
3889
  const shouldDeferScreenSnap = layoutMode === "floating" && target.isScreen && Boolean(layoutId);
3539
- (0, import_react21.useEffect)(() => {
3890
+ (0, import_react24.useEffect)(() => {
3540
3891
  return () => {
3541
3892
  if (deferredScreenSnapRef.current !== null) {
3542
3893
  cancelAnimationFrame(deferredScreenSnapRef.current);
@@ -3544,7 +3895,7 @@ var TourPopoverPortal = ({
3544
3895
  }
3545
3896
  };
3546
3897
  }, []);
3547
- (0, import_react21.useLayoutEffect)(() => {
3898
+ (0, import_react24.useLayoutEffect)(() => {
3548
3899
  if (layoutMode !== "floating") return;
3549
3900
  if (target.status === "ready" && !target.isScreen) return;
3550
3901
  if (shouldDeferScreenSnap) return;
@@ -3556,7 +3907,7 @@ var TourPopoverPortal = ({
3556
3907
  target.isScreen,
3557
3908
  target.status
3558
3909
  ]);
3559
- (0, import_react21.useEffect)(() => {
3910
+ (0, import_react24.useEffect)(() => {
3560
3911
  if (!shouldDeferScreenSnap) return;
3561
3912
  if (deferredScreenSnapRef.current !== null) {
3562
3913
  cancelAnimationFrame(deferredScreenSnapRef.current);
@@ -3583,14 +3934,14 @@ var TourPopoverPortal = ({
3583
3934
  }
3584
3935
  };
3585
3936
  }, [fallbackPosition, shouldDeferScreenSnap]);
3586
- (0, import_react21.useEffect)(() => {
3937
+ (0, import_react24.useEffect)(() => {
3587
3938
  return () => {
3588
3939
  if (overflowRetryTimeoutRef.current !== null) {
3589
3940
  window.clearTimeout(overflowRetryTimeoutRef.current);
3590
3941
  }
3591
3942
  };
3592
3943
  }, []);
3593
- (0, import_react21.useLayoutEffect)(() => {
3944
+ (0, import_react24.useLayoutEffect)(() => {
3594
3945
  if (!isBrowser) return;
3595
3946
  const floatingEl = floatingRef.current;
3596
3947
  const rectInfo = target.rect;
@@ -3628,7 +3979,14 @@ var TourPopoverPortal = ({
3628
3979
  padding: FLOATING_OFFSET,
3629
3980
  alignment: autoAlignment
3630
3981
  })
3631
- ] : [(0, import_dom13.flip)({ padding: FLOATING_OFFSET, fallbackStrategy: "bestFit" })],
3982
+ ] : [
3983
+ (0, import_dom13.flip)({
3984
+ padding: FLOATING_OFFSET,
3985
+ fallbackStrategy: "bestFit",
3986
+ crossAxis: true,
3987
+ fallbackPlacements: ["bottom", "top", "right", "left"]
3988
+ })
3989
+ ],
3632
3990
  (0, import_dom13.shift)({ padding: FLOATING_OFFSET })
3633
3991
  ];
3634
3992
  const updatePosition = async () => {
@@ -3673,9 +4031,10 @@ var TourPopoverPortal = ({
3673
4031
  const spaceBelow = viewportBottom - targetRect.bottom;
3674
4032
  const spaceLeft = targetRect.left - viewportLeft;
3675
4033
  const spaceRight = viewportRight - targetRect.right;
3676
- const minSpaceNeeded = floatingBox.height + FLOATING_OFFSET * 2;
3677
- const hasVerticalSpace = spaceAbove >= minSpaceNeeded || spaceBelow >= minSpaceNeeded;
3678
- const hasHorizontalSpace = spaceLeft >= minSpaceNeeded || spaceRight >= minSpaceNeeded;
4034
+ const minVerticalSpaceNeeded = floatingBox.height + FLOATING_OFFSET * 2;
4035
+ const minHorizontalSpaceNeeded = floatingBox.width + FLOATING_OFFSET * 2;
4036
+ const hasVerticalSpace = spaceAbove >= minVerticalSpaceNeeded || spaceBelow >= minVerticalSpaceNeeded;
4037
+ const hasHorizontalSpace = spaceLeft >= minHorizontalSpaceNeeded || spaceRight >= minHorizontalSpaceNeeded;
3679
4038
  const targetNearlyFillsViewport = !target.isScreen && !hasVerticalSpace && !hasHorizontalSpace;
3680
4039
  const shouldDock = intersectsViewport && (targetNearlyFillsViewport || maxOverflow > overflowThreshold);
3681
4040
  if (shouldDock) {
@@ -3724,7 +4083,7 @@ var TourPopoverPortal = ({
3724
4083
  target.status,
3725
4084
  target.stepId
3726
4085
  ]);
3727
- (0, import_react21.useLayoutEffect)(() => {
4086
+ (0, import_react24.useLayoutEffect)(() => {
3728
4087
  if (layoutMode !== "manual" || !dragPosition) return;
3729
4088
  setFloatingPosition({
3730
4089
  top: dragPosition.top,
@@ -3809,7 +4168,7 @@ var TourPopoverPortal = ({
3809
4168
  }
3810
4169
  event.preventDefault();
3811
4170
  };
3812
- (0, import_react21.useEffect)(() => endDrag, []);
4171
+ (0, import_react24.useEffect)(() => endDrag, []);
3813
4172
  const shouldUseFallbackInitial = layoutMode !== "mobile" && (Boolean(target.lastResolvedRect) || Boolean(cachedTarget));
3814
4173
  const floatingCacheKey = layoutMode === "mobile" ? null : getFloatingCacheKey(target);
3815
4174
  const persistedFloatingInitial = floatingCacheKey && floatingPositionCache.has(floatingCacheKey) ? floatingPositionCache.get(floatingCacheKey) ?? null : null;
@@ -3901,7 +4260,7 @@ var TourPopoverPortal = ({
3901
4260
  };
3902
4261
 
3903
4262
  // src/components/TourFocusManager.tsx
3904
- var import_react22 = require("react");
4263
+ var import_react25 = require("react");
3905
4264
  var import_react_dom3 = require("react-dom");
3906
4265
 
3907
4266
  // src/utils/focus.ts
@@ -3962,7 +4321,7 @@ var focusElement = (element, options) => {
3962
4321
  };
3963
4322
 
3964
4323
  // src/components/TourFocusManager.tsx
3965
- var import_jsx_runtime4 = require("react/jsx-runtime");
4324
+ var import_jsx_runtime5 = require("react/jsx-runtime");
3966
4325
  var runMicrotask = (callback) => {
3967
4326
  if (typeof queueMicrotask === "function") {
3968
4327
  queueMicrotask(callback);
@@ -3978,18 +4337,18 @@ var TourFocusManager = ({
3978
4337
  highlightRect,
3979
4338
  guardElementFocusRing
3980
4339
  }) => {
3981
- const previousFocusRef = (0, import_react22.useRef)(null);
3982
- const guardNodesRef = (0, import_react22.useRef)({
4340
+ const previousFocusRef = (0, import_react25.useRef)(null);
4341
+ const guardNodesRef = (0, import_react25.useRef)({
3983
4342
  "target-start": null,
3984
4343
  "target-end": null,
3985
4344
  "popover-start": null,
3986
4345
  "popover-end": null
3987
4346
  });
3988
- const lastTabDirectionRef = (0, import_react22.useRef)("forward");
3989
- const suppressGuardHopRef = (0, import_react22.useRef)(null);
3990
- const [targetRingActive, setTargetRingActive] = (0, import_react22.useState)(false);
3991
- const [popoverRingActive, setPopoverRingActive] = (0, import_react22.useState)(false);
3992
- const [popoverRect, setPopoverRect] = (0, import_react22.useState)(null);
4347
+ const lastTabDirectionRef = (0, import_react25.useRef)("forward");
4348
+ const suppressGuardHopRef = (0, import_react25.useRef)(null);
4349
+ const [targetRingActive, setTargetRingActive] = (0, import_react25.useState)(false);
4350
+ const [popoverRingActive, setPopoverRingActive] = (0, import_react25.useState)(false);
4351
+ const [popoverRect, setPopoverRect] = (0, import_react25.useState)(null);
3993
4352
  const restoreFocus = () => {
3994
4353
  const previous = previousFocusRef.current;
3995
4354
  previousFocusRef.current = null;
@@ -3999,7 +4358,7 @@ var TourFocusManager = ({
3999
4358
  });
4000
4359
  }
4001
4360
  };
4002
- (0, import_react22.useLayoutEffect)(() => {
4361
+ (0, import_react25.useLayoutEffect)(() => {
4003
4362
  if (!isBrowser) return;
4004
4363
  if (!active) {
4005
4364
  restoreFocus();
@@ -4015,7 +4374,7 @@ var TourFocusManager = ({
4015
4374
  restoreFocus();
4016
4375
  };
4017
4376
  }, [active, popoverNode, target.element]);
4018
- (0, import_react22.useEffect)(() => {
4377
+ (0, import_react25.useEffect)(() => {
4019
4378
  if (!isBrowser) return;
4020
4379
  if (!active) return;
4021
4380
  const doc = popoverNode?.ownerDocument ?? target.element?.ownerDocument ?? document;
@@ -4209,7 +4568,7 @@ var TourFocusManager = ({
4209
4568
  target.stepId,
4210
4569
  target.visibility
4211
4570
  ]);
4212
- (0, import_react22.useLayoutEffect)(() => {
4571
+ (0, import_react25.useLayoutEffect)(() => {
4213
4572
  if (popoverRingActive && popoverNode) {
4214
4573
  setPopoverRect(popoverNode.getBoundingClientRect());
4215
4574
  } else {
@@ -4224,8 +4583,8 @@ var TourFocusManager = ({
4224
4583
  const showPopoverRing = popoverRingActive && popoverRect;
4225
4584
  if (!showTargetRing && !showPopoverRing) return null;
4226
4585
  return (0, import_react_dom3.createPortal)(
4227
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
4228
- showTargetRing && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4586
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
4587
+ showTargetRing && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4229
4588
  "div",
4230
4589
  {
4231
4590
  style: {
@@ -4242,7 +4601,7 @@ var TourFocusManager = ({
4242
4601
  "aria-hidden": true
4243
4602
  }
4244
4603
  ),
4245
- showPopoverRing && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4604
+ showPopoverRing && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4246
4605
  "div",
4247
4606
  {
4248
4607
  style: {
@@ -4265,7 +4624,7 @@ var TourFocusManager = ({
4265
4624
  };
4266
4625
 
4267
4626
  // src/motion/useHudMotion.ts
4268
- var import_react23 = require("react");
4627
+ var import_react26 = require("react");
4269
4628
  var DEFAULT_HIGHLIGHT_TRANSITION2 = {
4270
4629
  duration: 0.35,
4271
4630
  ease: "easeOut",
@@ -4292,7 +4651,7 @@ var DEFAULT_POPOVER_CONTENT_TRANSITION2 = {
4292
4651
  };
4293
4652
  var useHudMotion = () => {
4294
4653
  const adapter = useAnimationAdapter();
4295
- return (0, import_react23.useMemo)(() => {
4654
+ return (0, import_react26.useMemo)(() => {
4296
4655
  const components = {
4297
4656
  ...adapter.components
4298
4657
  };
@@ -4311,12 +4670,12 @@ var useHudMotion = () => {
4311
4670
  // Annotate the CommonJS export names for ESM import in node:
4312
4671
  0 && (module.exports = {
4313
4672
  AnimationAdapterProvider,
4673
+ DialogRegistryProvider,
4314
4674
  OverlayBackdrop,
4315
4675
  TourFocusManager,
4316
4676
  TourPopoverPortal,
4317
4677
  TourProvider,
4318
4678
  createPathString,
4319
- createRadixDialogHelpers,
4320
4679
  createWaitForPredicateController,
4321
4680
  defaultAnimationAdapter,
4322
4681
  defaultLabels,
@@ -4328,6 +4687,8 @@ var useHudMotion = () => {
4328
4687
  useAnimationAdapter,
4329
4688
  useBodyScrollLock,
4330
4689
  useDelayAdvance,
4690
+ useDialogRegistry,
4691
+ useDialogRegistryOptional,
4331
4692
  useHiddenTargetFallback,
4332
4693
  useHudDescription,
4333
4694
  useHudMotion,
@@ -4336,6 +4697,7 @@ var useHudMotion = () => {
4336
4697
  useHudTargetIssue,
4337
4698
  usePreferredAnimationAdapter,
4338
4699
  useRadixDialogAdapter,
4700
+ useRadixTourDialog,
4339
4701
  useTour,
4340
4702
  useTourControls,
4341
4703
  useTourEvents,