@tent-official/react-walkthrough 1.3.0 → 1.3.4

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
@@ -92,7 +92,8 @@ Hook to register a walkthrough tour.
92
92
  | `displayTotal` | `number` | — | Override the total step count displayed in the step counter (display-only, does not affect logic) |
93
93
  | `displayStepOffset` | `number` | `0` | Offset added to the displayed current step number (display-only, does not affect logic). e.g. `displayStepOffset: 3` with 3 real steps shows 4/total → 5/total → 6/total |
94
94
  | `isClearLastPositionOnEnd` | `boolean` | `false` | When `true`, clears the saved last highlight position when the tour ends. This prevents the next tour from animating its highlight from this tour's last position |
95
- | `onStepNext` | `Record<number, () => void>` | — | Callbacks fired when the user clicks "Next" on a specific step. The key is the original step index (0-based). Called right before advancing to the next step |
95
+ | `onStepNext` | `Record<number, () => void>` | — | Map of original step index → callback. Fires when the user clicks "Next" from that step. Example: `{ 0: () => console.log("left step 0"), 2: () => doSomething() }` |
96
+ | `onStepPrev` | `Record<number, () => void>` | — | Map of original step index → callback. Fires when the user clicks "Back" from that step. Example: `{ 1: () => closeDropdown(), 3: () => cleanup() }` |
96
97
 
97
98
  **Returns:** `{ start: () => void }`
98
99
 
@@ -114,9 +115,9 @@ Hook to register a walkthrough tour.
114
115
  | `nextLabel` | `string` | — | Override tour-level `nextLabel` for this step |
115
116
  | `prevLabel` | `string` | — | Override tour-level `prevLabel` for this step |
116
117
  | `skipLabel` | `string` | — | Override tour-level `skipLabel` for this step |
117
- | `displayStep` | `number` | — | Override the displayed current step number for this step (display-only, does not affect logic) |
118
- | `displayTotal` | `number` | — | Override the displayed total step count for this step (display-only, does not affect logic) |
119
- | `forceRecompute` | `boolean` | `false` | 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 |
118
+ | `displayStep` | `number` | — | Override the displayed step number for this step (display-only) |
119
+ | `displayTotal` | `number` | — | Override the displayed total for this step (display-only) |
120
+ | `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 |
120
121
 
121
122
  ### `IStepDescription`
122
123
 
@@ -258,44 +259,9 @@ The popover automatically positions itself to stay within the viewport:
258
259
 
259
260
  The popover also waits for the target element to be scrolled into view before appearing.
260
261
 
261
- ## Step-Level Callbacks (`onStepNext`)
262
+ ## Instant Dismiss
262
263
 
263
- Use `onStepNext` to fire a custom function when the user clicks "Next" on a specific step. The key is the original step index (0-based):
264
-
265
- ```jsx
266
- useWalkthrough({
267
- name: "setup-tour",
268
- steps: [
269
- { el: "print-side", title: "Print Side", description: [{ description: "Select print side" }] },
270
- { el: "print-system", title: "Print System", description: [{ description: "Select print system" }] },
271
- { el: "print-color", title: "Print Color", description: [{ description: "Select color" }] },
272
- ],
273
- onStepNext: {
274
- 0: () => openPrintSystemDropdown(), // fired when leaving step 0
275
- 1: () => fetchColorOptions(), // fired when leaving step 1
276
- },
277
- });
278
- ```
279
-
280
- ## Force Recompute (`forceRecompute`)
281
-
282
- When a step's next element is conditionally rendered (hidden until some action), use `forceRecompute` to wait for it to appear before advancing:
283
-
284
- ```jsx
285
- steps: [
286
- {
287
- el: "print-side",
288
- title: "Print Side",
289
- forceRecompute: true, // wait for next element to appear after advancing
290
- description: [{ description: "Select print side — the next section will appear after selection" }],
291
- },
292
- {
293
- el: "print-system", // this element is hidden until print-side is selected
294
- title: "Print System",
295
- description: [{ description: "Now select the print system" }],
296
- },
297
- ]
298
- ```
264
+ When the user clicks **Done** on the last step (or **Skip** at any step), the highlight and popover vanish **instantly** in the same render frame — no lingering overlay or flash.
299
265
 
300
266
  ## License
301
267
 
package/dist/index.d.mts CHANGED
@@ -105,6 +105,8 @@ interface IUseWalkthroughOptions {
105
105
  isClearLastPositionOnEnd?: boolean;
106
106
  /** Callbacks fired when the user clicks "Next" on a specific step. The key is the original step index (0-based). Called right before advancing to the next step. Example: `onStepNext: { 0: () => openDropdown(), 2: () => fetchData() }` */
107
107
  onStepNext?: Record<number, () => void>;
108
+ /** Callbacks fired when the user clicks "Back" on a specific step. The key is the original step index (0-based). Called right before going back to the previous step. Example: `onStepPrev: { 1: () => closeDropdown(), 3: () => cleanup() }` */
109
+ onStepPrev?: Record<number, () => void>;
108
110
  }
109
111
  /**
110
112
  * Return value of the useWalkthrough hook.
package/dist/index.d.ts CHANGED
@@ -105,6 +105,8 @@ interface IUseWalkthroughOptions {
105
105
  isClearLastPositionOnEnd?: boolean;
106
106
  /** Callbacks fired when the user clicks "Next" on a specific step. The key is the original step index (0-based). Called right before advancing to the next step. Example: `onStepNext: { 0: () => openDropdown(), 2: () => fetchData() }` */
107
107
  onStepNext?: Record<number, () => void>;
108
+ /** Callbacks fired when the user clicks "Back" on a specific step. The key is the original step index (0-based). Called right before going back to the previous step. Example: `onStepPrev: { 1: () => closeDropdown(), 3: () => cleanup() }` */
109
+ onStepPrev?: Record<number, () => void>;
108
110
  }
109
111
  /**
110
112
  * Return value of the useWalkthrough hook.
package/dist/index.js CHANGED
@@ -223,12 +223,14 @@ var useWalkthrough = ({
223
223
  displayTotal,
224
224
  displayStepOffset,
225
225
  isClearLastPositionOnEnd = false,
226
- onStepNext
226
+ onStepNext,
227
+ onStepPrev
227
228
  }) => {
228
229
  const started = react.useRef(false);
229
230
  const onCompleteRef = react.useRef(onWalkthroughComplete);
230
231
  const handleWhenLastStepRef = react.useRef(handleWhenLastStep);
231
232
  const onStepNextRef = react.useRef(onStepNext);
233
+ const onStepPrevRef = react.useRef(onStepPrev);
232
234
  const conditionMet = startWhenCondition === void 0 ? true : typeof startWhenCondition === "function" ? startWhenCondition() : !!startWhenCondition;
233
235
  react.useEffect(() => {
234
236
  onCompleteRef.current = onWalkthroughComplete;
@@ -239,6 +241,9 @@ var useWalkthrough = ({
239
241
  react.useEffect(() => {
240
242
  onStepNextRef.current = onStepNext;
241
243
  }, [onStepNext]);
244
+ react.useEffect(() => {
245
+ onStepPrevRef.current = onStepPrev;
246
+ }, [onStepPrev]);
242
247
  const start = react.useCallback(() => {
243
248
  if (isDone(storageSuffix, name) || started.current) return;
244
249
  started.current = true;
@@ -263,7 +268,8 @@ var useWalkthrough = ({
263
268
  displayTotal,
264
269
  displayStepOffset,
265
270
  isClearLastPositionOnEnd,
266
- onStepNext: onStepNextRef.current
271
+ onStepNext: onStepNextRef.current,
272
+ onStepPrev: onStepPrevRef.current
267
273
  }
268
274
  });
269
275
  }, [
@@ -637,6 +643,7 @@ var WalkthroughOverlay = ({
637
643
  const popoverRef = react.useRef(null);
638
644
  const [popoverPos, setPopoverPos] = react.useState(null);
639
645
  const [popoverHidden, setPopoverHidden] = react.useState(false);
646
+ const [isDismissing, setIsDismissing] = react.useState(false);
640
647
  const displayStepRef = react.useRef(null);
641
648
  const displayPosRef = react.useRef(null);
642
649
  const [validSteps, setValidSteps] = react.useState([]);
@@ -649,6 +656,7 @@ var WalkthroughOverlay = ({
649
656
  if (!activeTour) {
650
657
  setValidSteps([]);
651
658
  setIsDelaying(false);
659
+ setIsDismissing(false);
652
660
  waitingForElsRef.current = false;
653
661
  delayDoneForRef.current = null;
654
662
  skipNextRecomputeRef.current = false;
@@ -848,6 +856,7 @@ var WalkthroughOverlay = ({
848
856
  setPopoverHidden(false);
849
857
  }, [popoverHidden, isAnimating, step, popoverPos]);
850
858
  if (!activeTour) return null;
859
+ if (isDismissing) return null;
851
860
  if (_activeOverlayId !== null && _activeOverlayId !== instanceIdRef.current) {
852
861
  return null;
853
862
  }
@@ -938,6 +947,7 @@ var WalkthroughOverlay = ({
938
947
  const hasMoreOriginalSteps = currentOrigIdx < activeTour.steps.length - 1;
939
948
  const effectiveIsLast = isLast && !(hasTrigger && hasMoreOriginalSteps);
940
949
  if (effectiveIsLast) {
950
+ setIsDismissing(true);
941
951
  if (activeTour.handleWhenLastStep) activeTour.handleWhenLastStep();
942
952
  completeTour();
943
953
  } else {
@@ -1050,8 +1060,7 @@ var WalkthroughOverlay = ({
1050
1060
  }
1051
1061
  return;
1052
1062
  }
1053
- setPopoverHidden(true);
1054
- setPopoverPos(null);
1063
+ setIsDismissing(true);
1055
1064
  if (activeTour.handleWhenLastStep) activeTour.handleWhenLastStep();
1056
1065
  setTimeout(() => completeTour(), 300);
1057
1066
  return;
@@ -1059,7 +1068,13 @@ var WalkthroughOverlay = ({
1059
1068
  advanceStep(hasTrigger);
1060
1069
  };
1061
1070
  const prev = () => {
1071
+ var _a2;
1062
1072
  if (currentValidPos > 0) {
1073
+ const currentOrigIdx = validSteps[currentValidPos]._originalIdx;
1074
+ const stepPrevCb = (_a2 = activeTour.onStepPrev) == null ? void 0 : _a2[currentOrigIdx];
1075
+ if (typeof stepPrevCb === "function") {
1076
+ stepPrevCb();
1077
+ }
1063
1078
  setPopoverHidden(true);
1064
1079
  setPopoverPos(null);
1065
1080
  const prevStep = validSteps[currentValidPos - 1];
@@ -1070,6 +1085,7 @@ var WalkthroughOverlay = ({
1070
1085
  }
1071
1086
  };
1072
1087
  const skip = () => {
1088
+ setIsDismissing(true);
1073
1089
  completeTour();
1074
1090
  };
1075
1091
  const popoverWidth = clampSize(step.width, window.innerWidth);