@tent-official/react-walkthrough 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -118,8 +118,8 @@ Hook to register a walkthrough tour.
118
118
  | `skipLabel` | `string` | — | Override tour-level `skipLabel` for this step |
119
119
  | `displayStep` | `number` | — | Override the displayed step number for this step (display-only) |
120
120
  | `displayTotal` | `number` | — | Override the displayed total for this step (display-only) |
121
- | `forceRecompute` | `boolean` | — | When `true`, forces a DOM re-read before advancing to the next step. Useful when the next element is conditionally rendered and needs a layout update to appear |
122
121
  | `delayAfterNext` | `number` | `0` | Delay in ms after clicking "Next" (after `onStepNext` and `triggerElOnNext` have fired) before advancing to the next step. The overlay stays visible with the popover hidden during the delay |
122
+ | `nextEl` | `string` | — | DOM element ID to look for after `delayAfterNext` completes. If found, advances to the step that owns it. If not found, skips to the next valid step. Supports `#id` or `id` format |
123
123
 
124
124
  ### `IStepDescription`
125
125
 
package/dist/index.d.mts CHANGED
@@ -59,10 +59,10 @@ interface IWalkthroughStep {
59
59
  displayStep?: number;
60
60
  /** Override the displayed total step count for this specific step (display-only, does not affect logic). If omitted, uses the tour-level displayTotal or actual count */
61
61
  displayTotal?: number;
62
- /** When true, forces a recompute of valid steps after advancing from this step. Useful when the next step's element is hidden/conditional and needs DOM changes to become visible. Default: false */
63
- forceRecompute?: boolean;
64
62
  /** Delay in milliseconds after clicking "Next" (after onStepNext and triggerElOnNext have fired) before advancing to the next step. The overlay stays visible with the popover hidden during the delay. Default: 0 (no delay) */
65
63
  delayAfterNext?: number;
64
+ /** DOM element ID to look for after delayAfterNext completes. If the element is found in the DOM, the tour advances to the step that owns it. If not found, the step is skipped and the tour moves to the next valid step. Supports "#id" or "id" format. */
65
+ nextEl?: string;
66
66
  }
67
67
  /**
68
68
  * Options for the useWalkthrough hook.
package/dist/index.d.ts CHANGED
@@ -59,10 +59,10 @@ interface IWalkthroughStep {
59
59
  displayStep?: number;
60
60
  /** Override the displayed total step count for this specific step (display-only, does not affect logic). If omitted, uses the tour-level displayTotal or actual count */
61
61
  displayTotal?: number;
62
- /** When true, forces a recompute of valid steps after advancing from this step. Useful when the next step's element is hidden/conditional and needs DOM changes to become visible. Default: false */
63
- forceRecompute?: boolean;
64
62
  /** Delay in milliseconds after clicking "Next" (after onStepNext and triggerElOnNext have fired) before advancing to the next step. The overlay stays visible with the popover hidden during the delay. Default: 0 (no delay) */
65
63
  delayAfterNext?: number;
64
+ /** DOM element ID to look for after delayAfterNext completes. If the element is found in the DOM, the tour advances to the step that owns it. If not found, the step is skipped and the tour moves to the next valid step. Supports "#id" or "id" format. */
65
+ nextEl?: string;
66
66
  }
67
67
  /**
68
68
  * Options for the useWalkthrough hook.
package/dist/index.js CHANGED
@@ -967,43 +967,6 @@ var WalkthroughOverlay = ({
967
967
  setPopoverPos(null);
968
968
  const nextValidStep = validSteps[currentValidPos + 1];
969
969
  const nextOrigIdx = hasTrigger && !nextValidStep ? currentOrigIdx + 1 : (_a2 = nextValidStep == null ? void 0 : nextValidStep._originalIdx) != null ? _a2 : currentOrigIdx + 1;
970
- const shouldForceRecompute = !!step.forceRecompute;
971
- if (shouldForceRecompute) {
972
- const nextStepDef = activeTour.steps[nextOrigIdx];
973
- if (nextStepDef) {
974
- const nextElId = resolveElId(nextStepDef.el);
975
- const SETTLE_DELAY = 150;
976
- const doAdvance = () => {
977
- setGlobalState((s) => ({
978
- ...s,
979
- activeTour: { ...s.activeTour, currentStep: nextOrigIdx }
980
- }));
981
- };
982
- const alreadyExists = document.getElementById(nextElId);
983
- if (alreadyExists) {
984
- setTimeout(() => doAdvance(), SETTLE_DELAY);
985
- } else {
986
- waitingForElsRef.current = true;
987
- const observer = new MutationObserver(() => {
988
- const found = document.getElementById(nextElId);
989
- if (found) {
990
- observer.disconnect();
991
- waitingForElsRef.current = false;
992
- setTimeout(() => doAdvance(), SETTLE_DELAY);
993
- }
994
- });
995
- observer.observe(document.body, { childList: true, subtree: true });
996
- setTimeout(() => {
997
- observer.disconnect();
998
- if (waitingForElsRef.current) {
999
- waitingForElsRef.current = false;
1000
- doAdvance();
1001
- }
1002
- }, 3e3);
1003
- }
1004
- return;
1005
- }
1006
- }
1007
970
  setGlobalState((s) => ({
1008
971
  ...s,
1009
972
  activeTour: { ...s.activeTour, currentStep: nextOrigIdx }
@@ -1019,6 +982,7 @@ var WalkthroughOverlay = ({
1019
982
  }
1020
983
  const hasTrigger = !!step.triggerElOnNext;
1021
984
  const afterNextDelay = (_b2 = step.delayAfterNext) != null ? _b2 : 0;
985
+ const nextElId = step.nextEl ? resolveElId(step.nextEl) : null;
1022
986
  const withDelay = (fn) => {
1023
987
  if (afterNextDelay > 0) {
1024
988
  setTimeout(fn, afterNextDelay);
@@ -1026,6 +990,39 @@ var WalkthroughOverlay = ({
1026
990
  fn();
1027
991
  }
1028
992
  };
993
+ const advanceWithNextEl = () => {
994
+ const SETTLE_DELAY = 150;
995
+ const targetEl = document.getElementById(nextElId);
996
+ if (targetEl) {
997
+ const targetStepIdx = activeTour.steps.findIndex(
998
+ (s) => resolveElId(s.el) === nextElId
999
+ );
1000
+ if (targetStepIdx !== -1) {
1001
+ const targetStepDef = activeTour.steps[targetStepIdx];
1002
+ const targetStepWithIdx = { ...targetStepDef, _originalIdx: targetStepIdx };
1003
+ const alreadyInValid = validSteps.some((s) => s._originalIdx === targetStepIdx);
1004
+ const newValidSteps = alreadyInValid ? validSteps : [...validSteps, targetStepWithIdx].sort((a, b) => a._originalIdx - b._originalIdx);
1005
+ setValidSteps(newValidSteps);
1006
+ skipNextRecomputeRef.current = true;
1007
+ setTimeout(() => {
1008
+ setGlobalState((s) => ({
1009
+ ...s,
1010
+ activeTour: { ...s.activeTour, currentStep: targetStepIdx }
1011
+ }));
1012
+ }, SETTLE_DELAY);
1013
+ return;
1014
+ }
1015
+ }
1016
+ const nextValid = validSteps.find((s) => s._originalIdx > currentOrigIdx);
1017
+ if (nextValid) {
1018
+ setGlobalState((s) => ({
1019
+ ...s,
1020
+ activeTour: { ...s.activeTour, currentStep: nextValid._originalIdx }
1021
+ }));
1022
+ } else {
1023
+ completeTour();
1024
+ }
1025
+ };
1029
1026
  if (hasTrigger) {
1030
1027
  setPopoverHidden(true);
1031
1028
  setPopoverPos(null);
@@ -1037,32 +1034,33 @@ var WalkthroughOverlay = ({
1037
1034
  triggerTarget.dispatchEvent(new MouseEvent("mouseup", { bubbles: true, cancelable: true, button: 0 }));
1038
1035
  triggerTarget.click();
1039
1036
  }
1040
- const currentOrigIdx2 = validSteps[currentValidPos]._originalIdx;
1041
- const nextOrigIdx = currentOrigIdx2 + 1;
1037
+ if (nextElId) {
1038
+ withDelay(() => advanceWithNextEl());
1039
+ return;
1040
+ }
1041
+ const nextOrigIdx = currentOrigIdx + 1;
1042
1042
  const nextStepDef = activeTour.steps[nextOrigIdx];
1043
1043
  if (nextStepDef) {
1044
- const nextElId = resolveElId(nextStepDef.el);
1044
+ const nextStepElId = resolveElId(nextStepDef.el);
1045
1045
  const injectAndAdvance = () => {
1046
1046
  const nextStepWithIdx = { ...nextStepDef, _originalIdx: nextOrigIdx };
1047
1047
  const alreadyInValid = validSteps.some((s) => s._originalIdx === nextOrigIdx);
1048
1048
  const newValidSteps = alreadyInValid ? validSteps : [...validSteps, nextStepWithIdx].sort((a, b) => a._originalIdx - b._originalIdx);
1049
1049
  setValidSteps(newValidSteps);
1050
- if (!step.forceRecompute) {
1051
- skipNextRecomputeRef.current = true;
1052
- }
1050
+ skipNextRecomputeRef.current = true;
1053
1051
  setGlobalState((s) => ({
1054
1052
  ...s,
1055
1053
  activeTour: { ...s.activeTour, currentStep: nextOrigIdx }
1056
1054
  }));
1057
1055
  };
1058
1056
  const SETTLE_DELAY = 150;
1059
- const alreadyExists = document.getElementById(nextElId);
1057
+ const alreadyExists = document.getElementById(nextStepElId);
1060
1058
  if (alreadyExists) {
1061
1059
  withDelay(() => setTimeout(() => injectAndAdvance(), SETTLE_DELAY));
1062
1060
  } else {
1063
1061
  waitingForElsRef.current = true;
1064
1062
  const observer = new MutationObserver(() => {
1065
- const found = document.getElementById(nextElId);
1063
+ const found = document.getElementById(nextStepElId);
1066
1064
  if (found) {
1067
1065
  observer.disconnect();
1068
1066
  waitingForElsRef.current = false;
@@ -1085,6 +1083,12 @@ var WalkthroughOverlay = ({
1085
1083
  setTimeout(() => completeTour(), 300);
1086
1084
  return;
1087
1085
  }
1086
+ if (nextElId) {
1087
+ setPopoverHidden(true);
1088
+ setPopoverPos(null);
1089
+ withDelay(() => advanceWithNextEl());
1090
+ return;
1091
+ }
1088
1092
  if (afterNextDelay > 0) {
1089
1093
  setPopoverHidden(true);
1090
1094
  setPopoverPos(null);