@tent-official/react-walkthrough 1.1.77 → 1.1.79

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.d.mts CHANGED
@@ -127,10 +127,24 @@ interface IResetWalkthroughOptions {
127
127
  /** List of walkthrough names to reset */
128
128
  walkthroughList?: string[];
129
129
  }
130
+ /**
131
+ * Options for the readElement function.
132
+ */
133
+ interface IReadElementOptions {
134
+ /** Optional AbortSignal to cancel waiting for the element */
135
+ signal?: AbortSignal;
136
+ }
130
137
  /**
131
138
  * Reset specified walkthroughs so they can be replayed without page refresh.
132
139
  */
133
140
  declare function resetWalkthrough(options?: IResetWalkthroughOptions): void;
141
+ /**
142
+ * Read (find) a DOM element by its ID.
143
+ * Returns immediately if the element already exists in the DOM.
144
+ * If not found, uses a MutationObserver to wait until it appears.
145
+ * Supports cancellation via AbortSignal.
146
+ */
147
+ declare function readElement(elementId: string, options?: IReadElementOptions): Promise<HTMLElement | null>;
134
148
  /**
135
149
  * Hook to register and control a walkthrough tour.
136
150
  */
@@ -141,4 +155,4 @@ declare function useWalkthrough(options: IUseWalkthroughOptions): IUseWalkthroug
141
155
  */
142
156
  declare function WalkthroughOverlay(props?: IWalkthroughOverlayProps): ReactPortal | null;
143
157
 
144
- export { type IResetWalkthroughOptions, type IStepDescription, type IUseWalkthroughOptions, type IUseWalkthroughReturn, type IWalkthroughOverlayProps, type IWalkthroughStep, type TDescriptionDirection, type TPopoverPosition, WalkthroughOverlay, resetWalkthrough, useWalkthrough };
158
+ export { type IReadElementOptions, type IResetWalkthroughOptions, type IStepDescription, type IUseWalkthroughOptions, type IUseWalkthroughReturn, type IWalkthroughOverlayProps, type IWalkthroughStep, type TDescriptionDirection, type TPopoverPosition, WalkthroughOverlay, readElement, resetWalkthrough, useWalkthrough };
package/dist/index.d.ts CHANGED
@@ -127,10 +127,24 @@ interface IResetWalkthroughOptions {
127
127
  /** List of walkthrough names to reset */
128
128
  walkthroughList?: string[];
129
129
  }
130
+ /**
131
+ * Options for the readElement function.
132
+ */
133
+ interface IReadElementOptions {
134
+ /** Optional AbortSignal to cancel waiting for the element */
135
+ signal?: AbortSignal;
136
+ }
130
137
  /**
131
138
  * Reset specified walkthroughs so they can be replayed without page refresh.
132
139
  */
133
140
  declare function resetWalkthrough(options?: IResetWalkthroughOptions): void;
141
+ /**
142
+ * Read (find) a DOM element by its ID.
143
+ * Returns immediately if the element already exists in the DOM.
144
+ * If not found, uses a MutationObserver to wait until it appears.
145
+ * Supports cancellation via AbortSignal.
146
+ */
147
+ declare function readElement(elementId: string, options?: IReadElementOptions): Promise<HTMLElement | null>;
134
148
  /**
135
149
  * Hook to register and control a walkthrough tour.
136
150
  */
@@ -141,4 +155,4 @@ declare function useWalkthrough(options: IUseWalkthroughOptions): IUseWalkthroug
141
155
  */
142
156
  declare function WalkthroughOverlay(props?: IWalkthroughOverlayProps): ReactPortal | null;
143
157
 
144
- export { type IResetWalkthroughOptions, type IStepDescription, type IUseWalkthroughOptions, type IUseWalkthroughReturn, type IWalkthroughOverlayProps, type IWalkthroughStep, type TDescriptionDirection, type TPopoverPosition, WalkthroughOverlay, resetWalkthrough, useWalkthrough };
158
+ export { type IReadElementOptions, type IResetWalkthroughOptions, type IStepDescription, type IUseWalkthroughOptions, type IUseWalkthroughReturn, type IWalkthroughOverlayProps, type IWalkthroughStep, type TDescriptionDirection, type TPopoverPosition, WalkthroughOverlay, readElement, resetWalkthrough, useWalkthrough };
package/dist/index.js CHANGED
@@ -68,6 +68,36 @@ var easeOutCubic = (t) => {
68
68
  var lerp = (a, b, t) => {
69
69
  return a + (b - a) * t;
70
70
  };
71
+ var resolveElId = (id) => typeof id === "string" && id.startsWith("#") ? id.slice(1) : id;
72
+ var readElement = (elementId, { signal } = {}) => {
73
+ return new Promise((resolve) => {
74
+ if (signal == null ? void 0 : signal.aborted) {
75
+ resolve(null);
76
+ return;
77
+ }
78
+ const id = resolveElId(elementId);
79
+ const el = document.getElementById(id);
80
+ if (el) {
81
+ resolve(el);
82
+ return;
83
+ }
84
+ const observer = new MutationObserver(() => {
85
+ const found = document.getElementById(id);
86
+ if (found) {
87
+ observer.disconnect();
88
+ resolve(found);
89
+ }
90
+ });
91
+ observer.observe(document.body, { childList: true, subtree: true });
92
+ if (signal) {
93
+ const onAbort = () => {
94
+ observer.disconnect();
95
+ resolve(null);
96
+ };
97
+ signal.addEventListener("abort", onAbort, { once: true });
98
+ }
99
+ });
100
+ };
71
101
  var STYLE_ID = "wt-keyframes";
72
102
  var injectKeyframes = () => {
73
103
  if (typeof document === "undefined") return;
@@ -166,7 +196,6 @@ var StepCounter = react.forwardRef(({ style, children, ...props }, ref) => /* @_
166
196
  ...style
167
197
  }, ...props, children }));
168
198
  var ButtonGroup = react.forwardRef(({ style, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, style: { display: "flex", gap: 6, ...style }, ...props, children }));
169
- var resolveElId = (id) => typeof id === "string" && id.startsWith("#") ? id.slice(1) : id;
170
199
  var _overlayInstanceCounter = 0;
171
200
  var _activeOverlayId = null;
172
201
  var useWalkthrough = ({
@@ -562,16 +591,42 @@ var WalkthroughOverlay = ({
562
591
  const [popoverHidden, setPopoverHidden] = react.useState(false);
563
592
  const displayStepRef = react.useRef(null);
564
593
  const displayPosRef = react.useRef(null);
594
+ const delayDoneForRef = react.useRef(null);
595
+ const [isDelaying, setIsDelaying] = react.useState(false);
596
+ const currentTourName = (_a = activeTour == null ? void 0 : activeTour.name) != null ? _a : null;
597
+ react.useEffect(() => {
598
+ var _a2;
599
+ if (!activeTour) {
600
+ delayDoneForRef.current = null;
601
+ setIsDelaying(false);
602
+ return;
603
+ }
604
+ if (delayDoneForRef.current === activeTour.name) return;
605
+ const ms = (_a2 = activeTour.delay) != null ? _a2 : 0;
606
+ if (ms <= 0) {
607
+ delayDoneForRef.current = activeTour.name;
608
+ return;
609
+ }
610
+ setIsDelaying(true);
611
+ const timer = setTimeout(() => {
612
+ delayDoneForRef.current = activeTour.name;
613
+ setIsDelaying(false);
614
+ }, ms);
615
+ return () => clearTimeout(timer);
616
+ }, [currentTourName, activeTour]);
565
617
  const [validSteps, setValidSteps] = react.useState([]);
566
618
  const waitingForElsRef = react.useRef(false);
619
+ const elReadyRef = react.useRef(false);
567
620
  react.useEffect(() => {
568
- var _a2, _b2;
569
- if (!activeTour) {
621
+ var _a2, _b2, _c2;
622
+ if (!activeTour || isDelaying) {
570
623
  setValidSteps([]);
571
624
  waitingForElsRef.current = false;
625
+ elReadyRef.current = false;
572
626
  return;
573
627
  }
574
628
  waitingForElsRef.current = true;
629
+ const abortController = new AbortController();
575
630
  const compute = () => activeTour.steps.map((s, i) => ({ ...s, _originalIdx: i })).filter((s) => document.getElementById(resolveElId(s.el)));
576
631
  const found = compute();
577
632
  if (found.length > 0) {
@@ -580,71 +635,54 @@ var WalkthroughOverlay = ({
580
635
  if (currentStepInFound) {
581
636
  setValidSteps(found);
582
637
  waitingForElsRef.current = false;
638
+ elReadyRef.current = true;
583
639
  return;
584
640
  }
585
641
  setValidSteps(found);
642
+ elReadyRef.current = true;
586
643
  const currentStepEl = (_b2 = activeTour.steps[currentStepIdx]) == null ? void 0 : _b2.el;
587
644
  if (!currentStepEl) {
588
645
  waitingForElsRef.current = false;
589
646
  return;
590
647
  }
591
- const observer2 = new MutationObserver(() => {
592
- const el = document.getElementById(resolveElId(currentStepEl));
593
- if (el) {
648
+ readElement(currentStepEl, { signal: abortController.signal }).then((el) => {
649
+ if (el && !abortController.signal.aborted) {
594
650
  waitingForElsRef.current = false;
595
651
  setValidSteps(compute());
596
- observer2.disconnect();
597
652
  }
598
653
  });
599
- observer2.observe(document.body, { childList: true, subtree: true });
600
654
  return () => {
601
- observer2.disconnect();
655
+ abortController.abort();
602
656
  waitingForElsRef.current = false;
603
657
  };
604
658
  }
605
659
  setValidSteps([]);
606
- const observer = new MutationObserver(() => {
607
- const updated = compute();
608
- if (updated.length > 0) {
609
- waitingForElsRef.current = false;
610
- setValidSteps(updated);
611
- observer.disconnect();
660
+ const firstStepEl = (_c2 = activeTour.steps[0]) == null ? void 0 : _c2.el;
661
+ if (!firstStepEl) {
662
+ waitingForElsRef.current = false;
663
+ elReadyRef.current = true;
664
+ return;
665
+ }
666
+ readElement(firstStepEl, { signal: abortController.signal }).then((el) => {
667
+ if (el && !abortController.signal.aborted) {
668
+ const updated = compute();
669
+ if (updated.length > 0) {
670
+ waitingForElsRef.current = false;
671
+ elReadyRef.current = true;
672
+ setValidSteps(updated);
673
+ }
612
674
  }
613
675
  });
614
- observer.observe(document.body, { childList: true, subtree: true });
615
676
  return () => {
616
- observer.disconnect();
677
+ abortController.abort();
617
678
  waitingForElsRef.current = false;
618
679
  };
619
- }, [activeTour]);
620
- const currentOriginalIdx = (_a = activeTour == null ? void 0 : activeTour.currentStep) != null ? _a : 0;
680
+ }, [activeTour, isDelaying]);
681
+ const currentOriginalIdx = (_b = activeTour == null ? void 0 : activeTour.currentStep) != null ? _b : 0;
621
682
  const currentValidPos = validSteps.findIndex(
622
683
  (s) => s._originalIdx === currentOriginalIdx
623
684
  );
624
685
  const rawStep = currentValidPos !== -1 ? validSteps[currentValidPos] : null;
625
- const delayDoneForRef = react.useRef(null);
626
- const [isDelaying, setIsDelaying] = react.useState(false);
627
- const currentTourName = (_b = activeTour == null ? void 0 : activeTour.name) != null ? _b : null;
628
- react.useEffect(() => {
629
- var _a2;
630
- if (!activeTour) {
631
- delayDoneForRef.current = null;
632
- setIsDelaying(false);
633
- return;
634
- }
635
- if (delayDoneForRef.current === activeTour.name) return;
636
- const ms = (_a2 = activeTour.delay) != null ? _a2 : 0;
637
- if (ms <= 0) {
638
- delayDoneForRef.current = activeTour.name;
639
- return;
640
- }
641
- setIsDelaying(true);
642
- const timer = setTimeout(() => {
643
- delayDoneForRef.current = activeTour.name;
644
- setIsDelaying(false);
645
- }, ms);
646
- return () => clearTimeout(timer);
647
- }, [currentTourName, activeTour]);
648
686
  const step = isDelaying ? null : rawStep;
649
687
  const tourAnimationSpeed = (_c = activeTour == null ? void 0 : activeTour.animationSpeed) != null ? _c : 350;
650
688
  const { rect, isAnimating } = useAnimatedRect(step, tourAnimationSpeed, activeTour == null ? void 0 : activeTour.containerElement, !!activeTour, activeTour == null ? void 0 : activeTour.name);
@@ -657,6 +695,8 @@ var WalkthroughOverlay = ({
657
695
  }, [activeTour, rect]);
658
696
  react.useEffect(() => {
659
697
  if (!activeTour) return;
698
+ if (isDelaying) return;
699
+ if (!elReadyRef.current) return;
660
700
  if (currentValidPos !== -1) return;
661
701
  if (waitingForElsRef.current) return;
662
702
  if (validSteps.length === 0) {
@@ -676,6 +716,7 @@ var WalkthroughOverlay = ({
676
716
  }
677
717
  }, [
678
718
  activeTour,
719
+ isDelaying,
679
720
  currentValidPos,
680
721
  currentOriginalIdx,
681
722
  validSteps,
@@ -1013,6 +1054,7 @@ var WalkthroughOverlay = ({
1013
1054
  };
1014
1055
 
1015
1056
  exports.WalkthroughOverlay = WalkthroughOverlay;
1057
+ exports.readElement = readElement;
1016
1058
  exports.resetWalkthrough = resetWalkthrough;
1017
1059
  exports.useWalkthrough = useWalkthrough;
1018
1060
  //# sourceMappingURL=index.js.map