@matthesketh/react-guidetour 1.0.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/dist/index.mjs ADDED
@@ -0,0 +1,2127 @@
1
+ // src/literals/index.ts
2
+ var ACTIONS = {
3
+ INIT: "init",
4
+ START: "start",
5
+ STOP: "stop",
6
+ RESET: "reset",
7
+ PREV: "prev",
8
+ NEXT: "next",
9
+ GO: "go",
10
+ CLOSE: "close",
11
+ SKIP: "skip",
12
+ UPDATE: "update"
13
+ };
14
+ var EVENTS = {
15
+ TOUR_START: "tour:start",
16
+ STEP_BEFORE: "step:before",
17
+ BEACON: "beacon",
18
+ TOOLTIP: "tooltip",
19
+ STEP_AFTER: "step:after",
20
+ TOUR_END: "tour:end",
21
+ TOUR_STATUS: "tour:status",
22
+ TARGET_NOT_FOUND: "error:target_not_found",
23
+ ERROR: "error"
24
+ };
25
+ var LIFECYCLE = {
26
+ INIT: "init",
27
+ READY: "ready",
28
+ BEACON: "beacon",
29
+ TOOLTIP: "tooltip",
30
+ COMPLETE: "complete",
31
+ ERROR: "error"
32
+ };
33
+ var ORIGIN = {
34
+ BUTTON_CLOSE: "button_close",
35
+ BUTTON_PRIMARY: "button_primary",
36
+ KEYBOARD: "keyboard",
37
+ OVERLAY: "overlay"
38
+ };
39
+ var STATUS = {
40
+ IDLE: "idle",
41
+ READY: "ready",
42
+ WAITING: "waiting",
43
+ RUNNING: "running",
44
+ PAUSED: "paused",
45
+ SKIPPED: "skipped",
46
+ FINISHED: "finished",
47
+ ERROR: "error"
48
+ };
49
+
50
+ // src/components/index.tsx
51
+ import { useCallback as useCallback4, useEffect as useEffect5, useRef as useRef5, useState as useState2 } from "react";
52
+ import isEqual from "@gilbarbara/deep-equal";
53
+ import is6 from "is-lite";
54
+ import treeChanges3 from "tree-changes";
55
+
56
+ // src/modules/dom.ts
57
+ import scroll from "scroll";
58
+ import scrollParent from "scrollparent";
59
+ function canUseDOM() {
60
+ var _a;
61
+ return !!(typeof window !== "undefined" && ((_a = window.document) == null ? void 0 : _a.createElement));
62
+ }
63
+ function getClientRect(element) {
64
+ if (!element) {
65
+ return null;
66
+ }
67
+ return element.getBoundingClientRect();
68
+ }
69
+ function getDocumentHeight(median = false) {
70
+ const { body, documentElement } = document;
71
+ if (!body || !documentElement) {
72
+ return 0;
73
+ }
74
+ if (median) {
75
+ const heights = [
76
+ body.scrollHeight,
77
+ body.offsetHeight,
78
+ documentElement.clientHeight,
79
+ documentElement.scrollHeight,
80
+ documentElement.offsetHeight
81
+ ].sort((a, b) => a - b);
82
+ const middle = Math.floor(heights.length / 2);
83
+ if (heights.length % 2 === 0) {
84
+ return (heights[middle - 1] + heights[middle]) / 2;
85
+ }
86
+ return heights[middle];
87
+ }
88
+ return Math.max(
89
+ body.scrollHeight,
90
+ body.offsetHeight,
91
+ documentElement.clientHeight,
92
+ documentElement.scrollHeight,
93
+ documentElement.offsetHeight
94
+ );
95
+ }
96
+ function getElement(element) {
97
+ if (typeof element === "string") {
98
+ try {
99
+ return document.querySelector(element);
100
+ } catch (error) {
101
+ if (process.env.NODE_ENV !== "production") {
102
+ console.error(error);
103
+ }
104
+ return null;
105
+ }
106
+ }
107
+ return element;
108
+ }
109
+ function getStyleComputedProperty(el) {
110
+ if (!el || el.nodeType !== 1) {
111
+ return null;
112
+ }
113
+ return getComputedStyle(el);
114
+ }
115
+ function getScrollParent(element, skipFix, forListener) {
116
+ if (!element) {
117
+ return scrollDocument();
118
+ }
119
+ const parent = scrollParent(element);
120
+ if (parent) {
121
+ if (parent.isSameNode(scrollDocument())) {
122
+ if (forListener) {
123
+ return document;
124
+ }
125
+ return scrollDocument();
126
+ }
127
+ const hasScrolling = parent.scrollHeight > parent.offsetHeight;
128
+ if (!hasScrolling && !skipFix) {
129
+ parent.style.overflow = "initial";
130
+ return scrollDocument();
131
+ }
132
+ }
133
+ return parent;
134
+ }
135
+ function hasCustomScrollParent(element, skipFix) {
136
+ if (!element) {
137
+ return false;
138
+ }
139
+ const parent = getScrollParent(element, skipFix);
140
+ return parent ? !parent.isSameNode(scrollDocument()) : false;
141
+ }
142
+ function hasCustomOffsetParent(element) {
143
+ return element.offsetParent !== document.body;
144
+ }
145
+ function hasPosition(el, type = "fixed") {
146
+ if (!el || !(el instanceof HTMLElement)) {
147
+ return false;
148
+ }
149
+ const { nodeName } = el;
150
+ const styles = getStyleComputedProperty(el);
151
+ if (nodeName === "BODY" || nodeName === "HTML") {
152
+ return false;
153
+ }
154
+ if (styles && styles.position === type) {
155
+ return true;
156
+ }
157
+ if (!el.parentNode) {
158
+ return false;
159
+ }
160
+ return hasPosition(el.parentNode, type);
161
+ }
162
+ function isElementVisible(element) {
163
+ var _a;
164
+ if (!element) {
165
+ return false;
166
+ }
167
+ let parentElement = element;
168
+ while (parentElement) {
169
+ if (parentElement === document.body) {
170
+ break;
171
+ }
172
+ if (parentElement instanceof HTMLElement) {
173
+ const { display, visibility } = getComputedStyle(parentElement);
174
+ if (display === "none" || visibility === "hidden") {
175
+ return false;
176
+ }
177
+ }
178
+ parentElement = (_a = parentElement.parentElement) != null ? _a : null;
179
+ }
180
+ return true;
181
+ }
182
+ function getElementPosition(element, offset, skipFix) {
183
+ var _a, _b, _c;
184
+ const elementRect = getClientRect(element);
185
+ const parent = getScrollParent(element, skipFix);
186
+ const hasScrollParent = hasCustomScrollParent(element, skipFix);
187
+ const isFixedTarget = hasPosition(element);
188
+ let parentTop = 0;
189
+ let top = (_a = elementRect == null ? void 0 : elementRect.top) != null ? _a : 0;
190
+ if (hasScrollParent && isFixedTarget) {
191
+ const offsetTop = (_b = element == null ? void 0 : element.offsetTop) != null ? _b : 0;
192
+ const parentScrollTop = (_c = parent == null ? void 0 : parent.scrollTop) != null ? _c : 0;
193
+ top = offsetTop - parentScrollTop;
194
+ } else if (parent instanceof HTMLElement) {
195
+ parentTop = parent.scrollTop;
196
+ if (!hasScrollParent && !hasPosition(element)) {
197
+ top += parentTop;
198
+ }
199
+ if (!parent.isSameNode(scrollDocument())) {
200
+ top += scrollDocument().scrollTop;
201
+ }
202
+ }
203
+ return Math.floor(top - offset);
204
+ }
205
+ function getScrollTo(element, offset, skipFix) {
206
+ var _a;
207
+ if (!element) {
208
+ return 0;
209
+ }
210
+ const { offsetTop = 0, scrollTop = 0 } = (_a = scrollParent(element)) != null ? _a : {};
211
+ let top = element.getBoundingClientRect().top + scrollTop;
212
+ if (!!offsetTop && (hasCustomScrollParent(element, skipFix) || hasCustomOffsetParent(element))) {
213
+ top -= offsetTop;
214
+ }
215
+ const output = Math.floor(top - offset);
216
+ return output < 0 ? 0 : output;
217
+ }
218
+ function scrollDocument() {
219
+ var _a;
220
+ return (_a = document.scrollingElement) != null ? _a : document.documentElement;
221
+ }
222
+ function scrollTo(value, options) {
223
+ const { duration, element } = options;
224
+ return new Promise((resolve, reject) => {
225
+ const { scrollTop } = element;
226
+ const limit = value > scrollTop ? value - scrollTop : scrollTop - value;
227
+ scroll.top(element, value, { duration: limit < 100 ? 50 : duration }, (error) => {
228
+ if (error && error.message !== "Element already at target scroll position") {
229
+ return reject(error);
230
+ }
231
+ return resolve();
232
+ });
233
+ });
234
+ }
235
+
236
+ // src/modules/helpers.tsx
237
+ import { cloneElement, isValidElement } from "react";
238
+ import innerText from "react-innertext";
239
+ import is from "is-lite";
240
+ function isSafari() {
241
+ if (typeof window === "undefined" || typeof navigator === "undefined") {
242
+ return false;
243
+ }
244
+ return /(Version\/([\d._]+).*Safari|CriOS|FxiOS| Mobile\/)/.test(navigator.userAgent);
245
+ }
246
+ function getObjectType(value) {
247
+ return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
248
+ }
249
+ function getReactNodeText(input, options = {}) {
250
+ const { defaultValue, step, steps } = options;
251
+ let text = innerText(input);
252
+ if (!text) {
253
+ if (isValidElement(input) && !Object.values(input.props).length && getObjectType(input.type) === "function") {
254
+ const component = input.type({});
255
+ text = getReactNodeText(component, options);
256
+ } else {
257
+ text = innerText(defaultValue);
258
+ }
259
+ } else if ((text.includes("{step}") || text.includes("{steps}")) && step && steps) {
260
+ text = text.replace("{step}", step.toString()).replace("{steps}", steps.toString());
261
+ }
262
+ return text;
263
+ }
264
+ function hasValidKeys(object, keys) {
265
+ if (!is.plainObject(object) || !is.array(keys)) {
266
+ return false;
267
+ }
268
+ return Object.keys(object).every((d) => keys.includes(d));
269
+ }
270
+ function hexToRGB(hex) {
271
+ const shorthandRegex = /^#?([\da-f])([\da-f])([\da-f])$/i;
272
+ const properHex = hex.replace(shorthandRegex, (_m, r, g, b) => r + r + g + g + b + b);
273
+ const result = /^#?([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i.exec(properHex);
274
+ return result ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)] : [];
275
+ }
276
+ function hideBeacon(step) {
277
+ return step.disableBeacon || step.placement === "center";
278
+ }
279
+ function log({ data, debug = false, title, warn = false }) {
280
+ const logFn = warn ? console.warn || console.error : console.log;
281
+ if (debug) {
282
+ if (title && data) {
283
+ console.groupCollapsed(
284
+ `%creact-guidetour: ${title}`,
285
+ "color: #ff0044; font-weight: bold; font-size: 12px;"
286
+ );
287
+ if (Array.isArray(data)) {
288
+ data.forEach((d) => {
289
+ if (is.plainObject(d) && d.key) {
290
+ logFn.apply(console, [d.key, d.value]);
291
+ } else {
292
+ logFn.apply(console, [d]);
293
+ }
294
+ });
295
+ } else {
296
+ logFn.apply(console, [data]);
297
+ }
298
+ console.groupEnd();
299
+ } else {
300
+ console.error("Missing title or data props");
301
+ }
302
+ }
303
+ }
304
+ function noop() {
305
+ return void 0;
306
+ }
307
+ function objectKeys(input) {
308
+ return Object.keys(input);
309
+ }
310
+ function omit(input, ...filter) {
311
+ if (!is.plainObject(input)) {
312
+ throw new TypeError("Expected an object");
313
+ }
314
+ const output = {};
315
+ for (const key in input) {
316
+ if ({}.hasOwnProperty.call(input, key)) {
317
+ if (!filter.includes(key)) {
318
+ output[key] = input[key];
319
+ }
320
+ }
321
+ }
322
+ return output;
323
+ }
324
+ function pick(input, ...filter) {
325
+ if (!is.plainObject(input)) {
326
+ throw new TypeError("Expected an object");
327
+ }
328
+ if (!filter.length) {
329
+ return input;
330
+ }
331
+ const output = {};
332
+ for (const key in input) {
333
+ if ({}.hasOwnProperty.call(input, key)) {
334
+ if (filter.includes(key)) {
335
+ output[key] = input[key];
336
+ }
337
+ }
338
+ }
339
+ return output;
340
+ }
341
+ function replaceLocaleContent(input, step, steps) {
342
+ const replacer = (text) => text.replace("{step}", String(step)).replace("{steps}", String(steps));
343
+ if (getObjectType(input) === "string") {
344
+ return replacer(input);
345
+ }
346
+ if (!isValidElement(input)) {
347
+ return input;
348
+ }
349
+ const { children } = input.props;
350
+ if (getObjectType(children) === "string" && children.includes("{step}")) {
351
+ return cloneElement(input, {
352
+ children: replacer(children)
353
+ });
354
+ }
355
+ if (Array.isArray(children)) {
356
+ return cloneElement(input, {
357
+ children: children.map((child) => {
358
+ if (typeof child === "string") {
359
+ return replacer(child);
360
+ }
361
+ return replaceLocaleContent(child, step, steps);
362
+ })
363
+ });
364
+ }
365
+ if (getObjectType(input.type) === "function" && !Object.values(input.props).length) {
366
+ const component = input.type({});
367
+ return replaceLocaleContent(component, step, steps);
368
+ }
369
+ return input;
370
+ }
371
+ function shouldScroll(options) {
372
+ const { isFirstStep, lifecycle, previousLifecycle, scrollToFirstStep, step, target } = options;
373
+ return !step.disableScrolling && (!isFirstStep || scrollToFirstStep || lifecycle === LIFECYCLE.TOOLTIP) && step.placement !== "center" && (!step.isFixed || !hasPosition(target)) && // fixed steps don't need to scroll
374
+ previousLifecycle !== lifecycle && [LIFECYCLE.BEACON, LIFECYCLE.TOOLTIP].includes(lifecycle);
375
+ }
376
+
377
+ // src/modules/step.ts
378
+ import deepmerge2 from "deepmerge";
379
+ import is2 from "is-lite";
380
+
381
+ // src/defaults.ts
382
+ var defaultFloaterProps = {
383
+ wrapperOptions: {
384
+ offset: -18,
385
+ position: true
386
+ }
387
+ };
388
+ var defaultLocale = {
389
+ back: "Back",
390
+ close: "Close",
391
+ last: "Last",
392
+ next: "Next",
393
+ nextLabelWithProgress: "Next (Step {step} of {steps})",
394
+ open: "Open the dialog",
395
+ skip: "Skip"
396
+ };
397
+ var defaultStep = {
398
+ event: "click",
399
+ placement: "bottom",
400
+ offset: 10,
401
+ disableBeacon: false,
402
+ disableCloseOnEsc: false,
403
+ disableOverlay: false,
404
+ disableOverlayClose: false,
405
+ disableScrollParentFix: false,
406
+ disableScrolling: false,
407
+ hideBackButton: false,
408
+ hideCloseButton: false,
409
+ hideFooter: false,
410
+ isFixed: false,
411
+ locale: defaultLocale,
412
+ showProgress: false,
413
+ showSkipButton: false,
414
+ spotlightClicks: false,
415
+ spotlightPadding: 10
416
+ };
417
+ var defaultProps = {
418
+ continuous: false,
419
+ debug: false,
420
+ disableCloseOnEsc: false,
421
+ disableOverlay: false,
422
+ disableOverlayClose: false,
423
+ disableScrolling: false,
424
+ disableScrollParentFix: false,
425
+ getHelpers: noop(),
426
+ hideBackButton: false,
427
+ run: true,
428
+ scrollOffset: 20,
429
+ scrollDuration: 300,
430
+ scrollToFirstStep: false,
431
+ showSkipButton: false,
432
+ showProgress: false,
433
+ spotlightClicks: false,
434
+ spotlightPadding: 10,
435
+ steps: []
436
+ };
437
+
438
+ // src/styles.ts
439
+ import deepmerge from "deepmerge";
440
+ var defaultOptions = {
441
+ arrowColor: "#fff",
442
+ backgroundColor: "#fff",
443
+ beaconSize: 36,
444
+ overlayColor: "rgba(0, 0, 0, 0.5)",
445
+ primaryColor: "#f04",
446
+ spotlightShadow: "0 0 15px rgba(0, 0, 0, 0.5)",
447
+ textColor: "#333",
448
+ width: 380,
449
+ zIndex: 100
450
+ };
451
+ var buttonBase = {
452
+ backgroundColor: "transparent",
453
+ border: 0,
454
+ borderRadius: 0,
455
+ color: "#555",
456
+ cursor: "pointer",
457
+ fontSize: 16,
458
+ lineHeight: 1,
459
+ padding: 8,
460
+ WebkitAppearance: "none"
461
+ };
462
+ var spotlight = {
463
+ borderRadius: 4,
464
+ position: "absolute"
465
+ };
466
+ function getStyles(props, step) {
467
+ var _a, _b, _c, _d, _e;
468
+ const { floaterProps, styles } = props;
469
+ const mergedFloaterProps = deepmerge((_a = step.floaterProps) != null ? _a : {}, floaterProps != null ? floaterProps : {});
470
+ const mergedStyles = deepmerge(styles != null ? styles : {}, (_b = step.styles) != null ? _b : {});
471
+ const options = deepmerge(defaultOptions, mergedStyles.options || {});
472
+ const hideBeacon2 = step.placement === "center" || step.disableBeacon;
473
+ let { width } = options;
474
+ if (window.innerWidth > 480) {
475
+ width = 380;
476
+ }
477
+ if ("width" in options) {
478
+ width = typeof options.width === "number" && window.innerWidth < options.width ? window.innerWidth - 30 : options.width;
479
+ }
480
+ const overlay = {
481
+ bottom: 0,
482
+ left: 0,
483
+ overflow: "hidden",
484
+ position: "absolute",
485
+ right: 0,
486
+ top: 0,
487
+ zIndex: options.zIndex
488
+ };
489
+ const defaultStyles = {
490
+ beacon: {
491
+ ...buttonBase,
492
+ display: hideBeacon2 ? "none" : "inline-block",
493
+ height: options.beaconSize,
494
+ position: "relative",
495
+ width: options.beaconSize,
496
+ zIndex: options.zIndex
497
+ },
498
+ beaconInner: {
499
+ animation: "joyride-beacon-inner 1.2s infinite ease-in-out",
500
+ backgroundColor: options.primaryColor,
501
+ borderRadius: "50%",
502
+ display: "block",
503
+ height: "50%",
504
+ left: "50%",
505
+ opacity: 0.7,
506
+ position: "absolute",
507
+ top: "50%",
508
+ transform: "translate(-50%, -50%)",
509
+ width: "50%"
510
+ },
511
+ beaconOuter: {
512
+ animation: "joyride-beacon-outer 1.2s infinite ease-in-out",
513
+ backgroundColor: `rgba(${hexToRGB(options.primaryColor).join(",")}, 0.2)`,
514
+ border: `2px solid ${options.primaryColor}`,
515
+ borderRadius: "50%",
516
+ boxSizing: "border-box",
517
+ display: "block",
518
+ height: "100%",
519
+ left: 0,
520
+ opacity: 0.9,
521
+ position: "absolute",
522
+ top: 0,
523
+ transformOrigin: "center",
524
+ width: "100%"
525
+ },
526
+ tooltip: {
527
+ backgroundColor: options.backgroundColor,
528
+ borderRadius: 5,
529
+ boxSizing: "border-box",
530
+ color: options.textColor,
531
+ fontSize: 16,
532
+ maxWidth: "100%",
533
+ padding: 15,
534
+ position: "relative",
535
+ width
536
+ },
537
+ tooltipContainer: {
538
+ lineHeight: 1.4,
539
+ textAlign: "center"
540
+ },
541
+ tooltipTitle: {
542
+ fontSize: 18,
543
+ margin: 0
544
+ },
545
+ tooltipContent: {
546
+ padding: "20px 10px"
547
+ },
548
+ tooltipFooter: {
549
+ alignItems: "center",
550
+ display: "flex",
551
+ justifyContent: "flex-end",
552
+ marginTop: 15
553
+ },
554
+ tooltipFooterSpacer: {
555
+ flex: 1
556
+ },
557
+ buttonNext: {
558
+ ...buttonBase,
559
+ backgroundColor: options.primaryColor,
560
+ borderRadius: 4,
561
+ color: "#fff"
562
+ },
563
+ buttonBack: {
564
+ ...buttonBase,
565
+ color: options.primaryColor,
566
+ marginLeft: "auto",
567
+ marginRight: 5
568
+ },
569
+ buttonClose: {
570
+ ...buttonBase,
571
+ color: options.textColor,
572
+ height: 14,
573
+ padding: 15,
574
+ position: "absolute",
575
+ right: 0,
576
+ top: 0,
577
+ width: 14
578
+ },
579
+ buttonSkip: {
580
+ ...buttonBase,
581
+ color: options.textColor,
582
+ fontSize: 14
583
+ },
584
+ overlay: {
585
+ ...overlay,
586
+ backgroundColor: options.overlayColor,
587
+ mixBlendMode: "hard-light"
588
+ },
589
+ overlayLegacy: {
590
+ ...overlay
591
+ },
592
+ overlayLegacyCenter: {
593
+ ...overlay,
594
+ backgroundColor: options.overlayColor
595
+ },
596
+ spotlight: {
597
+ ...spotlight,
598
+ backgroundColor: "gray"
599
+ },
600
+ spotlightLegacy: {
601
+ ...spotlight,
602
+ boxShadow: `0 0 0 9999px ${options.overlayColor}, ${options.spotlightShadow}`
603
+ },
604
+ floaterStyles: {
605
+ arrow: {
606
+ color: (_e = (_d = (_c = mergedFloaterProps == null ? void 0 : mergedFloaterProps.styles) == null ? void 0 : _c.arrow) == null ? void 0 : _d.color) != null ? _e : options.arrowColor
607
+ },
608
+ options: {
609
+ zIndex: options.zIndex + 100
610
+ }
611
+ },
612
+ options
613
+ };
614
+ return deepmerge(defaultStyles, mergedStyles);
615
+ }
616
+
617
+ // src/modules/step.ts
618
+ function getTourProps(props) {
619
+ return pick(
620
+ props,
621
+ "beaconComponent",
622
+ "disableCloseOnEsc",
623
+ "disableOverlay",
624
+ "disableOverlayClose",
625
+ "disableScrolling",
626
+ "disableScrollParentFix",
627
+ "floaterProps",
628
+ "hideBackButton",
629
+ "hideCloseButton",
630
+ "locale",
631
+ "showProgress",
632
+ "showSkipButton",
633
+ "spotlightClicks",
634
+ "spotlightPadding",
635
+ "styles",
636
+ "tooltipComponent"
637
+ );
638
+ }
639
+ function getMergedStep(props, currentStep) {
640
+ var _a, _b, _c, _d, _e, _f, _g;
641
+ const step = currentStep != null ? currentStep : {};
642
+ const mergedStep = deepmerge2.all([defaultStep, getTourProps(props), step], {
643
+ isMergeableObject: is2.plainObject
644
+ });
645
+ const mergedStyles = getStyles(props, mergedStep);
646
+ const scrollParent2 = hasCustomScrollParent(
647
+ getElement(mergedStep.target),
648
+ mergedStep.disableScrollParentFix
649
+ );
650
+ const floaterProps = deepmerge2.all([
651
+ defaultFloaterProps,
652
+ (_a = props.floaterProps) != null ? _a : {},
653
+ (_b = mergedStep.floaterProps) != null ? _b : {}
654
+ ]);
655
+ floaterProps.offset = mergedStep.offset;
656
+ floaterProps.styles = deepmerge2((_c = floaterProps.styles) != null ? _c : {}, mergedStyles.floaterStyles);
657
+ floaterProps.offset += (_e = (_d = props.spotlightPadding) != null ? _d : mergedStep.spotlightPadding) != null ? _e : 0;
658
+ if (mergedStep.placementBeacon && floaterProps.wrapperOptions) {
659
+ floaterProps.wrapperOptions.placement = mergedStep.placementBeacon;
660
+ }
661
+ if (scrollParent2 && ((_f = floaterProps.modifiers) == null ? void 0 : _f.preventOverflow)) {
662
+ floaterProps.modifiers.preventOverflow.options = {
663
+ ...floaterProps.modifiers.preventOverflow.options,
664
+ boundary: "window"
665
+ };
666
+ }
667
+ return {
668
+ ...mergedStep,
669
+ locale: deepmerge2.all([defaultLocale, (_g = props.locale) != null ? _g : {}, mergedStep.locale || {}]),
670
+ floaterProps,
671
+ styles: omit(mergedStyles, "floaterStyles")
672
+ };
673
+ }
674
+ function validateStep(step, debug = false) {
675
+ if (!is2.plainObject(step)) {
676
+ log({
677
+ title: "validateStep",
678
+ data: "step must be an object",
679
+ warn: true,
680
+ debug
681
+ });
682
+ return false;
683
+ }
684
+ if (!step.target) {
685
+ log({
686
+ title: "validateStep",
687
+ data: "target is missing from the step",
688
+ warn: true,
689
+ debug
690
+ });
691
+ return false;
692
+ }
693
+ return true;
694
+ }
695
+ function validateSteps(steps, debug = false) {
696
+ if (!is2.array(steps)) {
697
+ log({
698
+ title: "validateSteps",
699
+ data: "steps must be an array",
700
+ warn: true,
701
+ debug
702
+ });
703
+ return false;
704
+ }
705
+ return steps.every((d) => validateStep(d, debug));
706
+ }
707
+
708
+ // src/modules/store.ts
709
+ import is3 from "is-lite";
710
+ var defaultState = {
711
+ action: "init",
712
+ controlled: false,
713
+ index: 0,
714
+ lifecycle: LIFECYCLE.INIT,
715
+ origin: null,
716
+ size: 0,
717
+ status: STATUS.IDLE
718
+ };
719
+ var validKeys = objectKeys(omit(defaultState, "controlled", "size"));
720
+ var Store = class {
721
+ constructor(options) {
722
+ this.data = /* @__PURE__ */ new Map();
723
+ this.store = /* @__PURE__ */ new Map();
724
+ this.addListener = (listener) => {
725
+ this.listener = listener;
726
+ };
727
+ this.setSteps = (steps) => {
728
+ const { size, status } = this.getState();
729
+ const state = {
730
+ size: steps.length,
731
+ status
732
+ };
733
+ this.data.set("steps", steps);
734
+ if (status === STATUS.WAITING && !size && steps.length) {
735
+ state.status = STATUS.RUNNING;
736
+ }
737
+ this.setState(state);
738
+ };
739
+ this.getPopper = (name) => {
740
+ if (name === "beacon") {
741
+ return this.beaconPopper;
742
+ }
743
+ return this.tooltipPopper;
744
+ };
745
+ this.setPopper = (name, popper) => {
746
+ if (name === "beacon") {
747
+ this.beaconPopper = popper;
748
+ } else {
749
+ this.tooltipPopper = popper;
750
+ }
751
+ };
752
+ this.cleanupPoppers = () => {
753
+ this.beaconPopper = null;
754
+ this.tooltipPopper = null;
755
+ };
756
+ this.close = (origin = null) => {
757
+ const { index, status } = this.getState();
758
+ if (status !== STATUS.RUNNING) {
759
+ return;
760
+ }
761
+ this.setState({
762
+ ...this.getNextState({ action: ACTIONS.CLOSE, index: index + 1, origin })
763
+ });
764
+ };
765
+ this.go = (nextIndex) => {
766
+ const { controlled, status } = this.getState();
767
+ if (controlled || status !== STATUS.RUNNING) {
768
+ return;
769
+ }
770
+ const step = this.getSteps()[nextIndex];
771
+ this.setState({
772
+ ...this.getNextState({ action: ACTIONS.GO, index: nextIndex }),
773
+ status: step ? status : STATUS.FINISHED
774
+ });
775
+ };
776
+ this.info = () => this.getState();
777
+ this.next = () => {
778
+ const { index, status } = this.getState();
779
+ if (status !== STATUS.RUNNING) {
780
+ return;
781
+ }
782
+ this.setState(this.getNextState({ action: ACTIONS.NEXT, index: index + 1 }));
783
+ };
784
+ this.open = () => {
785
+ const { status } = this.getState();
786
+ if (status !== STATUS.RUNNING) {
787
+ return;
788
+ }
789
+ this.setState({
790
+ ...this.getNextState({ action: ACTIONS.UPDATE, lifecycle: LIFECYCLE.TOOLTIP })
791
+ });
792
+ };
793
+ this.prev = () => {
794
+ const { index, status } = this.getState();
795
+ if (status !== STATUS.RUNNING) {
796
+ return;
797
+ }
798
+ this.setState({
799
+ ...this.getNextState({ action: ACTIONS.PREV, index: index - 1 })
800
+ });
801
+ };
802
+ this.reset = (restart = false) => {
803
+ const { controlled } = this.getState();
804
+ if (controlled) {
805
+ return;
806
+ }
807
+ this.setState({
808
+ ...this.getNextState({ action: ACTIONS.RESET, index: 0 }),
809
+ status: restart ? STATUS.RUNNING : STATUS.READY
810
+ });
811
+ };
812
+ this.skip = () => {
813
+ const { status } = this.getState();
814
+ if (status !== STATUS.RUNNING) {
815
+ return;
816
+ }
817
+ this.setState({
818
+ action: ACTIONS.SKIP,
819
+ lifecycle: LIFECYCLE.INIT,
820
+ status: STATUS.SKIPPED
821
+ });
822
+ };
823
+ this.start = (nextIndex) => {
824
+ const { index, size } = this.getState();
825
+ this.setState({
826
+ ...this.getNextState(
827
+ {
828
+ action: ACTIONS.START,
829
+ index: is3.number(nextIndex) ? nextIndex : index
830
+ },
831
+ true
832
+ ),
833
+ status: size ? STATUS.RUNNING : STATUS.WAITING
834
+ });
835
+ };
836
+ this.stop = (advance = false) => {
837
+ const { index, status } = this.getState();
838
+ if ([STATUS.FINISHED, STATUS.SKIPPED].includes(status)) {
839
+ return;
840
+ }
841
+ this.setState({
842
+ ...this.getNextState({ action: ACTIONS.STOP, index: index + (advance ? 1 : 0) }),
843
+ status: STATUS.PAUSED
844
+ });
845
+ };
846
+ this.update = (state) => {
847
+ var _a, _b;
848
+ if (!hasValidKeys(state, validKeys)) {
849
+ throw new Error(`State is not valid. Valid keys: ${validKeys.join(", ")}`);
850
+ }
851
+ this.setState({
852
+ ...this.getNextState(
853
+ {
854
+ ...this.getState(),
855
+ ...state,
856
+ action: (_a = state.action) != null ? _a : ACTIONS.UPDATE,
857
+ origin: (_b = state.origin) != null ? _b : null
858
+ },
859
+ true
860
+ )
861
+ });
862
+ };
863
+ const { continuous = false, stepIndex, steps = [] } = options != null ? options : {};
864
+ this.setState(
865
+ {
866
+ action: ACTIONS.INIT,
867
+ controlled: is3.number(stepIndex),
868
+ continuous,
869
+ index: is3.number(stepIndex) ? stepIndex : 0,
870
+ lifecycle: LIFECYCLE.INIT,
871
+ origin: null,
872
+ status: steps.length ? STATUS.READY : STATUS.IDLE
873
+ },
874
+ true
875
+ );
876
+ this.beaconPopper = null;
877
+ this.tooltipPopper = null;
878
+ this.listener = null;
879
+ this.setSteps(steps);
880
+ }
881
+ getState() {
882
+ if (!this.store.size) {
883
+ return { ...defaultState };
884
+ }
885
+ return {
886
+ action: this.store.get("action") || "",
887
+ controlled: this.store.get("controlled") || false,
888
+ index: parseInt(this.store.get("index"), 10),
889
+ lifecycle: this.store.get("lifecycle") || "",
890
+ origin: this.store.get("origin") || null,
891
+ size: this.store.get("size") || 0,
892
+ status: this.store.get("status") || ""
893
+ };
894
+ }
895
+ getNextState(state, force = false) {
896
+ var _a, _b, _c, _d, _e;
897
+ const { action, controlled, index, size, status } = this.getState();
898
+ const newIndex = is3.number(state.index) ? state.index : index;
899
+ const nextIndex = controlled && !force ? index : Math.min(Math.max(newIndex, 0), size);
900
+ return {
901
+ action: (_a = state.action) != null ? _a : action,
902
+ controlled,
903
+ index: nextIndex,
904
+ lifecycle: (_b = state.lifecycle) != null ? _b : LIFECYCLE.INIT,
905
+ origin: (_c = state.origin) != null ? _c : null,
906
+ size: (_d = state.size) != null ? _d : size,
907
+ status: nextIndex === size ? STATUS.FINISHED : (_e = state.status) != null ? _e : status
908
+ };
909
+ }
910
+ getSteps() {
911
+ const steps = this.data.get("steps");
912
+ return Array.isArray(steps) ? steps : [];
913
+ }
914
+ hasUpdatedState(oldState) {
915
+ const before = JSON.stringify(oldState);
916
+ const after = JSON.stringify(this.getState());
917
+ return before !== after;
918
+ }
919
+ setState(nextState, initial = false) {
920
+ const state = this.getState();
921
+ const {
922
+ action,
923
+ index,
924
+ lifecycle,
925
+ origin = null,
926
+ size,
927
+ status
928
+ } = {
929
+ ...state,
930
+ ...nextState
931
+ };
932
+ this.store.set("action", action);
933
+ this.store.set("index", index);
934
+ this.store.set("lifecycle", lifecycle);
935
+ this.store.set("origin", origin);
936
+ this.store.set("size", size);
937
+ this.store.set("status", status);
938
+ if (initial) {
939
+ this.store.set("controlled", nextState.controlled);
940
+ this.store.set("continuous", nextState.continuous);
941
+ }
942
+ if (this.listener && this.hasUpdatedState(state)) {
943
+ this.listener(this.getState());
944
+ }
945
+ }
946
+ getHelpers() {
947
+ return {
948
+ close: this.close,
949
+ go: this.go,
950
+ info: this.info,
951
+ next: this.next,
952
+ open: this.open,
953
+ prev: this.prev,
954
+ reset: this.reset,
955
+ skip: this.skip
956
+ };
957
+ }
958
+ };
959
+ function createStore(options) {
960
+ return new Store(options);
961
+ }
962
+
963
+ // src/components/Overlay.tsx
964
+ import { useCallback, useEffect, useRef, useState } from "react";
965
+ import treeChanges from "tree-changes";
966
+
967
+ // src/components/Spotlight.tsx
968
+ import { jsx } from "react/jsx-runtime";
969
+ function JoyrideSpotlight({ styles }) {
970
+ return /* @__PURE__ */ jsx(
971
+ "div",
972
+ {
973
+ className: "react-joyride__spotlight",
974
+ "data-test-id": "spotlight",
975
+ style: styles
976
+ },
977
+ "JoyrideSpotlight"
978
+ );
979
+ }
980
+ var Spotlight_default = JoyrideSpotlight;
981
+
982
+ // src/components/Overlay.tsx
983
+ import { jsx as jsx2 } from "react/jsx-runtime";
984
+ function JoyrideOverlay(props) {
985
+ const {
986
+ continuous,
987
+ debug,
988
+ disableOverlay,
989
+ disableOverlayClose,
990
+ disableScrolling,
991
+ disableScrollParentFix = false,
992
+ lifecycle,
993
+ onClickOverlay,
994
+ placement,
995
+ spotlightClicks,
996
+ spotlightPadding = 0,
997
+ styles,
998
+ target
999
+ } = props;
1000
+ const [isScrolling, setIsScrolling] = useState(false);
1001
+ const [mouseOverSpotlight, setMouseOverSpotlight] = useState(false);
1002
+ const [showSpotlight, setShowSpotlight] = useState(true);
1003
+ const [, setForceRender] = useState(0);
1004
+ const isActiveRef = useRef(false);
1005
+ const resizeTimeoutRef = useRef(void 0);
1006
+ const scrollTimeoutRef = useRef(void 0);
1007
+ const scrollParentRef = useRef(void 0);
1008
+ const previousPropsRef = useRef(props);
1009
+ const getSpotlightStyles = useCallback(() => {
1010
+ var _a, _b, _c;
1011
+ const element = getElement(target);
1012
+ const elementRect = getClientRect(element);
1013
+ const isFixedTarget = hasPosition(element);
1014
+ const top = getElementPosition(element, spotlightPadding, disableScrollParentFix);
1015
+ return {
1016
+ ...styles.spotlight,
1017
+ height: Math.round(((_a = elementRect == null ? void 0 : elementRect.height) != null ? _a : 0) + spotlightPadding * 2),
1018
+ left: Math.round(((_b = elementRect == null ? void 0 : elementRect.left) != null ? _b : 0) - spotlightPadding),
1019
+ opacity: showSpotlight ? 1 : 0,
1020
+ pointerEvents: spotlightClicks ? "none" : "auto",
1021
+ position: isFixedTarget ? "fixed" : "absolute",
1022
+ top,
1023
+ transition: "opacity 0.2s",
1024
+ width: Math.round(((_c = elementRect == null ? void 0 : elementRect.width) != null ? _c : 0) + spotlightPadding * 2)
1025
+ };
1026
+ }, [target, spotlightPadding, disableScrollParentFix, styles.spotlight, showSpotlight, spotlightClicks]);
1027
+ const handleMouseMove = useCallback((event) => {
1028
+ const spotStyles = getSpotlightStyles();
1029
+ const { height, left, position, top, width } = spotStyles;
1030
+ const offsetY = position === "fixed" ? event.clientY : event.pageY;
1031
+ const offsetX = position === "fixed" ? event.clientX : event.pageX;
1032
+ const inSpotlightHeight = offsetY >= top && offsetY <= top + height;
1033
+ const inSpotlightWidth = offsetX >= left && offsetX <= left + width;
1034
+ const inSpotlight = inSpotlightWidth && inSpotlightHeight;
1035
+ setMouseOverSpotlight((prev) => {
1036
+ if (inSpotlight !== prev) {
1037
+ return inSpotlight;
1038
+ }
1039
+ return prev;
1040
+ });
1041
+ }, [getSpotlightStyles]);
1042
+ const handleScroll = useCallback(() => {
1043
+ const element = getElement(target);
1044
+ if (scrollParentRef.current !== document) {
1045
+ setIsScrolling((prev) => {
1046
+ if (!prev) {
1047
+ setShowSpotlight(false);
1048
+ return true;
1049
+ }
1050
+ return prev;
1051
+ });
1052
+ clearTimeout(scrollTimeoutRef.current);
1053
+ scrollTimeoutRef.current = window.setTimeout(() => {
1054
+ if (isActiveRef.current) {
1055
+ setIsScrolling(false);
1056
+ setShowSpotlight(true);
1057
+ }
1058
+ }, 50);
1059
+ } else if (hasPosition(element, "sticky")) {
1060
+ setForceRender((c) => c + 1);
1061
+ }
1062
+ }, [target]);
1063
+ const handleResize = useCallback(() => {
1064
+ clearTimeout(resizeTimeoutRef.current);
1065
+ resizeTimeoutRef.current = window.setTimeout(() => {
1066
+ if (isActiveRef.current) {
1067
+ setForceRender((c) => c + 1);
1068
+ }
1069
+ }, 100);
1070
+ }, []);
1071
+ useEffect(() => {
1072
+ const element = getElement(target);
1073
+ scrollParentRef.current = getScrollParent(element != null ? element : document.body, disableScrollParentFix, true);
1074
+ isActiveRef.current = true;
1075
+ if (process.env.NODE_ENV !== "production") {
1076
+ if (!disableScrolling && hasCustomScrollParent(element, true)) {
1077
+ log({
1078
+ title: "step has a custom scroll parent and can cause trouble with scrolling",
1079
+ data: [{ key: "parent", value: scrollParentRef.current }],
1080
+ debug
1081
+ });
1082
+ }
1083
+ }
1084
+ window.addEventListener("resize", handleResize);
1085
+ return () => {
1086
+ var _a;
1087
+ isActiveRef.current = false;
1088
+ window.removeEventListener("mousemove", handleMouseMove);
1089
+ window.removeEventListener("resize", handleResize);
1090
+ clearTimeout(resizeTimeoutRef.current);
1091
+ clearTimeout(scrollTimeoutRef.current);
1092
+ (_a = scrollParentRef.current) == null ? void 0 : _a.removeEventListener("scroll", handleScroll);
1093
+ };
1094
+ }, []);
1095
+ useEffect(() => {
1096
+ var _a;
1097
+ const previousProps = previousPropsRef.current;
1098
+ const { changed } = treeChanges(previousProps, props);
1099
+ if (changed("target") || changed("disableScrollParentFix")) {
1100
+ const element = getElement(target);
1101
+ scrollParentRef.current = getScrollParent(element != null ? element : document.body, disableScrollParentFix, true);
1102
+ }
1103
+ if (changed("lifecycle", LIFECYCLE.TOOLTIP)) {
1104
+ (_a = scrollParentRef.current) == null ? void 0 : _a.addEventListener("scroll", handleScroll, { passive: true });
1105
+ setTimeout(() => {
1106
+ if (!isScrolling) {
1107
+ setShowSpotlight(true);
1108
+ }
1109
+ }, 100);
1110
+ }
1111
+ if (changed("spotlightClicks") || changed("disableOverlay") || changed("lifecycle")) {
1112
+ if (spotlightClicks && lifecycle === LIFECYCLE.TOOLTIP) {
1113
+ window.addEventListener("mousemove", handleMouseMove, false);
1114
+ } else if (lifecycle !== LIFECYCLE.TOOLTIP) {
1115
+ window.removeEventListener("mousemove", handleMouseMove);
1116
+ }
1117
+ }
1118
+ previousPropsRef.current = props;
1119
+ });
1120
+ const hideSpotlight = () => {
1121
+ const hiddenLifecycles = [
1122
+ LIFECYCLE.INIT,
1123
+ LIFECYCLE.BEACON,
1124
+ LIFECYCLE.COMPLETE,
1125
+ LIFECYCLE.ERROR
1126
+ ];
1127
+ return disableOverlay || (continuous ? hiddenLifecycles.includes(lifecycle) : lifecycle !== LIFECYCLE.TOOLTIP);
1128
+ };
1129
+ if (hideSpotlight()) {
1130
+ return null;
1131
+ }
1132
+ const spotlightStyles = getSpotlightStyles();
1133
+ const overlayStyles = {
1134
+ cursor: disableOverlayClose ? "default" : "pointer",
1135
+ height: getDocumentHeight(),
1136
+ pointerEvents: mouseOverSpotlight ? "none" : "auto",
1137
+ ...styles.overlay
1138
+ };
1139
+ let spotlight2 = placement !== "center" && showSpotlight && /* @__PURE__ */ jsx2(Spotlight_default, { styles: spotlightStyles });
1140
+ if (isSafari()) {
1141
+ const { mixBlendMode, zIndex, ...safariOverlay } = overlayStyles;
1142
+ spotlight2 = /* @__PURE__ */ jsx2("div", { style: { ...safariOverlay }, children: spotlight2 });
1143
+ delete overlayStyles.backgroundColor;
1144
+ }
1145
+ return /* @__PURE__ */ jsx2(
1146
+ "div",
1147
+ {
1148
+ className: "react-joyride__overlay",
1149
+ "data-test-id": "overlay",
1150
+ onClick: onClickOverlay,
1151
+ role: "presentation",
1152
+ style: overlayStyles,
1153
+ children: spotlight2
1154
+ }
1155
+ );
1156
+ }
1157
+
1158
+ // src/components/Portal.tsx
1159
+ import { useEffect as useEffect2, useRef as useRef2 } from "react";
1160
+ import { createPortal } from "react-dom";
1161
+ function JoyridePortal({ children, id }) {
1162
+ const nodeRef = useRef2(null);
1163
+ useEffect2(() => {
1164
+ if (!canUseDOM()) {
1165
+ return;
1166
+ }
1167
+ const node = document.createElement("div");
1168
+ node.id = id;
1169
+ document.body.appendChild(node);
1170
+ nodeRef.current = node;
1171
+ return () => {
1172
+ if (node.parentNode === document.body) {
1173
+ document.body.removeChild(node);
1174
+ }
1175
+ nodeRef.current = null;
1176
+ };
1177
+ }, [id]);
1178
+ if (!canUseDOM() || !nodeRef.current) {
1179
+ return null;
1180
+ }
1181
+ return createPortal(children, nodeRef.current);
1182
+ }
1183
+
1184
+ // src/components/Step.tsx
1185
+ import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef4 } from "react";
1186
+ import Floater from "react-floater";
1187
+ import is5 from "is-lite";
1188
+ import treeChanges2 from "tree-changes";
1189
+
1190
+ // src/modules/scope.ts
1191
+ var Scope = class {
1192
+ constructor(element, options) {
1193
+ this.canBeTabbed = (element) => {
1194
+ const { tabIndex } = element;
1195
+ if (tabIndex === null || tabIndex < 0) {
1196
+ return false;
1197
+ }
1198
+ return this.canHaveFocus(element);
1199
+ };
1200
+ this.canHaveFocus = (element) => {
1201
+ const validTabNodes = /input|select|textarea|button|object/;
1202
+ const nodeName = element.nodeName.toLowerCase();
1203
+ const isValid = validTabNodes.test(nodeName) && !element.getAttribute("disabled") || nodeName === "a" && !!element.getAttribute("href");
1204
+ return isValid && this.isVisible(element);
1205
+ };
1206
+ this.findValidTabElements = () => [].slice.call(this.element.querySelectorAll("*"), 0).filter(this.canBeTabbed);
1207
+ this.handleKeyDown = (event) => {
1208
+ const { code = "Tab" } = this.options;
1209
+ if (event.code === code) {
1210
+ this.interceptTab(event);
1211
+ }
1212
+ };
1213
+ this.interceptTab = (event) => {
1214
+ event.preventDefault();
1215
+ const elements = this.findValidTabElements();
1216
+ const { shiftKey } = event;
1217
+ if (!elements.length) {
1218
+ return;
1219
+ }
1220
+ let x = document.activeElement ? elements.indexOf(document.activeElement) : 0;
1221
+ if (x === -1 || !shiftKey && x + 1 === elements.length) {
1222
+ x = 0;
1223
+ } else if (shiftKey && x === 0) {
1224
+ x = elements.length - 1;
1225
+ } else {
1226
+ x += shiftKey ? -1 : 1;
1227
+ }
1228
+ elements[x].focus();
1229
+ };
1230
+ // eslint-disable-next-line class-methods-use-this
1231
+ this.isHidden = (element) => {
1232
+ const noSize = element.offsetWidth <= 0 && element.offsetHeight <= 0;
1233
+ const style = window.getComputedStyle(element);
1234
+ if (noSize && !element.innerHTML) {
1235
+ return true;
1236
+ }
1237
+ return noSize && style.getPropertyValue("overflow") !== "visible" || style.getPropertyValue("display") === "none";
1238
+ };
1239
+ this.isVisible = (element) => {
1240
+ let parentElement = element;
1241
+ while (parentElement) {
1242
+ if (parentElement instanceof HTMLElement) {
1243
+ if (parentElement === document.body) {
1244
+ break;
1245
+ }
1246
+ if (this.isHidden(parentElement)) {
1247
+ return false;
1248
+ }
1249
+ parentElement = parentElement.parentNode;
1250
+ }
1251
+ }
1252
+ return true;
1253
+ };
1254
+ this.removeScope = () => {
1255
+ window.removeEventListener("keydown", this.handleKeyDown);
1256
+ };
1257
+ this.checkFocus = (target) => {
1258
+ if (document.activeElement !== target) {
1259
+ target.focus();
1260
+ window.requestAnimationFrame(() => this.checkFocus(target));
1261
+ }
1262
+ };
1263
+ this.setFocus = () => {
1264
+ const { selector } = this.options;
1265
+ if (!selector) {
1266
+ return;
1267
+ }
1268
+ const target = this.element.querySelector(selector);
1269
+ if (target) {
1270
+ window.requestAnimationFrame(() => this.checkFocus(target));
1271
+ }
1272
+ };
1273
+ if (!(element instanceof HTMLElement)) {
1274
+ throw new TypeError("Invalid parameter: element must be an HTMLElement");
1275
+ }
1276
+ this.element = element;
1277
+ this.options = options;
1278
+ window.addEventListener("keydown", this.handleKeyDown, false);
1279
+ this.setFocus();
1280
+ }
1281
+ };
1282
+
1283
+ // src/components/Beacon.tsx
1284
+ import { useCallback as useCallback2, useEffect as useEffect3, useRef as useRef3 } from "react";
1285
+ import is4 from "is-lite";
1286
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
1287
+ function JoyrideBeacon(props) {
1288
+ const {
1289
+ beaconComponent,
1290
+ continuous,
1291
+ index,
1292
+ isLastStep,
1293
+ locale,
1294
+ nonce,
1295
+ onClickOrHover,
1296
+ shouldFocus,
1297
+ size,
1298
+ step,
1299
+ styles
1300
+ } = props;
1301
+ const beaconRef = useRef3(null);
1302
+ const setBeaconRef = useCallback2((c) => {
1303
+ beaconRef.current = c;
1304
+ }, []);
1305
+ useEffect3(() => {
1306
+ if (beaconComponent) {
1307
+ return;
1308
+ }
1309
+ const head = document.head || document.getElementsByTagName("head")[0];
1310
+ const style = document.createElement("style");
1311
+ style.id = "joyride-beacon-animation";
1312
+ if (nonce) {
1313
+ style.setAttribute("nonce", nonce);
1314
+ }
1315
+ const css = `
1316
+ @keyframes joyride-beacon-inner {
1317
+ 20% {
1318
+ opacity: 0.9;
1319
+ }
1320
+
1321
+ 90% {
1322
+ opacity: 0.7;
1323
+ }
1324
+ }
1325
+
1326
+ @keyframes joyride-beacon-outer {
1327
+ 0% {
1328
+ transform: scale(1);
1329
+ }
1330
+
1331
+ 45% {
1332
+ opacity: 0.7;
1333
+ transform: scale(0.75);
1334
+ }
1335
+
1336
+ 100% {
1337
+ opacity: 0.9;
1338
+ transform: scale(1);
1339
+ }
1340
+ }
1341
+ `;
1342
+ style.appendChild(document.createTextNode(css));
1343
+ head.appendChild(style);
1344
+ return () => {
1345
+ const existingStyle = document.getElementById("joyride-beacon-animation");
1346
+ if (existingStyle == null ? void 0 : existingStyle.parentNode) {
1347
+ existingStyle.parentNode.removeChild(existingStyle);
1348
+ }
1349
+ };
1350
+ }, [beaconComponent, nonce]);
1351
+ useEffect3(() => {
1352
+ if (process.env.NODE_ENV !== "production") {
1353
+ if (!is4.domElement(beaconRef.current)) {
1354
+ console.warn("beacon is not a valid DOM element");
1355
+ }
1356
+ }
1357
+ setTimeout(() => {
1358
+ if (is4.domElement(beaconRef.current) && shouldFocus) {
1359
+ beaconRef.current.focus();
1360
+ }
1361
+ }, 0);
1362
+ }, [shouldFocus]);
1363
+ const title = getReactNodeText(locale.open);
1364
+ const sharedProps = {
1365
+ "aria-label": title,
1366
+ onClick: onClickOrHover,
1367
+ onMouseEnter: onClickOrHover,
1368
+ ref: setBeaconRef,
1369
+ title
1370
+ };
1371
+ if (beaconComponent) {
1372
+ const BeaconComponent = beaconComponent;
1373
+ return /* @__PURE__ */ jsx3(
1374
+ BeaconComponent,
1375
+ {
1376
+ continuous,
1377
+ index,
1378
+ isLastStep,
1379
+ size,
1380
+ step,
1381
+ ...sharedProps
1382
+ }
1383
+ );
1384
+ }
1385
+ return /* @__PURE__ */ jsxs(
1386
+ "button",
1387
+ {
1388
+ className: "react-joyride__beacon",
1389
+ "data-test-id": "button-beacon",
1390
+ style: styles.beacon,
1391
+ type: "button",
1392
+ ...sharedProps,
1393
+ children: [
1394
+ /* @__PURE__ */ jsx3("span", { style: styles.beaconInner }),
1395
+ /* @__PURE__ */ jsx3("span", { style: styles.beaconOuter })
1396
+ ]
1397
+ },
1398
+ "JoyrideBeacon"
1399
+ );
1400
+ }
1401
+
1402
+ // src/components/Tooltip/CloseButton.tsx
1403
+ import { jsx as jsx4 } from "react/jsx-runtime";
1404
+ function JoyrideTooltipCloseButton({ styles, ...props }) {
1405
+ const { color, height, width, ...style } = styles;
1406
+ return /* @__PURE__ */ jsx4("button", { style, type: "button", ...props, children: /* @__PURE__ */ jsx4(
1407
+ "svg",
1408
+ {
1409
+ height: typeof height === "number" ? `${height}px` : height,
1410
+ preserveAspectRatio: "xMidYMid",
1411
+ version: "1.1",
1412
+ viewBox: "0 0 18 18",
1413
+ width: typeof width === "number" ? `${width}px` : width,
1414
+ xmlns: "http://www.w3.org/2000/svg",
1415
+ children: /* @__PURE__ */ jsx4("g", { children: /* @__PURE__ */ jsx4(
1416
+ "path",
1417
+ {
1418
+ d: "M8.13911129,9.00268191 L0.171521827,17.0258467 C-0.0498027049,17.248715 -0.0498027049,17.6098394 0.171521827,17.8327545 C0.28204354,17.9443526 0.427188206,17.9998706 0.572051765,17.9998706 C0.71714958,17.9998706 0.862013139,17.9443526 0.972581703,17.8327545 L9.0000937,9.74924618 L17.0276057,17.8327545 C17.1384085,17.9443526 17.2832721,17.9998706 17.4281356,17.9998706 C17.5729992,17.9998706 17.718097,17.9443526 17.8286656,17.8327545 C18.0499901,17.6098862 18.0499901,17.2487618 17.8286656,17.0258467 L9.86135722,9.00268191 L17.8340066,0.973848225 C18.0553311,0.750979934 18.0553311,0.389855532 17.8340066,0.16694039 C17.6126821,-0.0556467968 17.254037,-0.0556467968 17.0329467,0.16694039 L9.00042166,8.25611765 L0.967006424,0.167268345 C0.745681892,-0.0553188426 0.387317931,-0.0553188426 0.165993399,0.167268345 C-0.0553311331,0.390136635 -0.0553311331,0.751261038 0.165993399,0.974176179 L8.13920499,9.00268191 L8.13911129,9.00268191 Z",
1419
+ fill: color
1420
+ }
1421
+ ) })
1422
+ }
1423
+ ) });
1424
+ }
1425
+ var CloseButton_default = JoyrideTooltipCloseButton;
1426
+
1427
+ // src/components/Tooltip/Container.tsx
1428
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
1429
+ function JoyrideTooltipContainer(props) {
1430
+ const { backProps, closeProps, index, isLastStep, primaryProps, skipProps, step, tooltipProps } = props;
1431
+ const { content, hideBackButton, hideCloseButton, hideFooter, showSkipButton, styles, title } = step;
1432
+ const output = {};
1433
+ output.primary = /* @__PURE__ */ jsx5(
1434
+ "button",
1435
+ {
1436
+ "data-test-id": "button-primary",
1437
+ style: styles.buttonNext,
1438
+ type: "button",
1439
+ ...primaryProps
1440
+ }
1441
+ );
1442
+ if (showSkipButton && !isLastStep) {
1443
+ output.skip = /* @__PURE__ */ jsx5(
1444
+ "button",
1445
+ {
1446
+ "aria-live": "off",
1447
+ "data-test-id": "button-skip",
1448
+ style: styles.buttonSkip,
1449
+ type: "button",
1450
+ ...skipProps
1451
+ }
1452
+ );
1453
+ }
1454
+ if (!hideBackButton && index > 0) {
1455
+ output.back = /* @__PURE__ */ jsx5("button", { "data-test-id": "button-back", style: styles.buttonBack, type: "button", ...backProps });
1456
+ }
1457
+ output.close = !hideCloseButton && /* @__PURE__ */ jsx5(CloseButton_default, { "data-test-id": "button-close", styles: styles.buttonClose, ...closeProps });
1458
+ return /* @__PURE__ */ jsxs2(
1459
+ "div",
1460
+ {
1461
+ "aria-label": getReactNodeText(title != null ? title : content),
1462
+ className: "react-joyride__tooltip",
1463
+ style: styles.tooltip,
1464
+ ...tooltipProps,
1465
+ children: [
1466
+ /* @__PURE__ */ jsxs2("div", { style: styles.tooltipContainer, children: [
1467
+ title && /* @__PURE__ */ jsx5("h1", { "aria-label": getReactNodeText(title), style: styles.tooltipTitle, children: title }),
1468
+ /* @__PURE__ */ jsx5("div", { style: styles.tooltipContent, children: content })
1469
+ ] }),
1470
+ !hideFooter && /* @__PURE__ */ jsxs2("div", { style: styles.tooltipFooter, children: [
1471
+ /* @__PURE__ */ jsx5("div", { style: styles.tooltipFooterSpacer, children: output.skip }),
1472
+ output.back,
1473
+ output.primary
1474
+ ] }),
1475
+ output.close
1476
+ ]
1477
+ },
1478
+ "JoyrideTooltip"
1479
+ );
1480
+ }
1481
+ var Container_default = JoyrideTooltipContainer;
1482
+
1483
+ // src/components/Tooltip/index.tsx
1484
+ import { jsx as jsx6 } from "react/jsx-runtime";
1485
+ function JoyrideTooltip(props) {
1486
+ const { continuous, helpers, index, isLastStep, setTooltipRef, size, step } = props;
1487
+ const handleClickBack = (event) => {
1488
+ event.preventDefault();
1489
+ helpers.prev();
1490
+ };
1491
+ const handleClickClose = (event) => {
1492
+ event.preventDefault();
1493
+ helpers.close("button_close");
1494
+ };
1495
+ const handleClickPrimary = (event) => {
1496
+ event.preventDefault();
1497
+ if (!continuous) {
1498
+ helpers.close("button_primary");
1499
+ return;
1500
+ }
1501
+ helpers.next();
1502
+ };
1503
+ const handleClickSkip = (event) => {
1504
+ event.preventDefault();
1505
+ helpers.skip();
1506
+ };
1507
+ const getElementsProps = () => {
1508
+ const { back, close, last, next, nextLabelWithProgress, skip } = step.locale;
1509
+ const backText = getReactNodeText(back);
1510
+ const closeText = getReactNodeText(close);
1511
+ const lastText = getReactNodeText(last);
1512
+ const nextText = getReactNodeText(next);
1513
+ const skipText = getReactNodeText(skip);
1514
+ let primary = close;
1515
+ let primaryText = closeText;
1516
+ if (continuous) {
1517
+ primary = next;
1518
+ primaryText = nextText;
1519
+ if (step.showProgress && !isLastStep) {
1520
+ const labelWithProgress = getReactNodeText(nextLabelWithProgress, {
1521
+ step: index + 1,
1522
+ steps: size
1523
+ });
1524
+ primary = replaceLocaleContent(nextLabelWithProgress, index + 1, size);
1525
+ primaryText = labelWithProgress;
1526
+ }
1527
+ if (isLastStep) {
1528
+ primary = last;
1529
+ primaryText = lastText;
1530
+ }
1531
+ }
1532
+ return {
1533
+ backProps: {
1534
+ "aria-label": backText,
1535
+ children: back,
1536
+ "data-action": "back",
1537
+ onClick: handleClickBack,
1538
+ role: "button",
1539
+ title: backText
1540
+ },
1541
+ closeProps: {
1542
+ "aria-label": closeText,
1543
+ children: close,
1544
+ "data-action": "close",
1545
+ onClick: handleClickClose,
1546
+ role: "button",
1547
+ title: closeText
1548
+ },
1549
+ primaryProps: {
1550
+ "aria-label": primaryText,
1551
+ children: primary,
1552
+ "data-action": "primary",
1553
+ onClick: handleClickPrimary,
1554
+ role: "button",
1555
+ title: primaryText
1556
+ },
1557
+ skipProps: {
1558
+ "aria-label": skipText,
1559
+ children: skip,
1560
+ "data-action": "skip",
1561
+ onClick: handleClickSkip,
1562
+ role: "button",
1563
+ title: skipText
1564
+ },
1565
+ tooltipProps: {
1566
+ "aria-modal": true,
1567
+ ref: setTooltipRef,
1568
+ role: "alertdialog"
1569
+ }
1570
+ };
1571
+ };
1572
+ const { beaconComponent, tooltipComponent, ...cleanStep } = step;
1573
+ if (tooltipComponent) {
1574
+ const renderProps = {
1575
+ ...getElementsProps(),
1576
+ continuous,
1577
+ index,
1578
+ isLastStep,
1579
+ size,
1580
+ step: cleanStep,
1581
+ setTooltipRef
1582
+ };
1583
+ const TooltipComponent = tooltipComponent;
1584
+ return /* @__PURE__ */ jsx6(TooltipComponent, { ...renderProps });
1585
+ }
1586
+ return /* @__PURE__ */ jsx6(
1587
+ Container_default,
1588
+ {
1589
+ ...getElementsProps(),
1590
+ continuous,
1591
+ index,
1592
+ isLastStep,
1593
+ size,
1594
+ step
1595
+ }
1596
+ );
1597
+ }
1598
+
1599
+ // src/components/Step.tsx
1600
+ import { jsx as jsx7 } from "react/jsx-runtime";
1601
+ function JoyrideStep(props) {
1602
+ var _a;
1603
+ const {
1604
+ action,
1605
+ callback,
1606
+ continuous,
1607
+ controlled,
1608
+ debug,
1609
+ helpers,
1610
+ index,
1611
+ lifecycle,
1612
+ nonce,
1613
+ shouldScroll: shouldScroll2,
1614
+ size,
1615
+ status,
1616
+ step,
1617
+ store
1618
+ } = props;
1619
+ const scopeRef = useRef4(null);
1620
+ const tooltipRef = useRef4(null);
1621
+ const previousPropsRef = useRef4(props);
1622
+ const setTooltipRef = useCallback3((element) => {
1623
+ tooltipRef.current = element;
1624
+ }, []);
1625
+ const handleClickHoverBeacon = useCallback3((event) => {
1626
+ if (event.type === "mouseenter" && step.event !== "hover") {
1627
+ return;
1628
+ }
1629
+ store.update({ lifecycle: LIFECYCLE.TOOLTIP });
1630
+ }, [step.event, store]);
1631
+ const setPopper = useCallback3((popper, type) => {
1632
+ var _a2;
1633
+ if (type === "wrapper") {
1634
+ store.setPopper("beacon", popper);
1635
+ } else {
1636
+ store.setPopper("tooltip", popper);
1637
+ }
1638
+ if (store.getPopper("beacon") && (store.getPopper("tooltip") || step.placement === "center") && lifecycle === LIFECYCLE.INIT) {
1639
+ store.update({
1640
+ action,
1641
+ lifecycle: LIFECYCLE.READY
1642
+ });
1643
+ }
1644
+ if ((_a2 = step.floaterProps) == null ? void 0 : _a2.getPopper) {
1645
+ step.floaterProps.getPopper(popper, type);
1646
+ }
1647
+ }, [action, lifecycle, step.placement, step.floaterProps, store]);
1648
+ useEffect4(() => {
1649
+ log({
1650
+ title: `step:${index}`,
1651
+ data: [{ key: "props", value: props }],
1652
+ debug
1653
+ });
1654
+ }, []);
1655
+ useEffect4(() => {
1656
+ return () => {
1657
+ var _a2;
1658
+ (_a2 = scopeRef.current) == null ? void 0 : _a2.removeScope();
1659
+ };
1660
+ }, []);
1661
+ useEffect4(() => {
1662
+ var _a2;
1663
+ const previousProps = previousPropsRef.current;
1664
+ const { changed, changedFrom } = treeChanges2(previousProps, props);
1665
+ const state = helpers.info();
1666
+ const skipBeacon = continuous && action !== ACTIONS.CLOSE && (index > 0 || action === ACTIONS.PREV);
1667
+ const hasStoreChanged = changed("action") || changed("index") || changed("lifecycle") || changed("status");
1668
+ const isInitial = changedFrom("lifecycle", [LIFECYCLE.TOOLTIP, LIFECYCLE.INIT], LIFECYCLE.INIT);
1669
+ const isAfterAction = changed("action", [
1670
+ ACTIONS.NEXT,
1671
+ ACTIONS.PREV,
1672
+ ACTIONS.SKIP,
1673
+ ACTIONS.CLOSE
1674
+ ]);
1675
+ const isControlled = controlled && index === previousProps.index;
1676
+ if (isAfterAction && (isInitial || isControlled)) {
1677
+ callback({
1678
+ ...state,
1679
+ index: previousProps.index,
1680
+ lifecycle: LIFECYCLE.COMPLETE,
1681
+ step: previousProps.step,
1682
+ type: EVENTS.STEP_AFTER
1683
+ });
1684
+ }
1685
+ if (step.placement === "center" && status === STATUS.RUNNING && changed("index") && action !== ACTIONS.START && lifecycle === LIFECYCLE.INIT) {
1686
+ store.update({ lifecycle: LIFECYCLE.READY });
1687
+ }
1688
+ if (hasStoreChanged) {
1689
+ const element = getElement(step.target);
1690
+ const elementExists = !!element;
1691
+ const hasRenderedTarget = elementExists && isElementVisible(element);
1692
+ if (hasRenderedTarget) {
1693
+ if (changedFrom("status", STATUS.READY, STATUS.RUNNING) || changedFrom("lifecycle", LIFECYCLE.INIT, LIFECYCLE.READY)) {
1694
+ callback({
1695
+ ...state,
1696
+ step,
1697
+ type: EVENTS.STEP_BEFORE
1698
+ });
1699
+ }
1700
+ } else {
1701
+ console.warn(elementExists ? "Target not visible" : "Target not mounted", step);
1702
+ callback({
1703
+ ...state,
1704
+ type: EVENTS.TARGET_NOT_FOUND,
1705
+ step
1706
+ });
1707
+ if (!controlled) {
1708
+ store.update({ index: index + (action === ACTIONS.PREV ? -1 : 1) });
1709
+ }
1710
+ }
1711
+ }
1712
+ if (changedFrom("lifecycle", LIFECYCLE.INIT, LIFECYCLE.READY)) {
1713
+ store.update({
1714
+ lifecycle: hideBeacon(step) || skipBeacon ? LIFECYCLE.TOOLTIP : LIFECYCLE.BEACON
1715
+ });
1716
+ }
1717
+ if (changed("index")) {
1718
+ log({
1719
+ title: `step:${lifecycle}`,
1720
+ data: [{ key: "props", value: props }],
1721
+ debug
1722
+ });
1723
+ }
1724
+ if (changed("lifecycle", LIFECYCLE.BEACON)) {
1725
+ callback({
1726
+ ...state,
1727
+ step,
1728
+ type: EVENTS.BEACON
1729
+ });
1730
+ }
1731
+ if (changed("lifecycle", LIFECYCLE.TOOLTIP)) {
1732
+ callback({
1733
+ ...state,
1734
+ step,
1735
+ type: EVENTS.TOOLTIP
1736
+ });
1737
+ if (shouldScroll2 && tooltipRef.current) {
1738
+ scopeRef.current = new Scope(tooltipRef.current, { selector: "[data-action=primary]" });
1739
+ scopeRef.current.setFocus();
1740
+ }
1741
+ }
1742
+ if (changedFrom("lifecycle", [LIFECYCLE.TOOLTIP, LIFECYCLE.INIT], LIFECYCLE.INIT)) {
1743
+ (_a2 = scopeRef.current) == null ? void 0 : _a2.removeScope();
1744
+ store.cleanupPoppers();
1745
+ }
1746
+ previousPropsRef.current = props;
1747
+ });
1748
+ const target = getElement(step.target);
1749
+ if (!validateStep(step) || !is5.domElement(target)) {
1750
+ return null;
1751
+ }
1752
+ const isOpen = hideBeacon(step) || lifecycle === LIFECYCLE.TOOLTIP;
1753
+ const TooltipComponent = () => /* @__PURE__ */ jsx7(
1754
+ JoyrideTooltip,
1755
+ {
1756
+ continuous,
1757
+ helpers,
1758
+ index,
1759
+ isLastStep: index + 1 === size,
1760
+ setTooltipRef,
1761
+ size,
1762
+ step
1763
+ }
1764
+ );
1765
+ const { content: _c, component: _comp, ...safeFloaterProps } = (_a = step.floaterProps) != null ? _a : {};
1766
+ return /* @__PURE__ */ jsx7("div", { className: "react-joyride__step", children: /* @__PURE__ */ jsx7(
1767
+ Floater,
1768
+ {
1769
+ ...safeFloaterProps,
1770
+ component: TooltipComponent,
1771
+ debug,
1772
+ getPopper: setPopper,
1773
+ id: `react-joyride-step-${index}`,
1774
+ open: isOpen,
1775
+ placement: step.placement,
1776
+ target: step.target,
1777
+ children: /* @__PURE__ */ jsx7(
1778
+ JoyrideBeacon,
1779
+ {
1780
+ beaconComponent: step.beaconComponent,
1781
+ continuous,
1782
+ index,
1783
+ isLastStep: index + 1 === size,
1784
+ locale: step.locale,
1785
+ nonce,
1786
+ onClickOrHover: handleClickHoverBeacon,
1787
+ shouldFocus: shouldScroll2,
1788
+ size,
1789
+ step,
1790
+ styles: step.styles
1791
+ }
1792
+ )
1793
+ }
1794
+ ) }, `JoyrideStep-${index}`);
1795
+ }
1796
+
1797
+ // src/components/index.tsx
1798
+ import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
1799
+ var defaultPropsValues = {
1800
+ continuous: false,
1801
+ debug: false,
1802
+ disableCloseOnEsc: false,
1803
+ disableOverlay: false,
1804
+ disableOverlayClose: false,
1805
+ disableScrolling: false,
1806
+ disableScrollParentFix: false,
1807
+ hideBackButton: false,
1808
+ run: true,
1809
+ scrollOffset: 20,
1810
+ scrollDuration: 300,
1811
+ scrollToFirstStep: false,
1812
+ showSkipButton: false,
1813
+ showProgress: false,
1814
+ spotlightClicks: false,
1815
+ spotlightPadding: 10,
1816
+ steps: []
1817
+ };
1818
+ function Joyride(inputProps) {
1819
+ const props = { ...defaultPropsValues, ...inputProps };
1820
+ const {
1821
+ callback: callbackProp,
1822
+ continuous,
1823
+ debug,
1824
+ disableCloseOnEsc,
1825
+ getHelpers,
1826
+ nonce,
1827
+ run,
1828
+ scrollDuration,
1829
+ scrollOffset,
1830
+ scrollToFirstStep,
1831
+ stepIndex,
1832
+ steps
1833
+ } = props;
1834
+ const storeRef = useRef5(
1835
+ createStore({
1836
+ ...props,
1837
+ controlled: run && is6.number(stepIndex)
1838
+ })
1839
+ );
1840
+ const helpersRef = useRef5(storeRef.current.getHelpers());
1841
+ const [state, setState] = useState2(storeRef.current.getState());
1842
+ const previousStateRef = useRef5(state);
1843
+ const previousPropsRef = useRef5(props);
1844
+ const mountedRef = useRef5(false);
1845
+ const store = storeRef.current;
1846
+ const helpers = helpersRef.current;
1847
+ const triggerCallback = useCallback4(
1848
+ (data) => {
1849
+ if (is6.function(callbackProp)) {
1850
+ callbackProp(data);
1851
+ }
1852
+ },
1853
+ [callbackProp]
1854
+ );
1855
+ const handleKeyboard = useCallback4(
1856
+ (event) => {
1857
+ const { index: currentIndex, lifecycle: lifecycle2 } = storeRef.current.getState();
1858
+ const currentSteps = props.steps;
1859
+ const currentStep = currentSteps[currentIndex];
1860
+ if (lifecycle2 === LIFECYCLE.TOOLTIP) {
1861
+ if (event.code === "Escape" && currentStep && !currentStep.disableCloseOnEsc) {
1862
+ storeRef.current.close("keyboard");
1863
+ }
1864
+ }
1865
+ },
1866
+ [props.steps]
1867
+ );
1868
+ const handleClickOverlay = useCallback4(() => {
1869
+ const currentState = storeRef.current.getState();
1870
+ const step = getMergedStep(props, steps[currentState.index]);
1871
+ if (!step.disableOverlayClose) {
1872
+ helpers.close("overlay");
1873
+ }
1874
+ }, [props, steps, helpers]);
1875
+ useEffect5(() => {
1876
+ store.addListener(setState);
1877
+ log({
1878
+ title: "init",
1879
+ data: [
1880
+ { key: "props", value: props },
1881
+ { key: "state", value: state }
1882
+ ],
1883
+ debug
1884
+ });
1885
+ if (getHelpers) {
1886
+ getHelpers(helpers);
1887
+ }
1888
+ }, []);
1889
+ useEffect5(() => {
1890
+ if (!canUseDOM()) {
1891
+ return;
1892
+ }
1893
+ if (validateSteps(steps, debug) && run) {
1894
+ store.start();
1895
+ }
1896
+ if (!disableCloseOnEsc) {
1897
+ document.body.addEventListener("keydown", handleKeyboard, { passive: true });
1898
+ }
1899
+ mountedRef.current = true;
1900
+ return () => {
1901
+ if (!disableCloseOnEsc) {
1902
+ document.body.removeEventListener("keydown", handleKeyboard);
1903
+ }
1904
+ };
1905
+ }, []);
1906
+ useEffect5(() => {
1907
+ if (!mountedRef.current || !canUseDOM()) {
1908
+ return;
1909
+ }
1910
+ const previousProps = previousPropsRef.current;
1911
+ const { changedProps } = treeChanges3(previousProps, props);
1912
+ const changedPropsFn = (key) => {
1913
+ const prev = previousProps[key];
1914
+ const curr = props[key];
1915
+ return prev !== curr;
1916
+ };
1917
+ const stepsChanged = !isEqual(previousProps.steps, steps);
1918
+ if (stepsChanged) {
1919
+ if (validateSteps(steps, debug)) {
1920
+ store.setSteps(steps);
1921
+ } else {
1922
+ console.warn("Steps are not valid", steps);
1923
+ }
1924
+ }
1925
+ if (changedPropsFn("run")) {
1926
+ if (run) {
1927
+ store.start(stepIndex);
1928
+ } else {
1929
+ store.stop();
1930
+ }
1931
+ }
1932
+ const stepIndexChanged = is6.number(stepIndex) && changedPropsFn("stepIndex");
1933
+ if (stepIndexChanged) {
1934
+ const currentState = store.getState();
1935
+ let nextAction = is6.number(previousProps.stepIndex) && previousProps.stepIndex < stepIndex ? ACTIONS.NEXT : ACTIONS.PREV;
1936
+ if (currentState.action === ACTIONS.STOP) {
1937
+ nextAction = ACTIONS.START;
1938
+ }
1939
+ if (![STATUS.FINISHED, STATUS.SKIPPED].includes(currentState.status)) {
1940
+ store.update({
1941
+ action: currentState.action === ACTIONS.CLOSE ? ACTIONS.CLOSE : nextAction,
1942
+ index: stepIndex,
1943
+ lifecycle: LIFECYCLE.INIT
1944
+ });
1945
+ }
1946
+ }
1947
+ previousPropsRef.current = props;
1948
+ });
1949
+ useEffect5(() => {
1950
+ if (!mountedRef.current || !canUseDOM()) {
1951
+ return;
1952
+ }
1953
+ const previousState = previousStateRef.current;
1954
+ const { action, controlled, index: index2, lifecycle: lifecycle2, status: status2 } = state;
1955
+ const { changed, changedFrom } = treeChanges3(previousState, state);
1956
+ const step = getMergedStep(props, steps[index2]);
1957
+ const target = getElement(step.target);
1958
+ if (!controlled && status2 === STATUS.RUNNING && index2 === 0 && !target) {
1959
+ store.update({ index: index2 + 1 });
1960
+ triggerCallback({
1961
+ ...state,
1962
+ type: EVENTS.TARGET_NOT_FOUND,
1963
+ step
1964
+ });
1965
+ }
1966
+ const callbackData = {
1967
+ ...state,
1968
+ index: index2,
1969
+ step
1970
+ };
1971
+ const isAfterAction = changed("action", [
1972
+ ACTIONS.NEXT,
1973
+ ACTIONS.PREV,
1974
+ ACTIONS.SKIP,
1975
+ ACTIONS.CLOSE
1976
+ ]);
1977
+ if (isAfterAction && changed("status", STATUS.PAUSED)) {
1978
+ const previousStep = getMergedStep(props, steps[previousState.index]);
1979
+ triggerCallback({
1980
+ ...callbackData,
1981
+ index: previousState.index,
1982
+ lifecycle: LIFECYCLE.COMPLETE,
1983
+ step: previousStep,
1984
+ type: EVENTS.STEP_AFTER
1985
+ });
1986
+ }
1987
+ if (changed("status", [STATUS.FINISHED, STATUS.SKIPPED])) {
1988
+ const previousStep = getMergedStep(props, steps[previousState.index]);
1989
+ if (!controlled) {
1990
+ triggerCallback({
1991
+ ...callbackData,
1992
+ index: previousState.index,
1993
+ lifecycle: LIFECYCLE.COMPLETE,
1994
+ step: previousStep,
1995
+ type: EVENTS.STEP_AFTER
1996
+ });
1997
+ }
1998
+ triggerCallback({
1999
+ ...callbackData,
2000
+ type: EVENTS.TOUR_END,
2001
+ // Return the last step when the tour is finished
2002
+ step: previousStep,
2003
+ index: previousState.index
2004
+ });
2005
+ store.reset();
2006
+ } else if (changedFrom("status", [STATUS.IDLE, STATUS.READY], STATUS.RUNNING)) {
2007
+ triggerCallback({
2008
+ ...callbackData,
2009
+ type: EVENTS.TOUR_START
2010
+ });
2011
+ } else if (changed("status") || changed("action", ACTIONS.RESET)) {
2012
+ triggerCallback({
2013
+ ...callbackData,
2014
+ type: EVENTS.TOUR_STATUS
2015
+ });
2016
+ }
2017
+ scrollToStep(previousState);
2018
+ previousStateRef.current = state;
2019
+ });
2020
+ function scrollToStep(previousState) {
2021
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
2022
+ const { index: index2, lifecycle: lifecycle2, status: status2 } = state;
2023
+ const {
2024
+ disableScrollParentFix = false
2025
+ } = props;
2026
+ const step = getMergedStep(props, steps[index2]);
2027
+ const target = getElement(step.target);
2028
+ const shouldScrollToStep = shouldScroll({
2029
+ isFirstStep: index2 === 0,
2030
+ lifecycle: lifecycle2,
2031
+ previousLifecycle: previousState.lifecycle,
2032
+ scrollToFirstStep,
2033
+ step,
2034
+ target
2035
+ });
2036
+ if (status2 === STATUS.RUNNING && shouldScrollToStep) {
2037
+ const hasCustomScroll = hasCustomScrollParent(target, disableScrollParentFix);
2038
+ const scrollParent2 = getScrollParent(target, disableScrollParentFix);
2039
+ let scrollY = Math.floor(getScrollTo(target, scrollOffset, disableScrollParentFix)) || 0;
2040
+ log({
2041
+ title: "scrollToStep",
2042
+ data: [
2043
+ { key: "index", value: index2 },
2044
+ { key: "lifecycle", value: lifecycle2 },
2045
+ { key: "status", value: status2 }
2046
+ ],
2047
+ debug
2048
+ });
2049
+ const beaconPopper = store.getPopper("beacon");
2050
+ const tooltipPopper = store.getPopper("tooltip");
2051
+ if (lifecycle2 === LIFECYCLE.BEACON && beaconPopper) {
2052
+ const placement = (_b = (_a = beaconPopper.state) == null ? void 0 : _a.placement) != null ? _b : "";
2053
+ const popperTop = (_f = (_e = (_d = (_c = beaconPopper.state) == null ? void 0 : _c.rects) == null ? void 0 : _d.popper) == null ? void 0 : _e.y) != null ? _f : 0;
2054
+ if (!["bottom"].includes(placement) && !hasCustomScroll) {
2055
+ scrollY = Math.floor(popperTop - scrollOffset);
2056
+ }
2057
+ } else if (lifecycle2 === LIFECYCLE.TOOLTIP && tooltipPopper) {
2058
+ const placement = (_h = (_g = tooltipPopper.state) == null ? void 0 : _g.placement) != null ? _h : "";
2059
+ const popperTop = (_l = (_k = (_j = (_i = tooltipPopper.state) == null ? void 0 : _i.rects) == null ? void 0 : _j.popper) == null ? void 0 : _k.y) != null ? _l : 0;
2060
+ const flipped = ((_o = (_n = (_m = tooltipPopper.state) == null ? void 0 : _m.modifiersData) == null ? void 0 : _n.flip) == null ? void 0 : _o.overflows) != null;
2061
+ if (["top", "right", "left"].includes(placement) && !flipped && !hasCustomScroll) {
2062
+ scrollY = Math.floor(popperTop - scrollOffset);
2063
+ } else {
2064
+ scrollY -= step.spotlightPadding;
2065
+ }
2066
+ }
2067
+ scrollY = scrollY >= 0 ? scrollY : 0;
2068
+ if (status2 === STATUS.RUNNING) {
2069
+ scrollTo(scrollY, { element: scrollParent2, duration: scrollDuration }).then(
2070
+ () => {
2071
+ setTimeout(() => {
2072
+ var _a2;
2073
+ (_a2 = store.getPopper("tooltip")) == null ? void 0 : _a2.update();
2074
+ }, 10);
2075
+ }
2076
+ );
2077
+ }
2078
+ }
2079
+ }
2080
+ if (!canUseDOM()) {
2081
+ return null;
2082
+ }
2083
+ const { index, lifecycle, status } = state;
2084
+ const isRunning = status === STATUS.RUNNING;
2085
+ const content = {};
2086
+ if (isRunning && steps[index]) {
2087
+ const step = getMergedStep(props, steps[index]);
2088
+ content.step = /* @__PURE__ */ jsx8(
2089
+ JoyrideStep,
2090
+ {
2091
+ ...state,
2092
+ callback: triggerCallback,
2093
+ continuous,
2094
+ debug,
2095
+ helpers,
2096
+ nonce,
2097
+ shouldScroll: !step.disableScrolling && (index !== 0 || scrollToFirstStep),
2098
+ step,
2099
+ store
2100
+ }
2101
+ );
2102
+ content.overlay = /* @__PURE__ */ jsx8(JoyridePortal, { id: "react-joyride-portal", children: /* @__PURE__ */ jsx8(
2103
+ JoyrideOverlay,
2104
+ {
2105
+ ...step,
2106
+ continuous,
2107
+ debug,
2108
+ lifecycle,
2109
+ onClickOverlay: handleClickOverlay
2110
+ }
2111
+ ) });
2112
+ }
2113
+ return /* @__PURE__ */ jsxs3("div", { className: "react-joyride", children: [
2114
+ content.step,
2115
+ content.overlay
2116
+ ] });
2117
+ }
2118
+ var components_default = Joyride;
2119
+ export {
2120
+ ACTIONS,
2121
+ EVENTS,
2122
+ LIFECYCLE,
2123
+ ORIGIN,
2124
+ STATUS,
2125
+ components_default as default
2126
+ };
2127
+ //# sourceMappingURL=index.mjs.map