@tent-official/react-walkthrough 1.1.102 → 1.3.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 +43 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +69 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +69 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -92,6 +92,7 @@ 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
96
|
|
|
96
97
|
**Returns:** `{ start: () => void }`
|
|
97
98
|
|
|
@@ -113,6 +114,9 @@ Hook to register a walkthrough tour.
|
|
|
113
114
|
| `nextLabel` | `string` | — | Override tour-level `nextLabel` for this step |
|
|
114
115
|
| `prevLabel` | `string` | — | Override tour-level `prevLabel` for this step |
|
|
115
116
|
| `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 |
|
|
116
120
|
|
|
117
121
|
### `IStepDescription`
|
|
118
122
|
|
|
@@ -254,6 +258,45 @@ The popover automatically positions itself to stay within the viewport:
|
|
|
254
258
|
|
|
255
259
|
The popover also waits for the target element to be scrolled into view before appearing.
|
|
256
260
|
|
|
261
|
+
## Step-Level Callbacks (`onStepNext`)
|
|
262
|
+
|
|
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
|
+
```
|
|
299
|
+
|
|
257
300
|
## License
|
|
258
301
|
|
|
259
302
|
MIT
|
package/dist/index.d.mts
CHANGED
|
@@ -52,6 +52,12 @@ interface IWalkthroughStep {
|
|
|
52
52
|
prevLabel?: string;
|
|
53
53
|
/** Override tour-level skipLabel for this specific step. If omitted, uses the tour-level value */
|
|
54
54
|
skipLabel?: string;
|
|
55
|
+
/** Override the displayed current step number for this specific step (display-only, does not affect logic). If omitted, uses the calculated value from tour-level settings */
|
|
56
|
+
displayStep?: number;
|
|
57
|
+
/** 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 */
|
|
58
|
+
displayTotal?: number;
|
|
59
|
+
/** 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 */
|
|
60
|
+
forceRecompute?: boolean;
|
|
55
61
|
}
|
|
56
62
|
/**
|
|
57
63
|
* Options for the useWalkthrough hook.
|
|
@@ -97,6 +103,8 @@ interface IUseWalkthroughOptions {
|
|
|
97
103
|
displayStepOffset?: number;
|
|
98
104
|
/** 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. Default: false */
|
|
99
105
|
isClearLastPositionOnEnd?: boolean;
|
|
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
|
+
onStepNext?: Record<number, () => void>;
|
|
100
108
|
}
|
|
101
109
|
/**
|
|
102
110
|
* Return value of the useWalkthrough hook.
|
package/dist/index.d.ts
CHANGED
|
@@ -52,6 +52,12 @@ interface IWalkthroughStep {
|
|
|
52
52
|
prevLabel?: string;
|
|
53
53
|
/** Override tour-level skipLabel for this specific step. If omitted, uses the tour-level value */
|
|
54
54
|
skipLabel?: string;
|
|
55
|
+
/** Override the displayed current step number for this specific step (display-only, does not affect logic). If omitted, uses the calculated value from tour-level settings */
|
|
56
|
+
displayStep?: number;
|
|
57
|
+
/** 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 */
|
|
58
|
+
displayTotal?: number;
|
|
59
|
+
/** 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 */
|
|
60
|
+
forceRecompute?: boolean;
|
|
55
61
|
}
|
|
56
62
|
/**
|
|
57
63
|
* Options for the useWalkthrough hook.
|
|
@@ -97,6 +103,8 @@ interface IUseWalkthroughOptions {
|
|
|
97
103
|
displayStepOffset?: number;
|
|
98
104
|
/** 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. Default: false */
|
|
99
105
|
isClearLastPositionOnEnd?: boolean;
|
|
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
|
+
onStepNext?: Record<number, () => void>;
|
|
100
108
|
}
|
|
101
109
|
/**
|
|
102
110
|
* Return value of the useWalkthrough hook.
|
package/dist/index.js
CHANGED
|
@@ -222,11 +222,13 @@ var useWalkthrough = ({
|
|
|
222
222
|
animationSpeed = 350,
|
|
223
223
|
displayTotal,
|
|
224
224
|
displayStepOffset,
|
|
225
|
-
isClearLastPositionOnEnd = false
|
|
225
|
+
isClearLastPositionOnEnd = false,
|
|
226
|
+
onStepNext
|
|
226
227
|
}) => {
|
|
227
228
|
const started = react.useRef(false);
|
|
228
229
|
const onCompleteRef = react.useRef(onWalkthroughComplete);
|
|
229
230
|
const handleWhenLastStepRef = react.useRef(handleWhenLastStep);
|
|
231
|
+
const onStepNextRef = react.useRef(onStepNext);
|
|
230
232
|
const conditionMet = startWhenCondition === void 0 ? true : typeof startWhenCondition === "function" ? startWhenCondition() : !!startWhenCondition;
|
|
231
233
|
react.useEffect(() => {
|
|
232
234
|
onCompleteRef.current = onWalkthroughComplete;
|
|
@@ -234,6 +236,9 @@ var useWalkthrough = ({
|
|
|
234
236
|
react.useEffect(() => {
|
|
235
237
|
handleWhenLastStepRef.current = handleWhenLastStep;
|
|
236
238
|
}, [handleWhenLastStep]);
|
|
239
|
+
react.useEffect(() => {
|
|
240
|
+
onStepNextRef.current = onStepNext;
|
|
241
|
+
}, [onStepNext]);
|
|
237
242
|
const start = react.useCallback(() => {
|
|
238
243
|
if (isDone(storageSuffix, name) || started.current) return;
|
|
239
244
|
started.current = true;
|
|
@@ -257,7 +262,8 @@ var useWalkthrough = ({
|
|
|
257
262
|
animationSpeed,
|
|
258
263
|
displayTotal,
|
|
259
264
|
displayStepOffset,
|
|
260
|
-
isClearLastPositionOnEnd
|
|
265
|
+
isClearLastPositionOnEnd,
|
|
266
|
+
onStepNext: onStepNextRef.current
|
|
261
267
|
}
|
|
262
268
|
});
|
|
263
269
|
}, [
|
|
@@ -609,7 +615,7 @@ var WalkthroughOverlay = ({
|
|
|
609
615
|
prevColor,
|
|
610
616
|
skipColor
|
|
611
617
|
} = {}) => {
|
|
612
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
618
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
|
|
613
619
|
injectKeyframes();
|
|
614
620
|
const { activeTour } = useGlobalState();
|
|
615
621
|
const instanceIdRef = react.useRef(null);
|
|
@@ -911,9 +917,9 @@ var WalkthroughOverlay = ({
|
|
|
911
917
|
const totalSteps = validSteps.length;
|
|
912
918
|
const isLast = currentValidPos === totalSteps - 1;
|
|
913
919
|
const stepOffset = (_c = activeTour.displayStepOffset) != null ? _c : 0;
|
|
914
|
-
const displayCurrentStep = currentValidPos + 1 + stepOffset;
|
|
915
|
-
const displayTotalSteps = (
|
|
916
|
-
const borderRadius = (
|
|
920
|
+
const displayCurrentStep = (_d = step.displayStep) != null ? _d : currentValidPos + 1 + stepOffset;
|
|
921
|
+
const displayTotalSteps = (_f = (_e = step.displayTotal) != null ? _e : activeTour.displayTotal) != null ? _f : totalSteps;
|
|
922
|
+
const borderRadius = (_g = step.borderRadius) != null ? _g : 10;
|
|
917
923
|
const {
|
|
918
924
|
isShowSkip = true,
|
|
919
925
|
isShowPrev = true,
|
|
@@ -923,9 +929,9 @@ var WalkthroughOverlay = ({
|
|
|
923
929
|
skipLabel: tourSkipLabel = "Skip",
|
|
924
930
|
doneLabel = "Done"
|
|
925
931
|
} = activeTour;
|
|
926
|
-
const nextLabel = (
|
|
927
|
-
const prevLabel = (
|
|
928
|
-
const skipLabel = (
|
|
932
|
+
const nextLabel = (_h = step.nextLabel) != null ? _h : tourNextLabel;
|
|
933
|
+
const prevLabel = (_i = step.prevLabel) != null ? _i : tourPrevLabel;
|
|
934
|
+
const skipLabel = (_j = step.skipLabel) != null ? _j : tourSkipLabel;
|
|
929
935
|
const advanceStep = (hasTrigger) => {
|
|
930
936
|
var _a2;
|
|
931
937
|
const currentOrigIdx = validSteps[currentValidPos]._originalIdx;
|
|
@@ -939,6 +945,43 @@ var WalkthroughOverlay = ({
|
|
|
939
945
|
setPopoverPos(null);
|
|
940
946
|
const nextValidStep = validSteps[currentValidPos + 1];
|
|
941
947
|
const nextOrigIdx = hasTrigger && !nextValidStep ? currentOrigIdx + 1 : (_a2 = nextValidStep == null ? void 0 : nextValidStep._originalIdx) != null ? _a2 : currentOrigIdx + 1;
|
|
948
|
+
const shouldForceRecompute = !!step.forceRecompute;
|
|
949
|
+
if (shouldForceRecompute) {
|
|
950
|
+
const nextStepDef = activeTour.steps[nextOrigIdx];
|
|
951
|
+
if (nextStepDef) {
|
|
952
|
+
const nextElId = resolveElId(nextStepDef.el);
|
|
953
|
+
const SETTLE_DELAY = 150;
|
|
954
|
+
const doAdvance = () => {
|
|
955
|
+
setGlobalState((s) => ({
|
|
956
|
+
...s,
|
|
957
|
+
activeTour: { ...s.activeTour, currentStep: nextOrigIdx }
|
|
958
|
+
}));
|
|
959
|
+
};
|
|
960
|
+
const alreadyExists = document.getElementById(nextElId);
|
|
961
|
+
if (alreadyExists) {
|
|
962
|
+
setTimeout(() => doAdvance(), SETTLE_DELAY);
|
|
963
|
+
} else {
|
|
964
|
+
waitingForElsRef.current = true;
|
|
965
|
+
const observer = new MutationObserver(() => {
|
|
966
|
+
const found = document.getElementById(nextElId);
|
|
967
|
+
if (found) {
|
|
968
|
+
observer.disconnect();
|
|
969
|
+
waitingForElsRef.current = false;
|
|
970
|
+
setTimeout(() => doAdvance(), SETTLE_DELAY);
|
|
971
|
+
}
|
|
972
|
+
});
|
|
973
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
974
|
+
setTimeout(() => {
|
|
975
|
+
observer.disconnect();
|
|
976
|
+
if (waitingForElsRef.current) {
|
|
977
|
+
waitingForElsRef.current = false;
|
|
978
|
+
doAdvance();
|
|
979
|
+
}
|
|
980
|
+
}, 3e3);
|
|
981
|
+
}
|
|
982
|
+
return;
|
|
983
|
+
}
|
|
984
|
+
}
|
|
942
985
|
setGlobalState((s) => ({
|
|
943
986
|
...s,
|
|
944
987
|
activeTour: { ...s.activeTour, currentStep: nextOrigIdx }
|
|
@@ -946,6 +989,12 @@ var WalkthroughOverlay = ({
|
|
|
946
989
|
}
|
|
947
990
|
};
|
|
948
991
|
const next = () => {
|
|
992
|
+
var _a2;
|
|
993
|
+
const currentOrigIdx = validSteps[currentValidPos]._originalIdx;
|
|
994
|
+
const stepNextCb = (_a2 = activeTour.onStepNext) == null ? void 0 : _a2[currentOrigIdx];
|
|
995
|
+
if (typeof stepNextCb === "function") {
|
|
996
|
+
stepNextCb();
|
|
997
|
+
}
|
|
949
998
|
const hasTrigger = !!step.triggerElOnNext;
|
|
950
999
|
if (hasTrigger) {
|
|
951
1000
|
setPopoverHidden(true);
|
|
@@ -958,8 +1007,8 @@ var WalkthroughOverlay = ({
|
|
|
958
1007
|
triggerTarget.dispatchEvent(new MouseEvent("mouseup", { bubbles: true, cancelable: true, button: 0 }));
|
|
959
1008
|
triggerTarget.click();
|
|
960
1009
|
}
|
|
961
|
-
const
|
|
962
|
-
const nextOrigIdx =
|
|
1010
|
+
const currentOrigIdx2 = validSteps[currentValidPos]._originalIdx;
|
|
1011
|
+
const nextOrigIdx = currentOrigIdx2 + 1;
|
|
963
1012
|
const nextStepDef = activeTour.steps[nextOrigIdx];
|
|
964
1013
|
if (nextStepDef) {
|
|
965
1014
|
const nextElId = resolveElId(nextStepDef.el);
|
|
@@ -968,7 +1017,9 @@ var WalkthroughOverlay = ({
|
|
|
968
1017
|
const alreadyInValid = validSteps.some((s) => s._originalIdx === nextOrigIdx);
|
|
969
1018
|
const newValidSteps = alreadyInValid ? validSteps : [...validSteps, nextStepWithIdx].sort((a, b) => a._originalIdx - b._originalIdx);
|
|
970
1019
|
setValidSteps(newValidSteps);
|
|
971
|
-
|
|
1020
|
+
if (!step.forceRecompute) {
|
|
1021
|
+
skipNextRecomputeRef.current = true;
|
|
1022
|
+
}
|
|
972
1023
|
setGlobalState((s) => ({
|
|
973
1024
|
...s,
|
|
974
1025
|
activeTour: { ...s.activeTour, currentStep: nextOrigIdx }
|
|
@@ -1043,10 +1094,10 @@ var WalkthroughOverlay = ({
|
|
|
1043
1094
|
displayPosRef.current = currentValidPos;
|
|
1044
1095
|
}
|
|
1045
1096
|
const ds = displayStepRef.current;
|
|
1046
|
-
const dir = (
|
|
1047
|
-
const align = (
|
|
1048
|
-
const offsetX = (
|
|
1049
|
-
const offsetY = (
|
|
1097
|
+
const dir = (_k = popoverPos == null ? void 0 : popoverPos.dir) != null ? _k : "bottom";
|
|
1098
|
+
const align = (_l = popoverPos == null ? void 0 : popoverPos.align) != null ? _l : "start";
|
|
1099
|
+
const offsetX = (_m = popoverPos == null ? void 0 : popoverPos.offsetX) != null ? _m : 0;
|
|
1100
|
+
const offsetY = (_n = popoverPos == null ? void 0 : popoverPos.offsetY) != null ? _n : 0;
|
|
1050
1101
|
const anchorStyle = popoverReady ? {
|
|
1051
1102
|
position: "fixed",
|
|
1052
1103
|
top: rect.top,
|
|
@@ -1140,7 +1191,7 @@ var WalkthroughOverlay = ({
|
|
|
1140
1191
|
/* @__PURE__ */ jsxRuntime.jsxs(PopoverBody, { children: [
|
|
1141
1192
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "row", justifyContent: "space-between" }, children: [
|
|
1142
1193
|
pStep.title ? /* @__PURE__ */ jsxRuntime.jsx(PopoverTitle, { children: pStep.title }) : "",
|
|
1143
|
-
((
|
|
1194
|
+
((_o = pStep.isShowStep) != null ? _o : pIsShowStep) && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: "#a1a1aa", fontSize: "12px", fontWeight: "400" }, children: [
|
|
1144
1195
|
pDisplayCurrentStep,
|
|
1145
1196
|
"/",
|
|
1146
1197
|
pDisplayTotalSteps
|
|
@@ -1165,7 +1216,7 @@ var WalkthroughOverlay = ({
|
|
|
1165
1216
|
}
|
|
1166
1217
|
) }),
|
|
1167
1218
|
/* @__PURE__ */ jsxRuntime.jsxs(ButtonGroup, { children: [
|
|
1168
|
-
((
|
|
1219
|
+
((_p = pStep.isShowPrev) != null ? _p : pIsShowPrev) && pCurrentValidPos > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1169
1220
|
"button",
|
|
1170
1221
|
{
|
|
1171
1222
|
className: "wt-btn",
|