@numidev/react-joyride 1.0.1

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.

Potentially problematic release.


This version of @numidev/react-joyride might be problematic. Click here for more details.

Files changed (51) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +93 -0
  3. package/dist/index.cjs +2677 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +753 -0
  6. package/dist/index.d.mts +753 -0
  7. package/dist/index.mjs +2638 -0
  8. package/dist/index.mjs.map +1 -0
  9. package/package.json +158 -0
  10. package/src/components/Arrow.tsx +138 -0
  11. package/src/components/Beacon.tsx +141 -0
  12. package/src/components/Floater.tsx +381 -0
  13. package/src/components/Loader.tsx +80 -0
  14. package/src/components/Overlay.tsx +167 -0
  15. package/src/components/Portal.tsx +17 -0
  16. package/src/components/Step.tsx +72 -0
  17. package/src/components/Tooltip/CloseButton.tsx +29 -0
  18. package/src/components/Tooltip/DefaultTooltip.tsx +82 -0
  19. package/src/components/Tooltip/index.tsx +163 -0
  20. package/src/components/TourRenderer.tsx +157 -0
  21. package/src/defaults.ts +64 -0
  22. package/src/global.d.ts +8 -0
  23. package/src/hooks/useControls.ts +219 -0
  24. package/src/hooks/useDebugLogger.ts +58 -0
  25. package/src/hooks/useEventEmitter.ts +55 -0
  26. package/src/hooks/useFocusTrap.ts +72 -0
  27. package/src/hooks/useJoyride.tsx +32 -0
  28. package/src/hooks/useLifecycleEffect.ts +512 -0
  29. package/src/hooks/usePortalElement.ts +49 -0
  30. package/src/hooks/usePropSync.ts +84 -0
  31. package/src/hooks/useScrollEffect.ts +217 -0
  32. package/src/hooks/useTargetPosition.ts +154 -0
  33. package/src/hooks/useTourEngine.ts +106 -0
  34. package/src/index.tsx +23 -0
  35. package/src/literals/index.ts +61 -0
  36. package/src/modules/changes.ts +20 -0
  37. package/src/modules/dom.ts +359 -0
  38. package/src/modules/helpers.tsx +230 -0
  39. package/src/modules/step.ts +156 -0
  40. package/src/modules/store.ts +215 -0
  41. package/src/modules/svg.ts +40 -0
  42. package/src/styles.ts +183 -0
  43. package/src/types/common.ts +315 -0
  44. package/src/types/components.ts +84 -0
  45. package/src/types/events.ts +89 -0
  46. package/src/types/floating.ts +60 -0
  47. package/src/types/index.ts +8 -0
  48. package/src/types/props.ts +124 -0
  49. package/src/types/state.ts +49 -0
  50. package/src/types/step.ts +108 -0
  51. package/src/types/utilities.ts +26 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,2677 @@
1
+ 'use client';
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ //#region \0rolldown/runtime.js
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
+ key = keys[i];
13
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
14
+ get: ((k) => from[k]).bind(null, key),
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
21
+ value: mod,
22
+ enumerable: true
23
+ }) : target, mod));
24
+ //#endregion
25
+ let react = require("react");
26
+ react = __toESM(react);
27
+ let _gilbarbara_hooks = require("@gilbarbara/hooks");
28
+ let use_sync_external_store_shim = require("use-sync-external-store/shim");
29
+ let is_lite = require("is-lite");
30
+ is_lite = __toESM(is_lite);
31
+ let react_innertext = require("react-innertext");
32
+ react_innertext = __toESM(react_innertext);
33
+ let _fastify_deepmerge = require("@fastify/deepmerge");
34
+ _fastify_deepmerge = __toESM(_fastify_deepmerge);
35
+ let _gilbarbara_deep_equal = require("@gilbarbara/deep-equal");
36
+ _gilbarbara_deep_equal = __toESM(_gilbarbara_deep_equal);
37
+ let scroll = require("scroll");
38
+ scroll = __toESM(scroll);
39
+ let scrollparent = require("scrollparent");
40
+ scrollparent = __toESM(scrollparent);
41
+ let react_dom = require("react-dom");
42
+ let _floating_ui_react_dom = require("@floating-ui/react-dom");
43
+ //#region src/defaults.ts
44
+ const defaultOptions = {
45
+ arrowBase: 32,
46
+ arrowColor: "#ffffff",
47
+ arrowSize: 16,
48
+ arrowSpacing: 12,
49
+ backgroundColor: "#ffffff",
50
+ beaconSize: 36,
51
+ beaconTrigger: "click",
52
+ beforeTimeout: 5e3,
53
+ blockTargetInteraction: false,
54
+ buttons: [
55
+ "back",
56
+ "close",
57
+ "primary"
58
+ ],
59
+ closeButtonAction: "close",
60
+ disableFocusTrap: false,
61
+ dismissKeyAction: "close",
62
+ hideOverlay: false,
63
+ loaderDelay: 300,
64
+ offset: 10,
65
+ overlayClickAction: "close",
66
+ overlayColor: "#00000080",
67
+ primaryColor: "#000000",
68
+ scrollDuration: 300,
69
+ scrollOffset: 20,
70
+ showProgress: false,
71
+ skipBeacon: false,
72
+ skipScroll: false,
73
+ spotlightPadding: 10,
74
+ spotlightRadius: 4,
75
+ targetWaitTimeout: 1e3,
76
+ textColor: "#000000",
77
+ width: 380,
78
+ zIndex: 100
79
+ };
80
+ const defaultFloatingOptions = { beaconOptions: { offset: -18 } };
81
+ const defaultLocale = {
82
+ back: "Back",
83
+ close: "Close",
84
+ last: "Last",
85
+ next: "Next",
86
+ nextWithProgress: "Next ({current} of {total})",
87
+ open: "Open the dialog",
88
+ skip: "Skip"
89
+ };
90
+ const defaultStep = {
91
+ isFixed: false,
92
+ locale: defaultLocale,
93
+ placement: "bottom"
94
+ };
95
+ const defaultProps = {
96
+ continuous: false,
97
+ debug: false,
98
+ run: false,
99
+ scrollToFirstStep: false,
100
+ steps: []
101
+ };
102
+ //#endregion
103
+ //#region src/literals/index.ts
104
+ const ACTIONS = {
105
+ INIT: "init",
106
+ START: "start",
107
+ STOP: "stop",
108
+ RESET: "reset",
109
+ PREV: "prev",
110
+ NEXT: "next",
111
+ GO: "go",
112
+ CLOSE: "close",
113
+ SKIP: "skip",
114
+ REPLAY: "replay",
115
+ UPDATE: "update",
116
+ COMPLETE: "complete"
117
+ };
118
+ const EVENTS = {
119
+ TOUR_START: "tour:start",
120
+ STEP_BEFORE_HOOK: "step:before_hook",
121
+ STEP_BEFORE: "step:before",
122
+ SCROLL_START: "scroll:start",
123
+ SCROLL_END: "scroll:end",
124
+ BEACON: "beacon",
125
+ TOOLTIP: "tooltip",
126
+ STEP_AFTER: "step:after",
127
+ STEP_AFTER_HOOK: "step:after_hook",
128
+ TOUR_END: "tour:end",
129
+ TOUR_STATUS: "tour:status",
130
+ TARGET_NOT_FOUND: "error:target_not_found",
131
+ ERROR: "error"
132
+ };
133
+ const LIFECYCLE = {
134
+ INIT: "init",
135
+ READY: "ready",
136
+ BEACON_BEFORE: "beacon_before",
137
+ BEACON: "beacon",
138
+ TOOLTIP_BEFORE: "tooltip_before",
139
+ TOOLTIP: "tooltip",
140
+ COMPLETE: "complete"
141
+ };
142
+ const ORIGIN = {
143
+ BUTTON_BACK: "button_back",
144
+ BUTTON_CLOSE: "button_close",
145
+ BUTTON_PRIMARY: "button_primary",
146
+ BUTTON_SKIP: "button_skip",
147
+ KEYBOARD: "keyboard",
148
+ OVERLAY: "overlay"
149
+ };
150
+ const STATUS = {
151
+ IDLE: "idle",
152
+ READY: "ready",
153
+ WAITING: "waiting",
154
+ RUNNING: "running",
155
+ PAUSED: "paused",
156
+ SKIPPED: "skipped",
157
+ FINISHED: "finished"
158
+ };
159
+ const PORTAL_ELEMENT_ID = "react-joyride-portal";
160
+ //#endregion
161
+ //#region src/modules/helpers.tsx
162
+ /**
163
+ * Remove properties with undefined value from an object
164
+ */
165
+ function cleanUpObject(input) {
166
+ const output = {};
167
+ for (const key in input) if (input[key] !== void 0) output[key] = input[key];
168
+ return output;
169
+ }
170
+ function deepMerge(...objects) {
171
+ return (0, _fastify_deepmerge.default)({
172
+ all: true,
173
+ isMergeableObject: (value) => !(!is_lite.default.plainObject(value) || (0, react.isValidElement)(value))
174
+ })(...objects);
175
+ }
176
+ /**
177
+ * Get Object type
178
+ */
179
+ function getObjectType(value) {
180
+ return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
181
+ }
182
+ function getReactNodeText(input, options = {}) {
183
+ const { defaultValue, step, steps } = options;
184
+ let text = (0, react_innertext.default)(input);
185
+ if (!text) if ((0, react.isValidElement)(input) && !Object.values(input.props).length && getObjectType(input.type) === "function") try {
186
+ text = getReactNodeText(input.type({}), options);
187
+ } catch {
188
+ text = (0, react_innertext.default)(defaultValue);
189
+ }
190
+ else text = (0, react_innertext.default)(defaultValue);
191
+ else if ((text.includes("{current}") || text.includes("{total}")) && step && steps) text = text.replace("{current}", step.toString()).replace("{total}", steps.toString());
192
+ return text;
193
+ }
194
+ /**
195
+ * Log method calls if debug is enabled
196
+ */
197
+ function log(debug, scope, title, ...data) {
198
+ if (!debug) return;
199
+ const now = /* @__PURE__ */ new Date();
200
+ const time = `${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}:${String(now.getSeconds()).padStart(2, "0")}.${String(now.getMilliseconds()).padStart(3, "0")}`;
201
+ console.log(`${scope} %c${title}%c ${time}`, "font-weight: bold", "color: gray; font-weight: normal", ...data);
202
+ }
203
+ /**
204
+ * Merges the defaultProps with literal values with the incoming props, removing undefined values from it that would override the defaultProps.
205
+ * The result is a type-safe object with the defaultProps as required properties.
206
+ */
207
+ function mergeProps(defaultProps, props) {
208
+ const cleanProps = cleanUpObject(props);
209
+ return {
210
+ ...defaultProps,
211
+ ...cleanProps
212
+ };
213
+ }
214
+ /**
215
+ * A function that does nothing.
216
+ */
217
+ function noop() {}
218
+ /**
219
+ * Type-safe Object.keys()
220
+ */
221
+ function objectKeys(input) {
222
+ return Object.keys(input);
223
+ }
224
+ /**
225
+ * Remove properties from an object
226
+ */
227
+ function omit(input, ...filter) {
228
+ if (!is_lite.default.plainObject(input)) throw new TypeError("Expected an object");
229
+ const output = {};
230
+ for (const key in input)
231
+ /* istanbul ignore else */
232
+ if ({}.hasOwnProperty.call(input, key) && !filter.includes(key)) output[key] = input[key];
233
+ return output;
234
+ }
235
+ /**
236
+ * Select properties from an object
237
+ */
238
+ function pick(input, ...filter) {
239
+ if (!is_lite.default.plainObject(input)) throw new TypeError("Expected an object");
240
+ if (!filter.length) return input;
241
+ const output = {};
242
+ for (const key in input)
243
+ /* istanbul ignore else */
244
+ if ({}.hasOwnProperty.call(input, key) && filter.includes(key)) output[key] = input[key];
245
+ return output;
246
+ }
247
+ function replaceLocaleContent(input, step, steps) {
248
+ const replacer = (text) => text.replace("{current}", String(step)).replace("{total}", String(steps));
249
+ if (getObjectType(input) === "string") return replacer(input);
250
+ if (!(0, react.isValidElement)(input)) return input;
251
+ const { children } = input.props;
252
+ if (is_lite.default.string(children) && children.includes("{current}")) return (0, react.cloneElement)(input, { children: replacer(children) });
253
+ if (Array.isArray(children)) return (0, react.cloneElement)(input, { children: children.map((child) => {
254
+ if (typeof child === "string") return replacer(child);
255
+ return replaceLocaleContent(child, step, steps);
256
+ }) });
257
+ if (is_lite.default.function(input.type) && !Object.values(input.props).length) try {
258
+ return replaceLocaleContent(input.type({}), step, steps);
259
+ } catch {
260
+ return input;
261
+ }
262
+ return input;
263
+ }
264
+ /**
265
+ * Sort object keys
266
+ */
267
+ function sortObjectKeys(input) {
268
+ return objectKeys(input).sort().reduce((acc, key) => {
269
+ acc[key] = input[key];
270
+ return acc;
271
+ }, {});
272
+ }
273
+ //#endregion
274
+ //#region src/modules/dom.ts
275
+ function canUseDOM() {
276
+ return !!(typeof window !== "undefined" && window.document?.createElement);
277
+ }
278
+ /**
279
+ * Get the absolute document-relative offset of an element by walking up the offsetParent chain.
280
+ */
281
+ function getAbsoluteOffset(element) {
282
+ let top = 0;
283
+ let left = 0;
284
+ let current = element;
285
+ while (current) {
286
+ top += current.offsetTop;
287
+ left += current.offsetLeft;
288
+ current = current.offsetParent;
289
+ }
290
+ return {
291
+ left,
292
+ top
293
+ };
294
+ }
295
+ /**
296
+ * Find the bounding client rect
297
+ */
298
+ function getClientRect(element) {
299
+ if (!element) return null;
300
+ return element.getBoundingClientRect();
301
+ }
302
+ /**
303
+ * Helper function to get the browser-normalized "document height"
304
+ */
305
+ function getDocumentHeight(median = false) {
306
+ const { body, documentElement } = document;
307
+ if (!body || !documentElement) return 0;
308
+ if (median) {
309
+ const heights = [
310
+ body.scrollHeight,
311
+ body.offsetHeight,
312
+ documentElement.clientHeight,
313
+ documentElement.scrollHeight,
314
+ documentElement.offsetHeight
315
+ ].sort((a, b) => a - b);
316
+ const middle = Math.floor(heights.length / 2);
317
+ if (heights.length % 2 === 0) return (heights[middle - 1] + heights[middle]) / 2;
318
+ return heights[middle];
319
+ }
320
+ return Math.max(body.scrollHeight, body.offsetHeight, documentElement.clientHeight, documentElement.scrollHeight, documentElement.offsetHeight);
321
+ }
322
+ /**
323
+ * Find and return the target DOM element based on a step's 'target'.
324
+ */
325
+ function getElement(element) {
326
+ if (!element) return null;
327
+ if (typeof element === "function") try {
328
+ return element();
329
+ } catch (error) {
330
+ if (process.env.NODE_ENV !== "production") console.error(error);
331
+ return null;
332
+ }
333
+ if (typeof element === "object" && "current" in element) return element.current;
334
+ if (typeof element === "string") try {
335
+ return document.querySelector(element);
336
+ } catch (error) {
337
+ if (process.env.NODE_ENV !== "production") console.error(error);
338
+ return null;
339
+ }
340
+ return element;
341
+ }
342
+ /**
343
+ * Find and return the target DOM element based on a step's 'target'.
344
+ */
345
+ function getElementPosition(element, offset, isFixed) {
346
+ const elementRect = getClientRect(element);
347
+ const parent = getScrollParent(element);
348
+ const hasScrollParent = parent ? !parent.isSameNode(scrollDocument()) : false;
349
+ const isFixedTarget = isFixed ?? hasPosition(element);
350
+ let parentTop = 0;
351
+ let top = elementRect?.top ?? 0;
352
+ if (hasScrollParent && isFixedTarget) top = elementRect?.top ?? 0;
353
+ else if (parent instanceof HTMLElement) {
354
+ parentTop = parent.scrollTop;
355
+ if (!hasScrollParent && !isFixedTarget) top += parentTop;
356
+ if (!parent.isSameNode(scrollDocument())) top += scrollDocument().scrollTop;
357
+ }
358
+ return Math.floor(top - offset);
359
+ }
360
+ /**
361
+ * Get the scroll parent of an element.
362
+ * If the detected parent doesn't actually scroll, fall back to the document.
363
+ */
364
+ function getScrollParent(element, forListener) {
365
+ if (!element) return scrollDocument();
366
+ const parent = (0, scrollparent.default)(element);
367
+ if (parent) {
368
+ if (parent.isSameNode(scrollDocument())) {
369
+ if (forListener) return document;
370
+ return scrollDocument();
371
+ }
372
+ if (!(parent.scrollHeight > parent.offsetHeight)) return scrollDocument();
373
+ }
374
+ return parent;
375
+ }
376
+ function getScrollTargetToCenter(element) {
377
+ const rect = element.getBoundingClientRect();
378
+ const documentElement = scrollDocument();
379
+ const containerCenter = rect.top + rect.height / 2;
380
+ const viewportCenter = window.innerHeight / 2;
381
+ return Math.max(0, documentElement.scrollTop + containerCenter - viewportCenter);
382
+ }
383
+ /**
384
+ * Get the scrollTop position
385
+ */
386
+ function getScrollTo(element, offset) {
387
+ if (!element) return 0;
388
+ const parentElement = (0, scrollparent.default)(element) ?? scrollDocument();
389
+ const scrollMarginTop = parseFloat(getComputedStyle(element).scrollMarginTop) || 0;
390
+ const parentRect = getClientRect(parentElement);
391
+ const parentScrollTop = parentElement.scrollTop ?? 0;
392
+ const { offsetTop = 0, scrollTop = 0 } = parentElement;
393
+ let top = element.getBoundingClientRect().top + scrollTop;
394
+ if (!!offsetTop && (hasCustomScrollParent(element) || hasCustomOffsetParent(element))) {
395
+ const elementRect = element.getBoundingClientRect();
396
+ const elementTopInContainer = elementRect.top - (parentRect?.top ?? 0);
397
+ const elementBottomInContainer = elementTopInContainer + elementRect.height;
398
+ const containerHeight = parentElement.clientHeight;
399
+ const margin = containerHeight * .2;
400
+ if (elementTopInContainer >= margin && elementBottomInContainer <= containerHeight - margin) top = parentScrollTop;
401
+ else top = elementTopInContainer + parentScrollTop;
402
+ }
403
+ const output = Math.floor(top - offset - scrollMarginTop);
404
+ return output < 0 ? 0 : output;
405
+ }
406
+ /**
407
+ * Check if the element has custom offset parent
408
+ */
409
+ function hasCustomOffsetParent(element) {
410
+ return element.offsetParent !== document.body;
411
+ }
412
+ /**
413
+ * Check if the element has custom scroll parent
414
+ */
415
+ function hasCustomScrollParent(element) {
416
+ if (!element) return false;
417
+ const parent = getScrollParent(element);
418
+ return parent ? !parent.isSameNode(scrollDocument()) : false;
419
+ }
420
+ /**
421
+ * Check if an element has fixed/sticky position
422
+ */
423
+ function hasPosition(el, type = "fixed") {
424
+ if (!el || !(el instanceof Element)) return false;
425
+ const { nodeName } = el;
426
+ if (nodeName === "BODY" || nodeName === "HTML") return false;
427
+ if (getComputedStyle(el).position === type) return true;
428
+ if (!el.parentNode) return false;
429
+ return hasPosition(el.parentNode, type);
430
+ }
431
+ /**
432
+ * Check if the element is visible
433
+ */
434
+ function isElementVisible(element) {
435
+ if (!element) return false;
436
+ let parentElement = element;
437
+ while (parentElement) {
438
+ if (parentElement === document.body) break;
439
+ if (parentElement instanceof HTMLElement) {
440
+ const { display, visibility } = getComputedStyle(parentElement);
441
+ if (display === "none" || visibility === "hidden") return false;
442
+ }
443
+ parentElement = parentElement.parentElement ?? null;
444
+ }
445
+ return true;
446
+ }
447
+ function needsScrolling(options) {
448
+ const { isFirstStep, scrollToFirstStep, step, target, targetLifecycle } = options;
449
+ if (step.skipScroll || isFirstStep && !scrollToFirstStep && targetLifecycle !== LIFECYCLE.TOOLTIP || step.placement === "center") return false;
450
+ const parent = target?.isConnected ? getScrollParent(target) : scrollDocument();
451
+ const isCustomScrollParent = parent ? !parent.isSameNode(scrollDocument()) : false;
452
+ if ((step.isFixed || hasPosition(target)) && !isCustomScrollParent) return false;
453
+ return parent.scrollHeight > parent.clientHeight;
454
+ }
455
+ function scrollDocument() {
456
+ return document.scrollingElement ?? document.documentElement;
457
+ }
458
+ /**
459
+ * Scroll to position
460
+ */
461
+ function scrollTo(value, options) {
462
+ const { duration, element } = options;
463
+ let cancel = () => {};
464
+ const promise = new Promise((resolve) => {
465
+ const { scrollTop } = element;
466
+ const limit = value > scrollTop ? value - scrollTop : scrollTop - value;
467
+ cancel = scroll.default.top(element, value, { duration: limit < 100 ? 50 : duration }, () => {
468
+ resolve();
469
+ });
470
+ });
471
+ return {
472
+ cancel,
473
+ promise
474
+ };
475
+ }
476
+ //#endregion
477
+ //#region src/styles.ts
478
+ /**
479
+ * Convert hex to RGB
480
+ */
481
+ function hexToRGB(hex) {
482
+ const properHex = hex.replace(/^#?([\da-f])([\da-f])([\da-f])$/i, (_m, r, g, b) => r + r + g + g + b + b);
483
+ const result = /^#?([\da-f]{2})([\da-f]{2})([\da-f]{2})/i.exec(properHex);
484
+ return result ? [
485
+ parseInt(result[1], 16),
486
+ parseInt(result[2], 16),
487
+ parseInt(result[3], 16)
488
+ ] : [];
489
+ }
490
+ const buttonReset = {
491
+ backgroundColor: "transparent",
492
+ border: 0,
493
+ borderRadius: 0,
494
+ color: "#555555",
495
+ cursor: "pointer",
496
+ fontSize: 16,
497
+ lineHeight: 1,
498
+ padding: 0,
499
+ WebkitAppearance: "none"
500
+ };
501
+ const buttonBase = {
502
+ ...buttonReset,
503
+ borderRadius: 4,
504
+ padding: 8
505
+ };
506
+ function getStyles(props, step) {
507
+ const { styles } = props;
508
+ const mergedStyles = deepMerge(styles ?? {}, step.styles ?? {});
509
+ let { width } = step;
510
+ if (canUseDOM()) width = typeof width === "number" && window.innerWidth < width ? window.innerWidth - 30 : width;
511
+ const overlay = {
512
+ bottom: 0,
513
+ left: 0,
514
+ overflow: "hidden",
515
+ position: "absolute",
516
+ right: 0,
517
+ top: 0,
518
+ zIndex: step.zIndex
519
+ };
520
+ return deepMerge({
521
+ arrow: {
522
+ alignItems: "center",
523
+ color: step.arrowColor,
524
+ display: "inline-flex",
525
+ justifyContent: "center",
526
+ position: "absolute"
527
+ },
528
+ beaconWrapper: {
529
+ ...buttonReset,
530
+ display: "inline-flex",
531
+ borderRadius: "50%",
532
+ position: "relative"
533
+ },
534
+ beacon: {
535
+ height: step.beaconSize,
536
+ width: step.beaconSize
537
+ },
538
+ beaconInner: {
539
+ animation: "joyride-beacon-inner 1.2s infinite ease-in-out",
540
+ backgroundColor: step.primaryColor,
541
+ borderRadius: "50%",
542
+ display: "block",
543
+ height: "50%",
544
+ left: "50%",
545
+ opacity: .7,
546
+ position: "absolute",
547
+ top: "50%",
548
+ transform: "translate(-50%, -50%)",
549
+ width: "50%"
550
+ },
551
+ beaconOuter: {
552
+ animation: "joyride-beacon-outer 1.2s infinite ease-in-out",
553
+ backgroundColor: `rgba(${hexToRGB(step.primaryColor).join(",")}, 0.2)`,
554
+ border: `2px solid ${step.primaryColor}`,
555
+ borderRadius: "50%",
556
+ boxSizing: "border-box",
557
+ display: "block",
558
+ height: "100%",
559
+ left: 0,
560
+ opacity: .9,
561
+ position: "absolute",
562
+ top: 0,
563
+ transformOrigin: "center",
564
+ width: "100%"
565
+ },
566
+ buttonBack: {
567
+ ...buttonBase,
568
+ color: step.primaryColor,
569
+ marginLeft: "auto",
570
+ marginRight: 5
571
+ },
572
+ buttonClose: {
573
+ ...buttonBase,
574
+ color: step.textColor,
575
+ height: 12,
576
+ padding: 8,
577
+ position: "absolute",
578
+ right: 0,
579
+ top: 0,
580
+ width: 12
581
+ },
582
+ buttonPrimary: {
583
+ ...buttonBase,
584
+ backgroundColor: step.primaryColor,
585
+ color: step.backgroundColor
586
+ },
587
+ buttonSkip: {
588
+ ...buttonBase,
589
+ color: step.textColor,
590
+ fontSize: 14
591
+ },
592
+ floater: {
593
+ display: "inline-block",
594
+ filter: "drop-shadow(0 0 3px rgba(0, 0, 0, 0.3))",
595
+ maxWidth: "100%",
596
+ transition: "opacity 0.3s"
597
+ },
598
+ loader: {
599
+ alignItems: "center",
600
+ display: "flex",
601
+ height: 48,
602
+ inset: 0,
603
+ justifyContent: "center",
604
+ pointerEvents: "none",
605
+ position: "fixed",
606
+ width: 48,
607
+ zIndex: step.zIndex + 1
608
+ },
609
+ overlay: {
610
+ ...overlay,
611
+ backgroundColor: step.overlayColor
612
+ },
613
+ spotlight: {},
614
+ tooltip: {
615
+ backgroundColor: step.backgroundColor,
616
+ borderRadius: 5,
617
+ boxSizing: "border-box",
618
+ color: step.textColor,
619
+ fontSize: 16,
620
+ maxWidth: "100%",
621
+ padding: 12,
622
+ position: "relative",
623
+ width
624
+ },
625
+ tooltipContainer: {
626
+ lineHeight: 1.4,
627
+ textAlign: "center"
628
+ },
629
+ tooltipTitle: {
630
+ fontSize: 18,
631
+ margin: 0
632
+ },
633
+ tooltipContent: {
634
+ paddingBottom: 12,
635
+ paddingTop: 12
636
+ },
637
+ tooltipFooter: {
638
+ alignItems: "center",
639
+ display: "flex",
640
+ justifyContent: "flex-end"
641
+ },
642
+ tooltipFooterSpacer: { flex: 1 }
643
+ }, mergedStyles);
644
+ }
645
+ //#endregion
646
+ //#region src/modules/step.ts
647
+ const optionFieldNames = [
648
+ "after",
649
+ "arrowBase",
650
+ "arrowColor",
651
+ "arrowSize",
652
+ "arrowSpacing",
653
+ "backgroundColor",
654
+ "beaconSize",
655
+ "beaconTrigger",
656
+ "before",
657
+ "beforeTimeout",
658
+ "buttons",
659
+ "closeButtonAction",
660
+ "skipBeacon",
661
+ "dismissKeyAction",
662
+ "disableFocusTrap",
663
+ "hideOverlay",
664
+ "skipScroll",
665
+ "blockTargetInteraction",
666
+ "loaderDelay",
667
+ "offset",
668
+ "overlayClickAction",
669
+ "overlayColor",
670
+ "primaryColor",
671
+ "scrollDuration",
672
+ "scrollOffset",
673
+ "showProgress",
674
+ "spotlightPadding",
675
+ "spotlightRadius",
676
+ "targetWaitTimeout",
677
+ "textColor",
678
+ "width",
679
+ "zIndex"
680
+ ];
681
+ function getMergedStep(props, currentStep) {
682
+ if (!currentStep) return null;
683
+ const mergedStep = deepMerge(defaultStep, pick(props, "arrowComponent", "beaconComponent", "floatingOptions", "loaderComponent", "locale", "styles", "tooltipComponent"), currentStep);
684
+ const mergedOptions = deepMerge(defaultOptions, props.options ?? {}, pick(currentStep, ...optionFieldNames));
685
+ const mergedStyles = getStyles(props, {
686
+ ...mergedStep,
687
+ ...mergedOptions
688
+ });
689
+ const floatingOptions = deepMerge(defaultFloatingOptions, props.floatingOptions ?? {}, mergedStep.floatingOptions ?? {});
690
+ return {
691
+ ...mergedStep,
692
+ ...mergedOptions,
693
+ locale: deepMerge(defaultLocale, props.locale ?? {}, mergedStep.locale || {}),
694
+ floatingOptions,
695
+ spotlightPadding: normalizeSpotlightPadding(mergedOptions.spotlightPadding),
696
+ styles: mergedStyles
697
+ };
698
+ }
699
+ function normalizeSpotlightPadding(value) {
700
+ if (typeof value === "number") return {
701
+ top: value,
702
+ right: value,
703
+ bottom: value,
704
+ left: value
705
+ };
706
+ return {
707
+ top: value?.top ?? 0,
708
+ right: value?.right ?? 0,
709
+ bottom: value?.bottom ?? 0,
710
+ left: value?.left ?? 0
711
+ };
712
+ }
713
+ /**
714
+ * Decide if the step shouldn't skip the beacon
715
+ */
716
+ function shouldHideBeacon(step, state, continuous) {
717
+ const { action } = state;
718
+ const withContinuous = continuous && [ACTIONS.PREV, ACTIONS.NEXT].includes(action);
719
+ return step.skipBeacon || step.placement === "center" || withContinuous;
720
+ }
721
+ /**
722
+ * Validate if a step is valid
723
+ */
724
+ function validateStep(step, debug = false) {
725
+ if (!is_lite.default.plainObject(step)) {
726
+ log(debug, "tour", "step must be an object");
727
+ return false;
728
+ }
729
+ if (!step.target) {
730
+ log(debug, "tour", "target is missing from the step");
731
+ return false;
732
+ }
733
+ return true;
734
+ }
735
+ /**
736
+ * Validate if steps are valid
737
+ */
738
+ function validateSteps(steps, debug = false) {
739
+ if (!is_lite.default.array(steps)) {
740
+ log(debug, "tour", "steps must be an array");
741
+ return false;
742
+ }
743
+ return steps.every((d) => validateStep(d, debug));
744
+ }
745
+ //#endregion
746
+ //#region src/modules/store.ts
747
+ var Store = class {
748
+ beaconPosition = null;
749
+ debug;
750
+ eventListeners = /* @__PURE__ */ new Map();
751
+ listeners = /* @__PURE__ */ new Set();
752
+ props;
753
+ snapshot;
754
+ state;
755
+ steps;
756
+ tooltipPosition = null;
757
+ constructor(options) {
758
+ const { initialStepIndex, stepIndex, steps = [] } = options ?? {};
759
+ const isControlled = is_lite.default.number(stepIndex);
760
+ let startIndex = 0;
761
+ this.debug = options?.debug ?? false;
762
+ if (isControlled) {
763
+ startIndex = stepIndex;
764
+ if (is_lite.default.number(initialStepIndex)) log(this.debug, "tour", "initialStepIndex is ignored in controlled mode");
765
+ } else if (is_lite.default.number(initialStepIndex)) {
766
+ if (initialStepIndex >= 0 && initialStepIndex < steps.length) startIndex = initialStepIndex;
767
+ else if (steps.length > 0) log(this.debug, "tour", "initialStepIndex is out of bounds");
768
+ }
769
+ this.props = options ?? { steps: [] };
770
+ this.steps = steps;
771
+ this.state = {
772
+ action: ACTIONS.INIT,
773
+ controlled: isControlled,
774
+ index: startIndex,
775
+ lifecycle: LIFECYCLE.INIT,
776
+ origin: null,
777
+ positioned: false,
778
+ scrolling: false,
779
+ size: steps.length,
780
+ status: steps.length ? STATUS.READY : STATUS.IDLE,
781
+ waiting: false
782
+ };
783
+ this.snapshot = Object.freeze({ ...this.state });
784
+ }
785
+ applyTransitions(draft) {
786
+ if (draft.status === STATUS.WAITING && draft.size > 0) return {
787
+ ...draft,
788
+ status: STATUS.RUNNING
789
+ };
790
+ return draft;
791
+ }
792
+ getStep(nextIndex) {
793
+ return getMergedStep(this.props, this.steps[nextIndex ?? this.state.index]);
794
+ }
795
+ cleanupPositionData = () => {
796
+ this.beaconPosition = null;
797
+ this.tooltipPosition = null;
798
+ };
799
+ getPositionData = (name) => {
800
+ if (name === "beacon") return this.beaconPosition;
801
+ return this.tooltipPosition;
802
+ };
803
+ getServerSnapshot = () => this.snapshot;
804
+ getSnapshot = () => this.snapshot;
805
+ getEventState = () => omit(this.snapshot, "positioned");
806
+ getState = () => omit(this.snapshot, "positioned");
807
+ setPositionData = (name, data) => {
808
+ if ((name === "beacon" ? this.beaconPosition : this.tooltipPosition)?.placement !== data.placement) log(this.debug, `step:${this.state.index}`, "positioned", `${name} ${data.placement}`);
809
+ if (name === "beacon") this.beaconPosition = data;
810
+ else this.tooltipPosition = data;
811
+ if ((this.state.lifecycle === LIFECYCLE.BEACON_BEFORE || this.state.lifecycle === LIFECYCLE.TOOLTIP_BEFORE) && !this.state.positioned) this.updateState({ positioned: true });
812
+ const onPosition = this.getStep()?.floatingOptions?.onPosition;
813
+ if (onPosition) onPosition(data);
814
+ };
815
+ setSteps = (steps) => {
816
+ this.steps = steps;
817
+ this.updateState({ size: steps.length });
818
+ };
819
+ dispatch = (data, controls) => {
820
+ const handlers = this.eventListeners.get(data.type);
821
+ if (handlers) for (const handler of handlers) try {
822
+ handler(data, controls);
823
+ } catch {}
824
+ };
825
+ on = (eventType, handler) => {
826
+ let handlers = this.eventListeners.get(eventType);
827
+ if (!handlers) {
828
+ handlers = /* @__PURE__ */ new Set();
829
+ this.eventListeners.set(eventType, handlers);
830
+ }
831
+ handlers.add(handler);
832
+ return () => {
833
+ handlers.delete(handler);
834
+ };
835
+ };
836
+ subscribe = (listener) => {
837
+ this.listeners.add(listener);
838
+ return () => {
839
+ this.listeners.delete(listener);
840
+ };
841
+ };
842
+ updateState = (patch, forceIndex = false) => {
843
+ const { controlled, index } = this.state;
844
+ const previousSnapshot = this.snapshot;
845
+ const resolvedIndex = controlled && !forceIndex && patch.index !== void 0 ? index : patch.index ?? index;
846
+ const merged = {
847
+ action: patch.action ?? this.state.action,
848
+ controlled,
849
+ index: resolvedIndex,
850
+ lifecycle: patch.lifecycle ?? this.state.lifecycle,
851
+ origin: patch.origin ?? null,
852
+ positioned: patch.positioned ?? this.state.positioned,
853
+ scrolling: patch.scrolling ?? this.state.scrolling,
854
+ size: patch.size ?? this.state.size,
855
+ status: patch.status ?? this.state.status,
856
+ waiting: patch.waiting ?? this.state.waiting
857
+ };
858
+ const final = this.applyTransitions(merged);
859
+ this.state = final;
860
+ if (!(0, _gilbarbara_deep_equal.default)(previousSnapshot, final)) {
861
+ this.snapshot = Object.freeze({ ...final });
862
+ for (const listener of this.listeners) listener(this.snapshot);
863
+ }
864
+ };
865
+ };
866
+ function createStore(options) {
867
+ return new Store(options);
868
+ }
869
+ //#endregion
870
+ //#region src/hooks/useControls.ts
871
+ function getUpdatedIndex(nextIndex, size) {
872
+ return Math.min(Math.max(nextIndex, 0), size);
873
+ }
874
+ function useControls(store, debug, clearFailures) {
875
+ const debugRef = (0, react.useRef)(debug);
876
+ const clearFailuresRef = (0, react.useRef)(clearFailures);
877
+ debugRef.current = debug;
878
+ clearFailuresRef.current = clearFailures;
879
+ return (0, react.useMemo)(() => {
880
+ const getState = () => store.current.getSnapshot();
881
+ const close = (origin = null) => {
882
+ const { index, status } = getState();
883
+ if (status !== STATUS.RUNNING) return;
884
+ store.current.updateState({
885
+ action: ACTIONS.CLOSE,
886
+ index: index + 1,
887
+ origin,
888
+ lifecycle: LIFECYCLE.COMPLETE,
889
+ positioned: false,
890
+ scrolling: false,
891
+ waiting: false
892
+ });
893
+ };
894
+ const go = (nextIndex) => {
895
+ const { controlled, size, status } = getState();
896
+ if (controlled) {
897
+ log(debugRef.current, "tour", "go() is not supported in controlled mode");
898
+ return;
899
+ }
900
+ if (status !== STATUS.RUNNING) return;
901
+ store.current.updateState({
902
+ action: ACTIONS.GO,
903
+ index: nextIndex,
904
+ lifecycle: LIFECYCLE.COMPLETE,
905
+ positioned: false,
906
+ scrolling: false,
907
+ status: nextIndex < size ? status : STATUS.FINISHED,
908
+ waiting: false
909
+ });
910
+ };
911
+ const info = () => omit(store.current.getSnapshot(), "positioned");
912
+ const next = (origin) => {
913
+ const { index, size, status } = getState();
914
+ if (status !== STATUS.RUNNING) return;
915
+ store.current.updateState({
916
+ action: ACTIONS.NEXT,
917
+ index: getUpdatedIndex(index + 1, size),
918
+ lifecycle: LIFECYCLE.COMPLETE,
919
+ origin,
920
+ positioned: false,
921
+ scrolling: false,
922
+ waiting: false
923
+ });
924
+ };
925
+ const open = () => {
926
+ const { status } = getState();
927
+ if (status !== STATUS.RUNNING) return;
928
+ store.current.updateState({
929
+ action: ACTIONS.UPDATE,
930
+ lifecycle: LIFECYCLE.TOOLTIP_BEFORE,
931
+ positioned: false,
932
+ scrolling: false,
933
+ waiting: false
934
+ });
935
+ };
936
+ const previous = (origin) => {
937
+ const { index, size, status } = getState();
938
+ if (status !== STATUS.RUNNING) return;
939
+ store.current.updateState({
940
+ action: ACTIONS.PREV,
941
+ index: getUpdatedIndex(index - 1, size),
942
+ lifecycle: LIFECYCLE.COMPLETE,
943
+ origin,
944
+ positioned: false,
945
+ scrolling: false,
946
+ waiting: false
947
+ });
948
+ };
949
+ const replay = (origin) => {
950
+ const { lifecycle, status } = getState();
951
+ if (status !== STATUS.RUNNING || lifecycle !== LIFECYCLE.TOOLTIP) return;
952
+ store.current.updateState({
953
+ action: ACTIONS.REPLAY,
954
+ lifecycle: LIFECYCLE.COMPLETE,
955
+ origin,
956
+ positioned: false,
957
+ scrolling: false,
958
+ waiting: false
959
+ });
960
+ };
961
+ const reset = (restart = false) => {
962
+ const { controlled } = getState();
963
+ if (controlled) {
964
+ log(debugRef.current, "tour", "reset() is not supported in controlled mode");
965
+ return;
966
+ }
967
+ clearFailuresRef.current();
968
+ store.current.updateState({
969
+ action: ACTIONS.RESET,
970
+ index: 0,
971
+ lifecycle: LIFECYCLE.INIT,
972
+ positioned: false,
973
+ scrolling: false,
974
+ status: restart ? STATUS.RUNNING : STATUS.READY,
975
+ waiting: false
976
+ });
977
+ };
978
+ const skip = (origin) => {
979
+ const { status } = getState();
980
+ if (status !== STATUS.RUNNING) return;
981
+ store.current.updateState({
982
+ action: ACTIONS.SKIP,
983
+ lifecycle: LIFECYCLE.COMPLETE,
984
+ origin,
985
+ positioned: false,
986
+ scrolling: false,
987
+ status: STATUS.SKIPPED,
988
+ waiting: false
989
+ });
990
+ };
991
+ const start = (nextIndex) => {
992
+ const { index, size } = getState();
993
+ clearFailuresRef.current();
994
+ store.current.updateState({
995
+ action: ACTIONS.START,
996
+ index: is_lite.default.number(nextIndex) ? nextIndex : index,
997
+ lifecycle: LIFECYCLE.INIT,
998
+ positioned: false,
999
+ scrolling: false,
1000
+ status: size ? STATUS.RUNNING : STATUS.WAITING,
1001
+ waiting: false
1002
+ }, true);
1003
+ };
1004
+ const stop = (advance = false) => {
1005
+ const { index, status } = getState();
1006
+ if ([STATUS.FINISHED, STATUS.SKIPPED].includes(status)) return;
1007
+ store.current.updateState({
1008
+ action: ACTIONS.STOP,
1009
+ index: index + (advance ? 1 : 0),
1010
+ lifecycle: LIFECYCLE.COMPLETE,
1011
+ positioned: false,
1012
+ scrolling: false,
1013
+ status: STATUS.PAUSED,
1014
+ waiting: false
1015
+ });
1016
+ };
1017
+ return {
1018
+ close,
1019
+ go,
1020
+ info,
1021
+ next,
1022
+ open,
1023
+ prev: previous,
1024
+ replay,
1025
+ reset,
1026
+ skip,
1027
+ start,
1028
+ stop
1029
+ };
1030
+ }, [store]);
1031
+ }
1032
+ //#endregion
1033
+ //#region src/hooks/useDebugLogger.ts
1034
+ const skipFields = new Set(["origin", "positioned"]);
1035
+ function useDebugLogger(store, debug) {
1036
+ const previousRef = (0, react.useRef)(null);
1037
+ (0, react.useEffect)(() => {
1038
+ if (!debug) return;
1039
+ const current = store.current.getSnapshot();
1040
+ log(true, "tour", "init", current);
1041
+ previousRef.current = current;
1042
+ return store.current.subscribe((state) => {
1043
+ const previous = previousRef.current;
1044
+ previousRef.current = state;
1045
+ if (!previous) return;
1046
+ const changes = {};
1047
+ let isTourLevel = false;
1048
+ for (const key of Object.keys(state)) if (state[key] !== previous[key] && !skipFields.has(key)) {
1049
+ changes[key] = {
1050
+ from: previous[key],
1051
+ to: state[key]
1052
+ };
1053
+ if (key === "status" || key === "size") isTourLevel = true;
1054
+ }
1055
+ if (Object.keys(changes).length) {
1056
+ if (!(!isTourLevel && state.index >= state.size)) log(true, isTourLevel ? "tour" : `step:${state.index}`, "state", changes);
1057
+ }
1058
+ });
1059
+ }, [debug, store]);
1060
+ }
1061
+ //#endregion
1062
+ //#region src/hooks/useEventEmitter.ts
1063
+ function useEventEmitter(onEvent, controls, store) {
1064
+ const onEventRef = (0, react.useRef)(onEvent);
1065
+ const controlsRef = (0, react.useRef)(controls);
1066
+ onEventRef.current = onEvent;
1067
+ controlsRef.current = controls;
1068
+ return (0, react.useCallback)((type, step, overrides) => {
1069
+ const data = {
1070
+ ...store.current.getEventState(),
1071
+ error: null,
1072
+ scroll: null,
1073
+ step,
1074
+ type,
1075
+ ...overrides
1076
+ };
1077
+ onEventRef.current?.(data, controlsRef.current);
1078
+ store.current.dispatch(data, controlsRef.current);
1079
+ }, [store]);
1080
+ }
1081
+ //#endregion
1082
+ //#region src/modules/changes.ts
1083
+ function treeChanges(state, previous) {
1084
+ return {
1085
+ hasChanged(key) {
1086
+ return state[key] !== previous[key];
1087
+ },
1088
+ hasChangedTo(key, value) {
1089
+ const current = state[key];
1090
+ const previousValue = previous[key];
1091
+ if (Array.isArray(value)) return value.includes(current) && !value.includes(previousValue);
1092
+ return current === value && previousValue !== value;
1093
+ },
1094
+ previous
1095
+ };
1096
+ }
1097
+ //#endregion
1098
+ //#region src/hooks/useLifecycleEffect.ts
1099
+ function useLifecycleEffect(options) {
1100
+ const { addFailure, controls, emitEvent, previousState, props, state, step, store } = options;
1101
+ const { action, index, lifecycle, positioned, scrolling, size, status } = state;
1102
+ const previousStep = (0, _gilbarbara_hooks.usePrevious)(step) ?? null;
1103
+ const lastAction = (0, react.useRef)(null);
1104
+ const propsRef = (0, react.useRef)(props);
1105
+ const stateRef = (0, react.useRef)(state);
1106
+ const previousStateRef = (0, react.useRef)(previousState);
1107
+ const stepRef = (0, react.useRef)(step);
1108
+ const previousStepRef = (0, react.useRef)(previousStep);
1109
+ const controlsRef = (0, react.useRef)(controls);
1110
+ const pollingRef = (0, react.useRef)(null);
1111
+ const pollingTargetRef = (0, react.useRef)(null);
1112
+ const beforeRef = (0, react.useRef)(null);
1113
+ propsRef.current = props;
1114
+ stateRef.current = state;
1115
+ previousStateRef.current = previousState;
1116
+ stepRef.current = step;
1117
+ previousStepRef.current = previousStep;
1118
+ controlsRef.current = controls;
1119
+ const cleanup = () => {
1120
+ if (pollingRef.current) {
1121
+ clearInterval(pollingRef.current);
1122
+ pollingRef.current = null;
1123
+ }
1124
+ pollingTargetRef.current = null;
1125
+ if (beforeRef.current) {
1126
+ beforeRef.current.cancel();
1127
+ beforeRef.current = null;
1128
+ }
1129
+ };
1130
+ (0, react.useEffect)(() => {
1131
+ if (!previousStateRef.current) return;
1132
+ const { hasChangedTo } = treeChanges(stateRef.current, previousStateRef.current);
1133
+ const isAfterAction = hasChangedTo("action", [
1134
+ ACTIONS.NEXT,
1135
+ ACTIONS.PREV,
1136
+ ACTIONS.SKIP,
1137
+ ACTIONS.CLOSE,
1138
+ ACTIONS.REPLAY
1139
+ ]);
1140
+ const isStaleAfterStart = action === ACTIONS.START && (lastAction.current === ACTIONS.CLOSE || lastAction.current === ACTIONS.REPLAY);
1141
+ if (isAfterAction || isStaleAfterStart) lastAction.current = action;
1142
+ }, [action]);
1143
+ (0, react.useEffect)(() => {
1144
+ if (!previousStateRef.current) return () => {
1145
+ cleanup();
1146
+ };
1147
+ const { hasChanged } = treeChanges(stateRef.current, previousStateRef.current);
1148
+ const currentStep = stepRef.current;
1149
+ if (hasChanged("index")) cleanup();
1150
+ if (status !== STATUS.RUNNING || !currentStep || lifecycle !== LIFECYCLE.INIT) return () => {
1151
+ cleanup();
1152
+ };
1153
+ const { hasChangedTo: hasStatusChangedTo } = treeChanges(stateRef.current, previousStateRef.current);
1154
+ if (hasStatusChangedTo("status", STATUS.RUNNING) && [
1155
+ STATUS.IDLE,
1156
+ STATUS.READY,
1157
+ STATUS.PAUSED
1158
+ ].includes(previousStateRef.current.status)) emitEvent(EVENTS.TOUR_START, currentStep);
1159
+ store.current.cleanupPositionData();
1160
+ const { debug } = propsRef.current;
1161
+ if (currentStep.before && !beforeRef.current) {
1162
+ log(debug, `step:${index}`, "before()", currentStep);
1163
+ beforeRef.current = { cancel: () => {} };
1164
+ store.current.updateState({ waiting: true });
1165
+ emitEvent(EVENTS.STEP_BEFORE_HOOK, currentStep, { action: lastAction.current ?? stateRef.current.action });
1166
+ const proceed = () => {
1167
+ beforeRef.current = null;
1168
+ store.current.updateState({
1169
+ action: lastAction.current ?? stateRef.current.action,
1170
+ waiting: false,
1171
+ lifecycle: LIFECYCLE.READY
1172
+ });
1173
+ };
1174
+ const abortController = new AbortController();
1175
+ const timeout = currentStep.beforeTimeout;
1176
+ beforeRef.current = { cancel: () => abortController.abort() };
1177
+ const timeoutId = timeout ? setTimeout(() => {
1178
+ if (!abortController.signal.aborted) {
1179
+ log(debug, `step:${index}`, "before()", "timed out", `${timeout}ms`);
1180
+ abortController.abort();
1181
+ addFailure(currentStep, "before_hook");
1182
+ emitEvent(EVENTS.ERROR, currentStep, { error: /* @__PURE__ */ new Error("Step before hook timed out") });
1183
+ proceed();
1184
+ }
1185
+ }, timeout) : null;
1186
+ currentStep.before({
1187
+ ...store.current.getState(),
1188
+ action: lastAction.current ?? store.current.getState().action,
1189
+ step: currentStep
1190
+ }).then(() => {
1191
+ if (!abortController.signal.aborted) {
1192
+ if (timeoutId) clearTimeout(timeoutId);
1193
+ proceed();
1194
+ }
1195
+ }).catch((error) => {
1196
+ if (!abortController.signal.aborted) {
1197
+ if (timeoutId) clearTimeout(timeoutId);
1198
+ addFailure(currentStep, "before_hook");
1199
+ emitEvent(EVENTS.ERROR, currentStep, { error: error instanceof Error ? error : new Error(String(error)) });
1200
+ proceed();
1201
+ }
1202
+ });
1203
+ } else if (!beforeRef.current) {
1204
+ if (pollingRef.current && pollingTargetRef.current !== currentStep.target) cleanup();
1205
+ const element = getElement(currentStep.target);
1206
+ if (element && isElementVisible(element)) {
1207
+ cleanup();
1208
+ store.current.updateState({
1209
+ action: lastAction.current ?? ACTIONS.UPDATE,
1210
+ lifecycle: LIFECYCLE.READY,
1211
+ waiting: false
1212
+ });
1213
+ } else if (currentStep.targetWaitTimeout === 0) store.current.updateState({
1214
+ action: lastAction.current ?? ACTIONS.UPDATE,
1215
+ lifecycle: LIFECYCLE.READY,
1216
+ waiting: false
1217
+ });
1218
+ else if (!pollingRef.current) {
1219
+ const { targetWaitTimeout } = currentStep;
1220
+ const startTime = Date.now();
1221
+ pollingTargetRef.current = currentStep.target;
1222
+ log(debug, `step:${index}`, "polling", "started", `${targetWaitTimeout}ms`);
1223
+ store.current.updateState({ waiting: true });
1224
+ pollingRef.current = setInterval(() => {
1225
+ const el = getElement(currentStep.target);
1226
+ const elapsed = Date.now() - startTime;
1227
+ const timedOut = elapsed >= targetWaitTimeout;
1228
+ if (el && isElementVisible(el) || timedOut) {
1229
+ log(debug, `step:${index}`, "polling", el && isElementVisible(el) ? "found" : "timed out", `${elapsed}ms`);
1230
+ cleanup();
1231
+ store.current.updateState({
1232
+ action: lastAction.current ?? ACTIONS.UPDATE,
1233
+ lifecycle: LIFECYCLE.READY,
1234
+ waiting: false
1235
+ });
1236
+ }
1237
+ }, 100);
1238
+ }
1239
+ }
1240
+ return () => {
1241
+ cleanup();
1242
+ };
1243
+ }, [
1244
+ addFailure,
1245
+ emitEvent,
1246
+ index,
1247
+ lifecycle,
1248
+ status,
1249
+ store
1250
+ ]);
1251
+ (0, react.useEffect)(() => {
1252
+ if (!previousStateRef.current) return;
1253
+ const { hasChanged, hasChangedTo, previous } = treeChanges(stateRef.current, previousStateRef.current);
1254
+ const currentStep = stepRef.current;
1255
+ if (!currentStep) return;
1256
+ const element = getElement(currentStep.target);
1257
+ const elementExists = !!element;
1258
+ if (elementExists && isElementVisible(element)) {
1259
+ if (hasChangedTo("lifecycle", LIFECYCLE.READY) && previous.lifecycle === LIFECYCLE.INIT) emitEvent(EVENTS.STEP_BEFORE, currentStep, { action: lastAction.current ?? stateRef.current.action });
1260
+ if (hasChangedTo("lifecycle", LIFECYCLE.READY)) {
1261
+ const currentState = stateRef.current;
1262
+ const finalLifecycle = shouldHideBeacon(currentStep, currentState, propsRef.current.continuous) ? LIFECYCLE.TOOLTIP : LIFECYCLE.BEACON;
1263
+ const target = getElement(currentStep.scrollTarget ?? currentStep.spotlightTarget ?? currentStep.target);
1264
+ const willScroll = needsScrolling({
1265
+ isFirstStep: currentState.index === 0,
1266
+ scrollToFirstStep: propsRef.current.scrollToFirstStep,
1267
+ step: currentStep,
1268
+ target,
1269
+ targetLifecycle: finalLifecycle
1270
+ });
1271
+ const beforeLifecycle = finalLifecycle === LIFECYCLE.TOOLTIP ? LIFECYCLE.TOOLTIP_BEFORE : LIFECYCLE.BEACON_BEFORE;
1272
+ log(propsRef.current.debug, `step:${index}`, "scroll", willScroll ? "needed" : "skipped");
1273
+ store.current.updateState({
1274
+ action: ACTIONS.UPDATE,
1275
+ lifecycle: beforeLifecycle,
1276
+ scrolling: willScroll
1277
+ });
1278
+ }
1279
+ } else if (stateRef.current.status === STATUS.RUNNING && lifecycle !== LIFECYCLE.INIT && lifecycle !== LIFECYCLE.COMPLETE && hasChanged("lifecycle")) {
1280
+ log(propsRef.current.debug, `step:${index}`, elementExists ? "Target not visible" : "Target not mounted", currentStep);
1281
+ addFailure(currentStep, "target_not_found");
1282
+ emitEvent(EVENTS.TARGET_NOT_FOUND, currentStep);
1283
+ const currentState = stateRef.current;
1284
+ if (!currentState.controlled) store.current.updateState({
1285
+ action: ACTIONS.UPDATE,
1286
+ index: currentState.index + (currentState.action === ACTIONS.PREV ? -1 : 1),
1287
+ lifecycle: LIFECYCLE.INIT
1288
+ });
1289
+ }
1290
+ }, [
1291
+ addFailure,
1292
+ emitEvent,
1293
+ index,
1294
+ lifecycle,
1295
+ store
1296
+ ]);
1297
+ (0, react.useEffect)(() => {
1298
+ if (!previousStateRef.current) return;
1299
+ const { hasChangedTo, previous } = treeChanges(stateRef.current, previousStateRef.current);
1300
+ const currentStep = stepRef.current;
1301
+ const previousStepValue = previousStepRef.current;
1302
+ if (currentStep && hasChangedTo("lifecycle", LIFECYCLE.TOOLTIP_BEFORE) && previous.lifecycle === LIFECYCLE.BEACON) {
1303
+ const target = getElement(currentStep.scrollTarget ?? currentStep.spotlightTarget ?? currentStep.target);
1304
+ if (needsScrolling({
1305
+ isFirstStep: stateRef.current.index === 0,
1306
+ scrollToFirstStep: propsRef.current.scrollToFirstStep,
1307
+ step: currentStep,
1308
+ target,
1309
+ targetLifecycle: LIFECYCLE.TOOLTIP
1310
+ })) {
1311
+ store.current.updateState({
1312
+ scrolling: true,
1313
+ positioned: false
1314
+ });
1315
+ return;
1316
+ }
1317
+ }
1318
+ const isBeforePhase = lifecycle === LIFECYCLE.BEACON_BEFORE || lifecycle === LIFECYCLE.TOOLTIP_BEFORE;
1319
+ if (currentStep && isBeforePhase && !scrolling) {
1320
+ const finalLifecycle = lifecycle === LIFECYCLE.TOOLTIP_BEFORE ? LIFECYCLE.TOOLTIP : LIFECYCLE.BEACON;
1321
+ store.current.updateState({
1322
+ action: ACTIONS.UPDATE,
1323
+ lifecycle: finalLifecycle
1324
+ });
1325
+ }
1326
+ if (currentStep && hasChangedTo("lifecycle", LIFECYCLE.BEACON)) emitEvent(EVENTS.BEACON, currentStep);
1327
+ if (currentStep && hasChangedTo("lifecycle", LIFECYCLE.TOOLTIP)) emitEvent(EVENTS.TOOLTIP, currentStep);
1328
+ const currentState = stateRef.current;
1329
+ if ((currentState.status === STATUS.RUNNING || currentState.controlled && currentState.status === STATUS.PAUSED && !!currentStep) && previousStepValue && hasChangedTo("lifecycle", LIFECYCLE.COMPLETE) && previous.lifecycle === LIFECYCLE.TOOLTIP) {
1330
+ emitEvent(EVENTS.STEP_AFTER, previousStepValue, {
1331
+ action: lastAction.current ?? ACTIONS.UPDATE,
1332
+ index: previous.index ?? currentState.index,
1333
+ lifecycle: currentState.lifecycle
1334
+ });
1335
+ if (previousStepValue.after) {
1336
+ emitEvent(EVENTS.STEP_AFTER_HOOK, previousStepValue, {
1337
+ action: lastAction.current ?? ACTIONS.UPDATE,
1338
+ index: previous.index ?? currentState.index,
1339
+ lifecycle: currentState.lifecycle
1340
+ });
1341
+ try {
1342
+ previousStepValue.after({
1343
+ ...store.current.getState(),
1344
+ action: lastAction.current ?? ACTIONS.UPDATE,
1345
+ index: previous.index ?? currentState.index,
1346
+ lifecycle: currentState.lifecycle,
1347
+ step: previousStepValue
1348
+ });
1349
+ } catch {}
1350
+ }
1351
+ }
1352
+ }, [
1353
+ emitEvent,
1354
+ lifecycle,
1355
+ positioned,
1356
+ scrolling,
1357
+ store
1358
+ ]);
1359
+ (0, react.useEffect)(() => {
1360
+ if (!previousStateRef.current) return;
1361
+ const { hasChangedTo, previous } = treeChanges(stateRef.current, previousStateRef.current);
1362
+ const currentStep = stepRef.current;
1363
+ const previousStepValue = previousStepRef.current;
1364
+ if (hasChangedTo("action", ACTIONS.REPLAY) && hasChangedTo("lifecycle", LIFECYCLE.COMPLETE)) {
1365
+ store.current.updateState({ lifecycle: LIFECYCLE.INIT });
1366
+ return;
1367
+ }
1368
+ if (size && !currentStep && lifecycle === LIFECYCLE.INIT) store.current.updateState({
1369
+ action: ACTIONS.UPDATE,
1370
+ lifecycle: LIFECYCLE.COMPLETE,
1371
+ status: STATUS.FINISHED
1372
+ });
1373
+ if (!stateRef.current.controlled && status === STATUS.RUNNING && hasChangedTo("lifecycle", LIFECYCLE.COMPLETE) && index < size) store.current.updateState({
1374
+ action: ACTIONS.UPDATE,
1375
+ lifecycle: LIFECYCLE.INIT
1376
+ });
1377
+ if (hasChangedTo("lifecycle", LIFECYCLE.COMPLETE) && index >= size) store.current.updateState({
1378
+ action: ACTIONS.UPDATE,
1379
+ lifecycle: LIFECYCLE.COMPLETE,
1380
+ status: STATUS.FINISHED
1381
+ });
1382
+ const tourEndStep = currentStep ?? previousStepValue ?? getMergedStep(propsRef.current, propsRef.current.steps[index - 1]);
1383
+ if (tourEndStep && hasChangedTo("status", [STATUS.FINISHED, STATUS.SKIPPED])) {
1384
+ let tourEndIndex;
1385
+ if (currentStep) tourEndIndex = index;
1386
+ else if (previousStepValue) tourEndIndex = previous.index ?? index;
1387
+ else tourEndIndex = index - 1;
1388
+ emitEvent(EVENTS.TOUR_END, tourEndStep, { index: tourEndIndex });
1389
+ if (!stateRef.current.controlled) controlsRef.current.reset();
1390
+ lastAction.current = null;
1391
+ }
1392
+ if (currentStep && hasChangedTo("action", ACTIONS.STOP)) {
1393
+ lastAction.current = null;
1394
+ emitEvent(EVENTS.TOUR_STATUS, currentStep);
1395
+ }
1396
+ if (currentStep && hasChangedTo("action", ACTIONS.RESET)) {
1397
+ emitEvent(EVENTS.TOUR_STATUS, currentStep);
1398
+ lastAction.current = null;
1399
+ }
1400
+ }, [
1401
+ action,
1402
+ emitEvent,
1403
+ index,
1404
+ lifecycle,
1405
+ size,
1406
+ status,
1407
+ store
1408
+ ]);
1409
+ }
1410
+ //#endregion
1411
+ //#region src/hooks/usePropSync.ts
1412
+ function usePropSync({ controls, emitEvent, props, state, store }) {
1413
+ const { debug, initialStepIndex, run, stepIndex, steps } = props;
1414
+ const previousPropsRef = (0, react.useRef)(void 0);
1415
+ const stateRef = (0, react.useRef)(state);
1416
+ const controlsRef = (0, react.useRef)(controls);
1417
+ stateRef.current = state;
1418
+ controlsRef.current = controls;
1419
+ (0, react.useEffect)(() => {
1420
+ const previousProps = previousPropsRef.current;
1421
+ previousPropsRef.current = props;
1422
+ if (!previousProps || props === previousProps) return;
1423
+ const { hasChanged } = treeChanges(props, previousProps);
1424
+ if (!(0, _gilbarbara_deep_equal.default)(previousProps.steps, steps)) if (validateSteps(steps, debug)) store.current.setSteps(steps);
1425
+ else {
1426
+ log(debug, "tour", "Steps are not valid", steps);
1427
+ emitEvent(EVENTS.ERROR, steps[0] ?? {
1428
+ target: "",
1429
+ content: ""
1430
+ }, { error: /* @__PURE__ */ new Error("Steps are not valid") });
1431
+ }
1432
+ if (hasChanged("run")) if (run) {
1433
+ if (store.current.getState().size) controlsRef.current.start(stepIndex ?? initialStepIndex);
1434
+ } else controlsRef.current.stop();
1435
+ else if (is_lite.default.number(stepIndex) && hasChanged("stepIndex")) {
1436
+ const nextAction = is_lite.default.number(previousProps.stepIndex) && previousProps.stepIndex < stepIndex ? ACTIONS.NEXT : ACTIONS.PREV;
1437
+ if (![STATUS.FINISHED, STATUS.SKIPPED].includes(stateRef.current.status)) store.current.updateState({
1438
+ action: nextAction,
1439
+ index: stepIndex,
1440
+ lifecycle: LIFECYCLE.INIT,
1441
+ positioned: false
1442
+ }, true);
1443
+ }
1444
+ }, [
1445
+ debug,
1446
+ emitEvent,
1447
+ initialStepIndex,
1448
+ props,
1449
+ run,
1450
+ stepIndex,
1451
+ steps,
1452
+ store
1453
+ ]);
1454
+ }
1455
+ //#endregion
1456
+ //#region src/hooks/useScrollEffect.ts
1457
+ function adjustForPlacement(scrollY, options) {
1458
+ const { beaconPosition, lifecycle, scrollOffset, step } = options;
1459
+ if (step.scrollTarget || step.spotlightTarget) return Math.max(0, scrollY);
1460
+ let adjustedY = scrollY - step.spotlightPadding.top;
1461
+ if (lifecycle === LIFECYCLE.BEACON_BEFORE && beaconPosition?.placement) {
1462
+ const y = getMainAxisOffset(beaconPosition);
1463
+ if (!["bottom"].includes(beaconPosition.placement)) adjustedY += Math.floor(y - scrollOffset);
1464
+ } else if (lifecycle === LIFECYCLE.TOOLTIP_BEFORE) {
1465
+ const { placement } = step;
1466
+ if (placement === "top") {
1467
+ const floaterHeight = document.querySelector(".react-joyride__floater")?.getBoundingClientRect().height ?? 0;
1468
+ const arrowSize = step.floatingOptions?.hideArrow ? 0 : step.arrowSize;
1469
+ const gap = step.offset + step.spotlightPadding.top + arrowSize;
1470
+ adjustedY -= floaterHeight + gap;
1471
+ } else if (placement === "left" || placement === "right") {
1472
+ const floaterHeight = document.querySelector(".react-joyride__floater")?.getBoundingClientRect().height ?? 0;
1473
+ const targetHeight = getElement(step.target)?.getBoundingClientRect().height ?? 0;
1474
+ const floaterTopY = scrollOffset + step.spotlightPadding.top + targetHeight / 2 - floaterHeight / 2;
1475
+ if (floaterTopY < scrollOffset) adjustedY -= scrollOffset - floaterTopY;
1476
+ }
1477
+ }
1478
+ return Math.max(0, adjustedY);
1479
+ }
1480
+ function getMainAxisOffset(data) {
1481
+ const offsetData = data.middlewareData?.offset;
1482
+ if (!offsetData) return 0;
1483
+ return ["left", "right"].some((p) => data.placement.startsWith(p)) ? offsetData.x : offsetData.y;
1484
+ }
1485
+ function useScrollEffect({ emitEvent, previousState, props, state, step, store }) {
1486
+ const { index, lifecycle, positioned, scrolling, status } = state;
1487
+ const cancelScrollRef = (0, react.useRef)(null);
1488
+ const stateRef = (0, react.useRef)(state);
1489
+ const previousStateRef = (0, react.useRef)(previousState);
1490
+ const propsRef = (0, react.useRef)(props);
1491
+ const stepRef = (0, react.useRef)(step);
1492
+ stateRef.current = state;
1493
+ previousStateRef.current = previousState;
1494
+ propsRef.current = props;
1495
+ stepRef.current = step;
1496
+ (0, react.useEffect)(() => {
1497
+ return () => {
1498
+ cancelScrollRef.current?.();
1499
+ };
1500
+ }, []);
1501
+ (0, react.useEffect)(() => {
1502
+ if (!previousStateRef.current || !stepRef.current) return;
1503
+ const { hasChangedTo } = treeChanges(stateRef.current, previousStateRef.current);
1504
+ const currentStep = stepRef.current;
1505
+ const { debug } = propsRef.current;
1506
+ const { scrollDuration } = currentStep;
1507
+ const isBeforePhase = lifecycle === LIFECYCLE.BEACON_BEFORE || lifecycle === LIFECYCLE.TOOLTIP_BEFORE;
1508
+ if (status === STATUS.RUNNING && isBeforePhase && scrolling && hasChangedTo("positioned", true)) {
1509
+ const target = getElement(currentStep.scrollTarget ?? currentStep.spotlightTarget ?? currentStep.target);
1510
+ const beaconPosition = store.current.getPositionData("beacon");
1511
+ const scrollParent = getScrollParent(target);
1512
+ const hasCustomScroll = scrollParent ? !scrollParent.isSameNode(scrollDocument()) : false;
1513
+ cancelScrollRef.current?.();
1514
+ const handleScroll = async () => {
1515
+ if (hasCustomScroll && !hasPosition(scrollParent)) {
1516
+ const pageElement = scrollDocument();
1517
+ const pageScrollY = getScrollTargetToCenter(scrollParent);
1518
+ const pageScrollData = {
1519
+ initial: pageElement.scrollTop,
1520
+ target: pageScrollY,
1521
+ element: pageElement,
1522
+ duration: scrollDuration
1523
+ };
1524
+ emitEvent(EVENTS.SCROLL_START, currentStep, { scroll: pageScrollData });
1525
+ const { cancel: cancelPage, promise: pagePromise } = scrollTo(pageScrollY, {
1526
+ element: pageElement,
1527
+ duration: scrollDuration
1528
+ });
1529
+ cancelScrollRef.current = cancelPage;
1530
+ await pagePromise;
1531
+ emitEvent(EVENTS.SCROLL_END, currentStep, { scroll: pageScrollData });
1532
+ }
1533
+ const baseScrollY = Math.floor(getScrollTo(target, currentStep.scrollOffset)) || 0;
1534
+ const scrollY = hasCustomScroll ? baseScrollY : adjustForPlacement(baseScrollY, {
1535
+ beaconPosition,
1536
+ lifecycle,
1537
+ scrollOffset: currentStep.scrollOffset,
1538
+ step: currentStep
1539
+ });
1540
+ log(debug, `step:${index}`, "scroll", hasCustomScroll ? "custom" : "document", `${baseScrollY} → ${scrollY}`);
1541
+ const scrollElement = scrollParent;
1542
+ const scrollData = {
1543
+ initial: scrollElement.scrollTop,
1544
+ target: scrollY,
1545
+ element: scrollElement,
1546
+ duration: scrollDuration
1547
+ };
1548
+ emitEvent(EVENTS.SCROLL_START, currentStep, { scroll: scrollData });
1549
+ const { cancel, promise } = scrollTo(scrollY, {
1550
+ element: scrollElement,
1551
+ duration: scrollDuration
1552
+ });
1553
+ cancelScrollRef.current = cancel;
1554
+ await promise;
1555
+ emitEvent(EVENTS.SCROLL_END, currentStep, { scroll: scrollData });
1556
+ store.current.updateState({ scrolling: false });
1557
+ };
1558
+ handleScroll().catch(() => {
1559
+ store.current.updateState({ scrolling: false });
1560
+ });
1561
+ }
1562
+ }, [
1563
+ emitEvent,
1564
+ index,
1565
+ lifecycle,
1566
+ positioned,
1567
+ scrolling,
1568
+ status,
1569
+ store
1570
+ ]);
1571
+ }
1572
+ //#endregion
1573
+ //#region src/hooks/useTourEngine.ts
1574
+ function useTourEngine(props) {
1575
+ const mergedProps = (0, _gilbarbara_hooks.useMemoDeepCompare)(() => mergeProps(defaultProps, props), [props]);
1576
+ const { debug, initialStepIndex, onEvent, run, stepIndex, steps } = mergedProps;
1577
+ const store = (0, react.useRef)(createStore(mergedProps));
1578
+ const state = (0, use_sync_external_store_shim.useSyncExternalStore)(store.current.subscribe, store.current.getSnapshot, store.current.getServerSnapshot);
1579
+ const [failures, setFailures] = (0, react.useState)([]);
1580
+ const addFailure = (0, react.useCallback)((failedStep, reason) => {
1581
+ setFailures((previous) => [...previous, {
1582
+ reason,
1583
+ step: failedStep
1584
+ }]);
1585
+ }, []);
1586
+ const clearFailures = (0, react.useCallback)(() => {
1587
+ setFailures([]);
1588
+ }, []);
1589
+ useDebugLogger(store, debug);
1590
+ const controls = useControls(store, debug, clearFailures);
1591
+ const emitEvent = useEventEmitter(onEvent, controls, store);
1592
+ const { index, size, status } = state;
1593
+ const previousState = (0, _gilbarbara_hooks.usePrevious)(state);
1594
+ const step = (0, react.useMemo)(() => getMergedStep(mergedProps, steps[index]), [
1595
+ index,
1596
+ mergedProps,
1597
+ steps
1598
+ ]);
1599
+ (0, _gilbarbara_hooks.useMount)(() => {
1600
+ if (run && size && validateSteps(steps, debug)) controls.start(stepIndex ?? initialStepIndex);
1601
+ });
1602
+ (0, _gilbarbara_hooks.useUpdateEffect)(() => {
1603
+ if (run && size && status === STATUS.IDLE) store.current.updateState({ status: STATUS.READY });
1604
+ }, [
1605
+ run,
1606
+ size,
1607
+ status
1608
+ ]);
1609
+ usePropSync({
1610
+ controls,
1611
+ emitEvent,
1612
+ props: mergedProps,
1613
+ state,
1614
+ store
1615
+ });
1616
+ useLifecycleEffect({
1617
+ addFailure,
1618
+ controls,
1619
+ emitEvent,
1620
+ previousState,
1621
+ props: mergedProps,
1622
+ state,
1623
+ step,
1624
+ store
1625
+ });
1626
+ useScrollEffect({
1627
+ emitEvent,
1628
+ previousState,
1629
+ props: mergedProps,
1630
+ state,
1631
+ step,
1632
+ store
1633
+ });
1634
+ return {
1635
+ controls,
1636
+ failures,
1637
+ mergedProps,
1638
+ state,
1639
+ step,
1640
+ store
1641
+ };
1642
+ }
1643
+ //#endregion
1644
+ //#region src/hooks/usePortalElement.ts
1645
+ function usePortalElement(portalElement) {
1646
+ const [element, setElement] = (0, react.useState)(null);
1647
+ (0, react.useEffect)(() => {
1648
+ let createdElement = null;
1649
+ let isExternal = false;
1650
+ if (portalElement) if (is_lite.default.domElement(portalElement)) {
1651
+ createdElement = portalElement;
1652
+ isExternal = true;
1653
+ } else {
1654
+ const portal = document.querySelector(portalElement);
1655
+ if (portal) createdElement = portal;
1656
+ }
1657
+ else {
1658
+ const portal = document.createElement("div");
1659
+ portal.id = PORTAL_ELEMENT_ID;
1660
+ document.body.appendChild(portal);
1661
+ createdElement = portal;
1662
+ }
1663
+ setElement(createdElement);
1664
+ return () => {
1665
+ if (!createdElement || isExternal) return;
1666
+ if (createdElement.parentNode === document.body) document.body.removeChild(createdElement);
1667
+ };
1668
+ }, [portalElement]);
1669
+ return element;
1670
+ }
1671
+ //#endregion
1672
+ //#region src/components/Loader.tsx
1673
+ const spinnerStyles = {
1674
+ animation: "joyride-loader-spin 1s linear infinite",
1675
+ border: "5px solid rgba(0, 0, 0, 0.1)",
1676
+ borderRadius: "50%",
1677
+ borderTopColor: "#555"
1678
+ };
1679
+ function JoyrideLoader({ nonce, step }) {
1680
+ const { loaderComponent } = step;
1681
+ const hasLoaderComponent = Boolean(loaderComponent);
1682
+ (0, react.useEffect)(() => {
1683
+ if (hasLoaderComponent) return noop;
1684
+ if (document.getElementById("joyride-loader-animation")) return noop;
1685
+ const style = document.createElement("style");
1686
+ style.id = "joyride-loader-animation";
1687
+ if (nonce) style.setAttribute("nonce", nonce);
1688
+ style.appendChild(document.createTextNode(`
1689
+ @keyframes joyride-loader-spin {
1690
+ to { transform: rotate(360deg); }
1691
+ }
1692
+ `));
1693
+ document.head.appendChild(style);
1694
+ return () => {
1695
+ const insertedStyle = document.getElementById("joyride-loader-animation");
1696
+ if (insertedStyle?.parentNode) insertedStyle.parentNode.removeChild(insertedStyle);
1697
+ };
1698
+ }, [hasLoaderComponent, nonce]);
1699
+ if (loaderComponent === null) return null;
1700
+ const { height, width, ...loaderStyle } = step.styles.loader;
1701
+ let content;
1702
+ if (loaderComponent) {
1703
+ const CustomLoader = loaderComponent;
1704
+ content = /* @__PURE__ */ react.default.createElement(CustomLoader, { step });
1705
+ } else content = /* @__PURE__ */ react.default.createElement("div", { style: {
1706
+ ...spinnerStyles,
1707
+ height,
1708
+ width,
1709
+ borderTopColor: step.primaryColor
1710
+ } });
1711
+ return /* @__PURE__ */ react.default.createElement("div", {
1712
+ className: "react-joyride__loader",
1713
+ "data-testid": "loader",
1714
+ style: loaderStyle
1715
+ }, content);
1716
+ }
1717
+ //#endregion
1718
+ //#region src/hooks/useTargetPosition.ts
1719
+ const defaultRect = {
1720
+ height: 0,
1721
+ isFixed: false,
1722
+ left: 0,
1723
+ top: 0,
1724
+ width: 0
1725
+ };
1726
+ function computeRect(target, spotlightPadding) {
1727
+ const element = getElement(target);
1728
+ if (!element) return defaultRect;
1729
+ const elementRect = getClientRect(element);
1730
+ const isFixed = hasPosition(element);
1731
+ const top = getElementPosition(element, spotlightPadding.top, isFixed);
1732
+ return {
1733
+ height: Math.round((elementRect?.height ?? 0) + spotlightPadding.top + spotlightPadding.bottom),
1734
+ isFixed,
1735
+ left: Math.round((elementRect?.left ?? 0) - spotlightPadding.left),
1736
+ top,
1737
+ width: Math.round((elementRect?.width ?? 0) + spotlightPadding.left + spotlightPadding.right)
1738
+ };
1739
+ }
1740
+ function useTargetPosition(target, spotlightPadding, force) {
1741
+ const [rect, setRect] = (0, react.useState)(() => computeRect(target, spotlightPadding));
1742
+ const timeoutRef = (0, react.useRef)(void 0);
1743
+ const scrollParentRef = (0, react.useRef)(null);
1744
+ const previousForceRef = (0, react.useRef)(force);
1745
+ const observerRef = (0, react.useRef)(null);
1746
+ const updateRect = (0, react.useCallback)(() => {
1747
+ clearTimeout(timeoutRef.current);
1748
+ timeoutRef.current = window.setTimeout(() => {
1749
+ setRect((previous) => {
1750
+ const next = computeRect(target, spotlightPadding);
1751
+ if (previous.top === next.top && previous.left === next.left && previous.width === next.width && previous.height === next.height && previous.isFixed === next.isFixed) return previous;
1752
+ return next;
1753
+ });
1754
+ }, 100);
1755
+ }, [target, spotlightPadding]);
1756
+ (0, react.useEffect)(() => {
1757
+ let mutationObserver = null;
1758
+ const setup = (element) => {
1759
+ scrollParentRef.current = getScrollParent(element, true);
1760
+ if (scrollParentRef.current) scrollParentRef.current.addEventListener("scroll", updateRect, { passive: true });
1761
+ window.addEventListener("scroll", updateRect, { passive: true });
1762
+ window.addEventListener("resize", updateRect);
1763
+ if (typeof ResizeObserver !== "undefined") {
1764
+ observerRef.current = new ResizeObserver(updateRect);
1765
+ observerRef.current.observe(element);
1766
+ }
1767
+ setRect(computeRect(target, spotlightPadding));
1768
+ };
1769
+ const element = getElement(target);
1770
+ if (element) setup(element);
1771
+ else {
1772
+ mutationObserver = new MutationObserver(() => {
1773
+ const el = getElement(target);
1774
+ if (el) {
1775
+ mutationObserver?.disconnect();
1776
+ mutationObserver = null;
1777
+ setup(el);
1778
+ }
1779
+ });
1780
+ mutationObserver.observe(document.body, {
1781
+ childList: true,
1782
+ subtree: true
1783
+ });
1784
+ }
1785
+ return () => {
1786
+ mutationObserver?.disconnect();
1787
+ if (scrollParentRef.current) scrollParentRef.current.removeEventListener("scroll", updateRect);
1788
+ window.removeEventListener("scroll", updateRect);
1789
+ window.removeEventListener("resize", updateRect);
1790
+ observerRef.current?.disconnect();
1791
+ clearTimeout(timeoutRef.current);
1792
+ };
1793
+ }, [
1794
+ target,
1795
+ spotlightPadding,
1796
+ updateRect
1797
+ ]);
1798
+ (0, react.useEffect)(() => {
1799
+ if (previousForceRef.current && !force) setRect(computeRect(target, spotlightPadding));
1800
+ previousForceRef.current = force;
1801
+ }, [
1802
+ force,
1803
+ target,
1804
+ spotlightPadding
1805
+ ]);
1806
+ let finalRect = rect;
1807
+ if (previousForceRef.current && !force) finalRect = computeRect(target, spotlightPadding);
1808
+ return finalRect;
1809
+ }
1810
+ //#endregion
1811
+ //#region src/modules/svg.ts
1812
+ function generateOverlayPath(overlayWidth, overlayHeight, cutout) {
1813
+ let path = `M0 0H${overlayWidth}V${overlayHeight}H0Z`;
1814
+ if (cutout) path += ` ${cutout}`;
1815
+ return path;
1816
+ }
1817
+ function generateSpotlightPath(x, y, width, height, borderRadius) {
1818
+ if (width <= 0 || height <= 0) return "";
1819
+ const r = Math.max(0, Math.min(borderRadius, width / 2, height / 2));
1820
+ let path = `M${x + r} ${y}`;
1821
+ path += `H${x + width - r}`;
1822
+ path += `A${r} ${r} 0 0 1 ${x + width} ${y + r}`;
1823
+ path += `V${y + height - r}`;
1824
+ path += `A${r} ${r} 0 0 1 ${x + width - r} ${y + height}`;
1825
+ path += `H${x + r}`;
1826
+ path += `A${r} ${r} 0 0 1 ${x} ${y + height - r}`;
1827
+ path += `V${y + r}`;
1828
+ path += `A${r} ${r} 0 0 1 ${x + r} ${y}Z`;
1829
+ return path;
1830
+ }
1831
+ //#endregion
1832
+ //#region src/components/Overlay.tsx
1833
+ const hiddenLifecycles = [LIFECYCLE.BEACON_BEFORE, LIFECYCLE.BEACON];
1834
+ function JoyrideOverlay(props) {
1835
+ const { blockTargetInteraction, continuous, hideOverlay, lifecycle, onClickOverlay, overlayClickAction, placement, portalElement, scrolling, spotlightPadding, spotlightRadius, spotlightTarget, styles, target, waiting } = props;
1836
+ const windowSize = (0, _gilbarbara_hooks.useWindowSize)();
1837
+ const targetRect = useTargetPosition(spotlightTarget ?? target, spotlightPadding, scrolling || waiting);
1838
+ const overlayRef = (0, react.useRef)(null);
1839
+ const showSpotlight = (lifecycle === LIFECYCLE.TOOLTIP || lifecycle === LIFECYCLE.TOOLTIP_BEFORE) && placement !== "center";
1840
+ const [spotlightReady, setSpotlightReady] = (0, react.useState)(false);
1841
+ const container = portalElement ? overlayRef.current?.offsetParent : null;
1842
+ const overlayWidth = container?.clientWidth ?? windowSize.width;
1843
+ const overlayHeight = container?.clientHeight ?? getDocumentHeight() ?? windowSize.height;
1844
+ const overlayColor = styles.overlay?.backgroundColor ?? "rgba(0, 0, 0, 0.5)";
1845
+ const overlayStyles = (0, react.useMemo)(() => {
1846
+ const { backgroundColor: _bg, mixBlendMode: _mbm, ...rest } = styles.overlay;
1847
+ return {
1848
+ height: overlayHeight,
1849
+ pointerEvents: "none",
1850
+ ...rest
1851
+ };
1852
+ }, [overlayHeight, styles.overlay]);
1853
+ const showCutout = showSpotlight && !scrolling && !waiting;
1854
+ (0, react.useEffect)(() => {
1855
+ if (showCutout) requestAnimationFrame(() => setSpotlightReady(true));
1856
+ else setSpotlightReady(false);
1857
+ }, [showCutout]);
1858
+ const isHiddenInContinuous = continuous && hiddenLifecycles.includes(lifecycle);
1859
+ const isHiddenInNonContinuous = !continuous && lifecycle !== LIFECYCLE.TOOLTIP;
1860
+ if (hideOverlay || !waiting && (isHiddenInContinuous || isHiddenInNonContinuous)) return null;
1861
+ let coverPath = "";
1862
+ if (showCutout) if (portalElement && container) {
1863
+ const targetEl = getElement(spotlightTarget ?? target);
1864
+ if (targetEl) {
1865
+ const targetOffset = getAbsoluteOffset(targetEl);
1866
+ const containerOffset = getAbsoluteOffset(container);
1867
+ coverPath = generateSpotlightPath(targetOffset.left - containerOffset.left - spotlightPadding.left, targetOffset.top - containerOffset.top - spotlightPadding.top, targetEl.offsetWidth + spotlightPadding.left + spotlightPadding.right, targetEl.offsetHeight + spotlightPadding.top + spotlightPadding.bottom, spotlightRadius);
1868
+ }
1869
+ } else coverPath = generateSpotlightPath(targetRect.left, targetRect.top, targetRect.width, targetRect.height, spotlightRadius);
1870
+ const path = generateOverlayPath(overlayWidth, overlayHeight, coverPath);
1871
+ return /* @__PURE__ */ react.default.createElement("div", {
1872
+ ref: overlayRef,
1873
+ "aria-hidden": "true",
1874
+ className: "react-joyride__overlay",
1875
+ "data-testid": "overlay",
1876
+ style: overlayStyles
1877
+ }, /* @__PURE__ */ react.default.createElement("svg", {
1878
+ className: "react-joyride__spotlight",
1879
+ "data-testid": "spotlight",
1880
+ style: {
1881
+ height: overlayHeight,
1882
+ left: 0,
1883
+ position: targetRect.isFixed ? "fixed" : "absolute",
1884
+ top: 0,
1885
+ width: overlayWidth
1886
+ }
1887
+ }, /* @__PURE__ */ react.default.createElement("path", {
1888
+ d: path,
1889
+ fill: overlayColor,
1890
+ fillRule: "evenodd",
1891
+ onClick: onClickOverlay,
1892
+ style: {
1893
+ cursor: overlayClickAction ? "pointer" : "default",
1894
+ pointerEvents: "auto"
1895
+ }
1896
+ }), coverPath && /* @__PURE__ */ react.default.createElement("path", {
1897
+ d: coverPath,
1898
+ fill: overlayColor,
1899
+ style: {
1900
+ opacity: spotlightReady ? 0 : 1,
1901
+ pointerEvents: blockTargetInteraction ? "auto" : "none",
1902
+ transition: "opacity 0.2s"
1903
+ }
1904
+ }), coverPath && Object.keys(styles.spotlight).length > 0 && /* @__PURE__ */ react.default.createElement("path", {
1905
+ d: coverPath,
1906
+ fill: "none",
1907
+ style: { pointerEvents: "none" },
1908
+ ...styles.spotlight
1909
+ })));
1910
+ }
1911
+ //#endregion
1912
+ //#region src/components/Portal.tsx
1913
+ function JoyridePortal(props) {
1914
+ const { children, element } = props;
1915
+ if (!element) return null;
1916
+ return (0, react_dom.createPortal)(children, element);
1917
+ }
1918
+ //#endregion
1919
+ //#region src/hooks/useFocusTrap.ts
1920
+ const TABBABLE_SELECTOR = "a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), area[href], [tabindex]:not([tabindex=\"-1\"]), [contenteditable]";
1921
+ function useFocusTrap(element, selector) {
1922
+ const previousFocus = (0, react.useRef)(null);
1923
+ (0, react.useEffect)(() => {
1924
+ if (!element) return noop;
1925
+ previousFocus.current = document.activeElement;
1926
+ const handleKeyDown = (event) => {
1927
+ if (event.key !== "Tab") return;
1928
+ const elements = [...element.querySelectorAll(TABBABLE_SELECTOR)];
1929
+ const { shiftKey } = event;
1930
+ if (!elements.length) return;
1931
+ event.preventDefault();
1932
+ let index = document.activeElement ? elements.indexOf(document.activeElement) : 0;
1933
+ if (index === -1 || !shiftKey && index + 1 === elements.length) index = 0;
1934
+ else if (shiftKey && index === 0) index = elements.length - 1;
1935
+ else index += shiftKey ? -1 : 1;
1936
+ elements[index].focus();
1937
+ };
1938
+ element.addEventListener("keydown", handleKeyDown, false);
1939
+ let timerId;
1940
+ if (selector) {
1941
+ const target = element.querySelector(selector);
1942
+ if (target) timerId = setTimeout(() => {
1943
+ target.focus({ preventScroll: true });
1944
+ }, 100);
1945
+ }
1946
+ return () => {
1947
+ element.removeEventListener("keydown", handleKeyDown);
1948
+ if (timerId !== void 0) clearTimeout(timerId);
1949
+ previousFocus.current?.focus({ preventScroll: true });
1950
+ };
1951
+ }, [element, selector]);
1952
+ }
1953
+ //#endregion
1954
+ //#region src/components/Arrow.tsx
1955
+ function getDimensions(placement, base, size) {
1956
+ const [side] = placement.split("-");
1957
+ switch (side) {
1958
+ case "top":
1959
+ case "bottom": return {
1960
+ width: base,
1961
+ height: size
1962
+ };
1963
+ case "left":
1964
+ case "right": return {
1965
+ width: size,
1966
+ height: base
1967
+ };
1968
+ default: return null;
1969
+ }
1970
+ }
1971
+ function getPoints(placement, base, size) {
1972
+ const [side] = placement.split("-");
1973
+ switch (side) {
1974
+ case "top": return {
1975
+ points: `0,0 ${base / 2},${size} ${base},0`,
1976
+ ...getDimensions(placement, base, size)
1977
+ };
1978
+ case "bottom": return {
1979
+ points: `${base},${size} ${base / 2},0 0,${size}`,
1980
+ ...getDimensions(placement, base, size)
1981
+ };
1982
+ case "left": return {
1983
+ points: `0,0 ${size},${base / 2} 0,${base}`,
1984
+ ...getDimensions(placement, base, size)
1985
+ };
1986
+ case "right": return {
1987
+ points: `${size},${base} ${size},0 0,${base / 2}`,
1988
+ ...getDimensions(placement, base, size)
1989
+ };
1990
+ default: return null;
1991
+ }
1992
+ }
1993
+ function getPositionStyle(placement, position, size, base) {
1994
+ if (!position) return {};
1995
+ const [side] = placement.split("-");
1996
+ switch (side) {
1997
+ case "top": return {
1998
+ bottom: -size,
1999
+ left: position.x ?? 0,
2000
+ ...getDimensions(placement, base, size)
2001
+ };
2002
+ case "bottom": return {
2003
+ top: -size,
2004
+ left: position.x ?? 0,
2005
+ ...getDimensions(placement, base, size)
2006
+ };
2007
+ case "left": return {
2008
+ right: -size,
2009
+ top: position.y ?? 0,
2010
+ ...getDimensions(placement, base, size)
2011
+ };
2012
+ case "right": return {
2013
+ left: -size,
2014
+ top: position.y ?? 0,
2015
+ ...getDimensions(placement, base, size)
2016
+ };
2017
+ default: return {};
2018
+ }
2019
+ }
2020
+ function Arrow({ arrowComponent, arrowRef, base, placement, position, size, styles }) {
2021
+ const ArrowComponent = arrowComponent;
2022
+ let content = null;
2023
+ if (ArrowComponent) {
2024
+ if (!getDimensions(placement, base, size)) return null;
2025
+ content = /* @__PURE__ */ react.default.createElement("span", { style: { flexShrink: 0 } }, /* @__PURE__ */ react.default.createElement(ArrowComponent, {
2026
+ base,
2027
+ placement,
2028
+ size
2029
+ }));
2030
+ } else {
2031
+ const svg = getPoints(placement, base, size);
2032
+ if (!svg) return null;
2033
+ content = /* @__PURE__ */ react.default.createElement("svg", {
2034
+ height: svg.height,
2035
+ width: svg.width,
2036
+ xmlns: "http://www.w3.org/2000/svg"
2037
+ }, /* @__PURE__ */ react.default.createElement("polygon", {
2038
+ fill: "currentColor",
2039
+ points: svg.points
2040
+ }));
2041
+ }
2042
+ return /* @__PURE__ */ react.default.createElement("span", {
2043
+ ref: arrowRef,
2044
+ className: "react-joyride__arrow",
2045
+ "data-testid": "arrow",
2046
+ style: {
2047
+ ...styles,
2048
+ ...getPositionStyle(placement, position, size, base),
2049
+ ...position ? {} : { visibility: "hidden" }
2050
+ }
2051
+ }, content);
2052
+ }
2053
+ //#endregion
2054
+ //#region src/components/Beacon.tsx
2055
+ function JoyrideBeacon(props) {
2056
+ const { beaconComponent, continuous, index, isLastStep, locale, nonce, onInteract, shouldFocus, size, step, styles } = props;
2057
+ const beaconRef = (0, react.useRef)(null);
2058
+ const hasBeaconComponent = Boolean(beaconComponent);
2059
+ (0, react.useEffect)(() => {
2060
+ if (hasBeaconComponent) return noop;
2061
+ if (document.getElementById("joyride-beacon-animation")) return noop;
2062
+ const style = document.createElement("style");
2063
+ style.id = "joyride-beacon-animation";
2064
+ if (nonce) style.setAttribute("nonce", nonce);
2065
+ style.appendChild(document.createTextNode(`
2066
+ @keyframes joyride-beacon-inner {
2067
+ 20% {
2068
+ opacity: 0.9;
2069
+ }
2070
+
2071
+ 90% {
2072
+ opacity: 0.7;
2073
+ }
2074
+ }
2075
+
2076
+ @keyframes joyride-beacon-outer {
2077
+ 0% {
2078
+ transform: scale(1);
2079
+ }
2080
+
2081
+ 45% {
2082
+ opacity: 0.7;
2083
+ transform: scale(0.75);
2084
+ }
2085
+
2086
+ 100% {
2087
+ opacity: 0.9;
2088
+ transform: scale(1);
2089
+ }
2090
+ }
2091
+ `));
2092
+ document.head.appendChild(style);
2093
+ const focusTimer = setTimeout(() => {
2094
+ if (is_lite.default.domElement(beaconRef.current) && shouldFocus) beaconRef.current.focus();
2095
+ }, 0);
2096
+ return () => {
2097
+ clearTimeout(focusTimer);
2098
+ const insertedStyle = document.getElementById("joyride-beacon-animation");
2099
+ if (insertedStyle?.parentNode) insertedStyle.parentNode.removeChild(insertedStyle);
2100
+ };
2101
+ }, [
2102
+ hasBeaconComponent,
2103
+ nonce,
2104
+ shouldFocus
2105
+ ]);
2106
+ const title = getReactNodeText(locale.open);
2107
+ let content;
2108
+ if (beaconComponent) {
2109
+ const BeaconComponent = beaconComponent;
2110
+ content = /* @__PURE__ */ react.default.createElement(BeaconComponent, {
2111
+ continuous,
2112
+ index,
2113
+ isLastStep,
2114
+ size,
2115
+ step
2116
+ });
2117
+ } else content = /* @__PURE__ */ react.default.createElement("span", { style: styles.beacon }, /* @__PURE__ */ react.default.createElement("span", { style: styles.beaconOuter }), /* @__PURE__ */ react.default.createElement("span", { style: styles.beaconInner }));
2118
+ return /* @__PURE__ */ react.default.createElement("button", {
2119
+ ref: beaconRef,
2120
+ "aria-label": title,
2121
+ className: "react-joyride__beacon",
2122
+ "data-testid": "button-beacon",
2123
+ onClick: onInteract,
2124
+ onMouseEnter: onInteract,
2125
+ style: styles.beaconWrapper,
2126
+ title,
2127
+ type: "button"
2128
+ }, content);
2129
+ }
2130
+ //#endregion
2131
+ //#region src/components/Tooltip/CloseButton.tsx
2132
+ function JoyrideTooltipCloseButton({ styles, ...props }) {
2133
+ const { color, height, width, ...style } = styles;
2134
+ return /* @__PURE__ */ react.default.createElement("button", {
2135
+ style,
2136
+ type: "button",
2137
+ ...props
2138
+ }, /* @__PURE__ */ react.default.createElement("svg", {
2139
+ height: typeof height === "number" ? `${height}px` : height,
2140
+ preserveAspectRatio: "xMidYMid",
2141
+ version: "1.1",
2142
+ viewBox: "0 0 18 18",
2143
+ width: typeof width === "number" ? `${width}px` : width,
2144
+ xmlns: "http://www.w3.org/2000/svg"
2145
+ }, /* @__PURE__ */ react.default.createElement("g", null, /* @__PURE__ */ react.default.createElement("path", {
2146
+ 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",
2147
+ fill: color
2148
+ }))));
2149
+ }
2150
+ //#endregion
2151
+ //#region src/components/Tooltip/DefaultTooltip.tsx
2152
+ function JoyrideDefaultTooltip(props) {
2153
+ const { backProps, closeProps, index, isLastStep, primaryProps, skipProps, step, tooltipProps } = props;
2154
+ const { buttons, content, styles, title } = step;
2155
+ const buttonElements = {};
2156
+ if (buttons.includes("primary")) buttonElements.primary = /* @__PURE__ */ react.default.createElement("button", {
2157
+ "data-testid": "button-primary",
2158
+ style: styles.buttonPrimary,
2159
+ type: "button",
2160
+ ...primaryProps
2161
+ });
2162
+ if (buttons.includes("skip") && !isLastStep) buttonElements.skip = /* @__PURE__ */ react.default.createElement("button", {
2163
+ "aria-live": "off",
2164
+ "data-testid": "button-skip",
2165
+ style: styles.buttonSkip,
2166
+ type: "button",
2167
+ ...skipProps
2168
+ });
2169
+ if (buttons.includes("back") && index > 0) buttonElements.back = /* @__PURE__ */ react.default.createElement("button", {
2170
+ "data-testid": "button-back",
2171
+ style: styles.buttonBack,
2172
+ type: "button",
2173
+ ...backProps
2174
+ });
2175
+ buttonElements.close = buttons.includes("close") && /* @__PURE__ */ react.default.createElement(JoyrideTooltipCloseButton, {
2176
+ "data-testid": "button-close",
2177
+ styles: styles.buttonClose,
2178
+ ...closeProps
2179
+ });
2180
+ const ariaProps = title ? {
2181
+ "aria-labelledby": "joyride-tooltip-title",
2182
+ "aria-describedby": "joyride-tooltip-content"
2183
+ } : {
2184
+ "aria-label": getReactNodeText(content),
2185
+ "aria-describedby": "joyride-tooltip-content"
2186
+ };
2187
+ return /* @__PURE__ */ react.default.createElement("div", {
2188
+ key: "JoyrideTooltip",
2189
+ className: "react-joyride__tooltip",
2190
+ "data-joyride-step": index,
2191
+ ...step.id && { "data-joyride-id": step.id },
2192
+ style: styles.tooltip,
2193
+ ...tooltipProps,
2194
+ ...ariaProps
2195
+ }, /* @__PURE__ */ react.default.createElement("div", { style: styles.tooltipContainer }, title && /* @__PURE__ */ react.default.createElement("h4", {
2196
+ id: "joyride-tooltip-title",
2197
+ style: styles.tooltipTitle
2198
+ }, title), /* @__PURE__ */ react.default.createElement("div", {
2199
+ id: "joyride-tooltip-content",
2200
+ style: styles.tooltipContent
2201
+ }, content)), buttons.some((b) => b === "back" || b === "primary" || b === "skip") && /* @__PURE__ */ react.default.createElement("div", { style: styles.tooltipFooter }, /* @__PURE__ */ react.default.createElement("div", { style: styles.tooltipFooterSpacer }, buttonElements.skip), buttonElements.back, buttonElements.primary), buttonElements.close);
2202
+ }
2203
+ //#endregion
2204
+ //#region src/components/Tooltip/index.tsx
2205
+ function Tooltip(props) {
2206
+ const { continuous, controls, index, isLastStep, size, step } = props;
2207
+ const handleClickBack = (event) => {
2208
+ event.preventDefault();
2209
+ controls.prev(ORIGIN.BUTTON_BACK);
2210
+ };
2211
+ const handleClickClose = (event) => {
2212
+ event.preventDefault();
2213
+ if (step.closeButtonAction === "skip") controls.skip(ORIGIN.BUTTON_CLOSE);
2214
+ else if (step.closeButtonAction === "replay") controls.replay(ORIGIN.BUTTON_CLOSE);
2215
+ else controls.close(ORIGIN.BUTTON_CLOSE);
2216
+ };
2217
+ const handleClickPrimary = (event) => {
2218
+ event.preventDefault();
2219
+ if (!continuous) {
2220
+ controls.close(ORIGIN.BUTTON_PRIMARY);
2221
+ return;
2222
+ }
2223
+ controls.next(ORIGIN.BUTTON_PRIMARY);
2224
+ };
2225
+ const handleClickSkip = (event) => {
2226
+ event.preventDefault();
2227
+ controls.skip(ORIGIN.BUTTON_SKIP);
2228
+ };
2229
+ const getElementsProps = () => {
2230
+ const { back, close, last, next, nextWithProgress, skip } = step.locale;
2231
+ const backText = getReactNodeText(back);
2232
+ const closeText = getReactNodeText(close);
2233
+ const lastText = getReactNodeText(last);
2234
+ const nextText = getReactNodeText(next);
2235
+ const skipText = getReactNodeText(skip);
2236
+ let primary = close;
2237
+ let primaryText = closeText;
2238
+ if (continuous) {
2239
+ primary = next;
2240
+ primaryText = nextText;
2241
+ if (step.showProgress && !isLastStep) {
2242
+ const labelWithProgress = getReactNodeText(nextWithProgress, {
2243
+ step: index + 1,
2244
+ steps: size
2245
+ });
2246
+ primary = replaceLocaleContent(nextWithProgress, index + 1, size);
2247
+ primaryText = labelWithProgress;
2248
+ }
2249
+ if (isLastStep) {
2250
+ primary = last;
2251
+ primaryText = lastText;
2252
+ }
2253
+ }
2254
+ return {
2255
+ backProps: {
2256
+ "aria-label": backText,
2257
+ children: back,
2258
+ "data-action": "back",
2259
+ onClick: handleClickBack,
2260
+ role: "button",
2261
+ title: backText
2262
+ },
2263
+ closeProps: {
2264
+ "aria-label": closeText,
2265
+ children: close,
2266
+ "data-action": "close",
2267
+ onClick: handleClickClose,
2268
+ role: "button",
2269
+ title: closeText
2270
+ },
2271
+ primaryProps: {
2272
+ "aria-label": primaryText,
2273
+ children: primary,
2274
+ "data-action": "primary",
2275
+ onClick: handleClickPrimary,
2276
+ role: "button",
2277
+ title: primaryText
2278
+ },
2279
+ skipProps: {
2280
+ "aria-label": skipText,
2281
+ children: skip,
2282
+ "data-action": "skip",
2283
+ onClick: handleClickSkip,
2284
+ role: "button",
2285
+ title: skipText
2286
+ },
2287
+ tooltipProps: {
2288
+ "aria-modal": true,
2289
+ role: "alertdialog"
2290
+ }
2291
+ };
2292
+ };
2293
+ const { arrowComponent, beaconComponent, tooltipComponent, ...stepProps } = step;
2294
+ let component;
2295
+ if (tooltipComponent) {
2296
+ const TooltipComponent = tooltipComponent;
2297
+ component = /* @__PURE__ */ react.default.createElement(TooltipComponent, {
2298
+ ...getElementsProps(),
2299
+ continuous,
2300
+ controls,
2301
+ index,
2302
+ isLastStep,
2303
+ size,
2304
+ step: stepProps
2305
+ });
2306
+ } else component = /* @__PURE__ */ react.default.createElement(JoyrideDefaultTooltip, {
2307
+ ...getElementsProps(),
2308
+ continuous,
2309
+ controls,
2310
+ index,
2311
+ isLastStep,
2312
+ size,
2313
+ step: stepProps
2314
+ });
2315
+ return component;
2316
+ }
2317
+ //#endregion
2318
+ //#region src/components/Floater.tsx
2319
+ function getFallbackPlacements(placement) {
2320
+ if (placement.startsWith("left")) return ["top", "bottom"];
2321
+ if (placement.startsWith("right")) return ["bottom", "top"];
2322
+ }
2323
+ function getFlipMiddleware(isAuto, step, tooltipPlacement) {
2324
+ if (isAuto) return [(0, _floating_ui_react_dom.autoPlacement)()];
2325
+ if (step.floatingOptions?.flipOptions === false) return [];
2326
+ return [(0, _floating_ui_react_dom.flip)({
2327
+ crossAxis: false,
2328
+ fallbackPlacements: getFallbackPlacements(tooltipPlacement),
2329
+ padding: 20,
2330
+ ...step.floatingOptions?.flipOptions
2331
+ })];
2332
+ }
2333
+ function JoyrideFloater(props) {
2334
+ const { continuous, controls, index, lifecycle, nonce, open, portalElement, setPositionData, setTooltipRef, shouldScroll, size, step, target, updateState } = props;
2335
+ const arrowRef = (0, react.useRef)(null);
2336
+ const beaconMiddlewareRef = (0, react.useRef)({});
2337
+ const tooltipMiddlewareRef = (0, react.useRef)({});
2338
+ const isCenter = step.placement === "center";
2339
+ const isAuto = step.placement === "auto";
2340
+ const centerReference = (0, react.useMemo)(() => ({ getBoundingClientRect: () => ({
2341
+ x: window.innerWidth / 2,
2342
+ y: window.innerHeight / 2,
2343
+ top: window.innerHeight / 2,
2344
+ left: window.innerWidth / 2,
2345
+ bottom: window.innerHeight / 2,
2346
+ right: window.innerWidth / 2,
2347
+ width: 0,
2348
+ height: 0
2349
+ }) }), []);
2350
+ const scrollParent = (0, react.useMemo)(() => hasCustomScrollParent(target) ? getScrollParent(target) : void 0, [target]);
2351
+ const isFixedTarget = (0, react.useMemo)(() => hasPosition(target), [target]);
2352
+ const boundaryOptions = (0, react.useMemo)(() => scrollParent ? {
2353
+ boundary: scrollParent,
2354
+ rootBoundary: "viewport"
2355
+ } : {}, [scrollParent]);
2356
+ const tooltipPlacement = isCenter || isAuto ? "bottom" : step.placement;
2357
+ const strategy = isCenter ? "fixed" : step.floatingOptions?.strategy ?? (step.isFixed || isFixedTarget ? "fixed" : "absolute");
2358
+ const tooltipMiddleware = (0, react.useMemo)(() => isCenter ? [{
2359
+ name: "center",
2360
+ fn: ({ rects }) => ({
2361
+ x: (window.innerWidth - rects.floating.width) / 2,
2362
+ y: (window.innerHeight - rects.floating.height) / 2
2363
+ })
2364
+ }] : [
2365
+ (0, _floating_ui_react_dom.offset)(({ placement: currentPlacement }) => {
2366
+ let side = "right";
2367
+ if (currentPlacement.startsWith("top")) side = "top";
2368
+ else if (currentPlacement.startsWith("bottom")) side = "bottom";
2369
+ else if (currentPlacement.startsWith("left")) side = "left";
2370
+ const padding = step.spotlightTarget ? 0 : step.spotlightPadding[side];
2371
+ return step.offset + padding + (step.floatingOptions?.hideArrow ? 0 : step.arrowSize);
2372
+ }, [
2373
+ step.offset,
2374
+ step.spotlightPadding,
2375
+ step.spotlightTarget,
2376
+ step.arrowSize,
2377
+ step.floatingOptions?.hideArrow
2378
+ ]),
2379
+ ...getFlipMiddleware(isAuto, step, tooltipPlacement),
2380
+ (0, _floating_ui_react_dom.shift)({
2381
+ padding: 10,
2382
+ ...boundaryOptions,
2383
+ ...step.floatingOptions?.shiftOptions
2384
+ }),
2385
+ ...step.floatingOptions?.hideArrow ? [] : [(0, _floating_ui_react_dom.arrow)({
2386
+ element: arrowRef,
2387
+ padding: step.arrowSpacing
2388
+ }, [step.arrowSpacing, step.arrowBase])],
2389
+ ...step.floatingOptions?.middleware ?? []
2390
+ ], [
2391
+ isCenter,
2392
+ step,
2393
+ isAuto,
2394
+ tooltipPlacement,
2395
+ boundaryOptions
2396
+ ]);
2397
+ const tooltipFloating = (0, _floating_ui_react_dom.useFloating)({
2398
+ ...isCenter ? { elements: { reference: centerReference } } : {},
2399
+ placement: tooltipPlacement,
2400
+ strategy,
2401
+ middleware: tooltipMiddleware
2402
+ });
2403
+ const beaconFloating = (0, _floating_ui_react_dom.useFloating)({
2404
+ strategy,
2405
+ placement: step.beaconPlacement ?? (isAuto || isCenter ? "bottom" : step.placement),
2406
+ middleware: (0, react.useMemo)(() => [(0, _floating_ui_react_dom.offset)(step.floatingOptions?.beaconOptions?.offset ?? -18)], [step.floatingOptions?.beaconOptions?.offset]),
2407
+ whileElementsMounted: _floating_ui_react_dom.autoUpdate
2408
+ });
2409
+ tooltipMiddlewareRef.current = tooltipFloating.middlewareData;
2410
+ beaconMiddlewareRef.current = beaconFloating.middlewareData;
2411
+ (0, react.useEffect)(() => {
2412
+ const { floating, reference } = tooltipFloating.elements;
2413
+ if (!reference || !floating || lifecycle !== LIFECYCLE.TOOLTIP) return;
2414
+ return (0, _floating_ui_react_dom.autoUpdate)(reference, floating, tooltipFloating.update, step.floatingOptions?.autoUpdate);
2415
+ }, [
2416
+ lifecycle,
2417
+ tooltipFloating.update,
2418
+ step.floatingOptions?.autoUpdate,
2419
+ step.target,
2420
+ tooltipFloating.elements
2421
+ ]);
2422
+ (0, react.useEffect)(() => {
2423
+ if (!isCenter && target) tooltipFloating.refs.setReference(target);
2424
+ if (target) beaconFloating.refs.setReference(target);
2425
+ }, [
2426
+ beaconFloating.refs,
2427
+ isCenter,
2428
+ target,
2429
+ tooltipFloating.refs
2430
+ ]);
2431
+ (0, react.useEffect)(() => {
2432
+ if (tooltipFloating.isPositioned) setPositionData("tooltip", {
2433
+ placement: tooltipFloating.placement,
2434
+ x: tooltipFloating.x ?? 0,
2435
+ y: tooltipFloating.y ?? 0,
2436
+ middlewareData: tooltipMiddlewareRef.current
2437
+ });
2438
+ }, [
2439
+ setPositionData,
2440
+ tooltipFloating.isPositioned,
2441
+ tooltipFloating.placement,
2442
+ tooltipFloating.x,
2443
+ tooltipFloating.y
2444
+ ]);
2445
+ (0, react.useEffect)(() => {
2446
+ if (beaconFloating.isPositioned) setPositionData("beacon", {
2447
+ placement: beaconFloating.placement,
2448
+ x: beaconFloating.x ?? 0,
2449
+ y: beaconFloating.y ?? 0,
2450
+ middlewareData: beaconMiddlewareRef.current
2451
+ });
2452
+ }, [
2453
+ setPositionData,
2454
+ beaconFloating.isPositioned,
2455
+ beaconFloating.placement,
2456
+ beaconFloating.x,
2457
+ beaconFloating.y
2458
+ ]);
2459
+ const zIndex = step.zIndex + 1;
2460
+ const handleBeaconInteraction = (0, react.useCallback)((event) => {
2461
+ if (event.type === "mouseenter" && step.beaconTrigger !== "hover") return;
2462
+ updateState({
2463
+ lifecycle: LIFECYCLE.TOOLTIP_BEFORE,
2464
+ positioned: false
2465
+ });
2466
+ }, [step.beaconTrigger, updateState]);
2467
+ const floaterRef = (0, react.useCallback)((node) => {
2468
+ if (node) {
2469
+ tooltipFloating.refs.setFloating(node);
2470
+ setTooltipRef(node);
2471
+ }
2472
+ }, [tooltipFloating.refs, setTooltipRef]);
2473
+ const { arrow: arrowStyles, floater: floaterStyles } = step.styles;
2474
+ let content = null;
2475
+ if (lifecycle === LIFECYCLE.TOOLTIP || lifecycle === LIFECYCLE.TOOLTIP_BEFORE) {
2476
+ const styles = sortObjectKeys({
2477
+ ...floaterStyles,
2478
+ ...tooltipFloating.floatingStyles,
2479
+ zIndex,
2480
+ opacity: open && tooltipFloating.isPositioned ? 1 : 0,
2481
+ ...!open && { transition: "none" }
2482
+ });
2483
+ content = /* @__PURE__ */ react.default.createElement("div", {
2484
+ ref: floaterRef,
2485
+ className: "react-joyride__floater",
2486
+ "data-testid": "floater",
2487
+ id: `react-joyride-step-${index}`,
2488
+ style: styles
2489
+ }, /* @__PURE__ */ react.default.createElement(Tooltip, {
2490
+ continuous,
2491
+ controls,
2492
+ index,
2493
+ isLastStep: index + 1 === size,
2494
+ size,
2495
+ step
2496
+ }), !isCenter && !step.floatingOptions?.hideArrow && /* @__PURE__ */ react.default.createElement(Arrow, {
2497
+ arrowComponent: step.arrowComponent,
2498
+ arrowRef,
2499
+ base: step.arrowBase,
2500
+ placement: tooltipFloating.placement,
2501
+ position: tooltipFloating.middlewareData.arrow,
2502
+ size: step.arrowSize,
2503
+ styles: arrowStyles
2504
+ }));
2505
+ } else if (lifecycle === LIFECYCLE.BEACON || lifecycle === LIFECYCLE.BEACON_BEFORE) content = /* @__PURE__ */ react.default.createElement("div", {
2506
+ ref: beaconFloating.refs.setFloating,
2507
+ className: "react-joyride__floater",
2508
+ "data-testid": "floater-beacon",
2509
+ id: `react-joyride-step-${index}-beacon`,
2510
+ style: sortObjectKeys({
2511
+ ...beaconFloating.floatingStyles,
2512
+ zIndex
2513
+ })
2514
+ }, /* @__PURE__ */ react.default.createElement(JoyrideBeacon, {
2515
+ beaconComponent: step.beaconComponent,
2516
+ continuous,
2517
+ index,
2518
+ isLastStep: index + 1 === size,
2519
+ locale: step.locale,
2520
+ nonce,
2521
+ onInteract: handleBeaconInteraction,
2522
+ shouldFocus: shouldScroll,
2523
+ size,
2524
+ step,
2525
+ styles: step.styles
2526
+ }));
2527
+ return /* @__PURE__ */ react.default.createElement(JoyridePortal, { element: portalElement }, content);
2528
+ }
2529
+ //#endregion
2530
+ //#region src/components/Step.tsx
2531
+ function JoyrideStep(props) {
2532
+ const { continuous, controls, index, lifecycle, nonce, portalElement, setPositionData, shouldScroll, size, step, updateState } = props;
2533
+ const [tooltipElement, setTooltipElement] = (0, react.useState)(null);
2534
+ useFocusTrap(step.disableFocusTrap ? null : tooltipElement, "[data-action=primary]");
2535
+ const target = getElement(step.target);
2536
+ const open = lifecycle === LIFECYCLE.TOOLTIP;
2537
+ if (!validateStep(step) || !is_lite.default.domElement(target)) return null;
2538
+ return /* @__PURE__ */ react.default.createElement(JoyrideFloater, {
2539
+ key: `JoyrideStep-${index}`,
2540
+ continuous,
2541
+ controls,
2542
+ index,
2543
+ lifecycle,
2544
+ nonce,
2545
+ open,
2546
+ portalElement,
2547
+ setPositionData,
2548
+ setTooltipRef: setTooltipElement,
2549
+ shouldScroll,
2550
+ size,
2551
+ step,
2552
+ target,
2553
+ updateState
2554
+ });
2555
+ }
2556
+ //#endregion
2557
+ //#region src/components/TourRenderer.tsx
2558
+ function TourRenderer({ controls, mergedProps, state, step, store }) {
2559
+ const { continuous, debug, nonce, portalElement, scrollToFirstStep } = mergedProps;
2560
+ const element = usePortalElement(portalElement);
2561
+ const { index, lifecycle, status } = state;
2562
+ const isRunning = status === STATUS.RUNNING;
2563
+ const [showLoader, setShowLoader] = (0, react.useState)(false);
2564
+ const loaderTimerRef = (0, react.useRef)(null);
2565
+ const loaderDelay = step?.loaderDelay ?? 0;
2566
+ (0, react.useEffect)(() => {
2567
+ if (state.waiting) if (loaderDelay === 0) setShowLoader(true);
2568
+ else loaderTimerRef.current = setTimeout(() => {
2569
+ setShowLoader(true);
2570
+ }, loaderDelay);
2571
+ else setShowLoader(false);
2572
+ return () => {
2573
+ if (loaderTimerRef.current) {
2574
+ clearTimeout(loaderTimerRef.current);
2575
+ loaderTimerRef.current = null;
2576
+ }
2577
+ };
2578
+ }, [loaderDelay, state.waiting]);
2579
+ (0, react.useEffect)(() => {
2580
+ if (!isRunning) return;
2581
+ const handleKeyboard = (event) => {
2582
+ if (!step || lifecycle !== LIFECYCLE.TOOLTIP) return;
2583
+ if (event.key === "Escape" && step.dismissKeyAction) if (step.dismissKeyAction === "next") controls.next(ORIGIN.KEYBOARD);
2584
+ else if (step.dismissKeyAction === "replay") controls.replay(ORIGIN.KEYBOARD);
2585
+ else controls.close(ORIGIN.KEYBOARD);
2586
+ };
2587
+ document.body.addEventListener("keydown", handleKeyboard, { passive: true });
2588
+ return () => {
2589
+ document.body.removeEventListener("keydown", handleKeyboard);
2590
+ };
2591
+ }, [
2592
+ controls,
2593
+ isRunning,
2594
+ lifecycle,
2595
+ step
2596
+ ]);
2597
+ const handleClickOverlay = (0, react.useCallback)(() => {
2598
+ switch (step?.overlayClickAction) {
2599
+ case "close":
2600
+ controls.close(ORIGIN.OVERLAY);
2601
+ break;
2602
+ case "next":
2603
+ controls.next(ORIGIN.OVERLAY);
2604
+ break;
2605
+ case "replay":
2606
+ controls.replay(ORIGIN.OVERLAY);
2607
+ break;
2608
+ }
2609
+ }, [controls, step?.overlayClickAction]);
2610
+ if (!step || !isRunning) return null;
2611
+ const hideOverlay = state.action === ACTIONS.START && !step.skipBeacon && step.placement !== "center";
2612
+ return /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, lifecycle !== LIFECYCLE.INIT && /* @__PURE__ */ react.default.createElement(JoyrideStep, {
2613
+ ...state,
2614
+ continuous,
2615
+ controls,
2616
+ debug,
2617
+ nonce,
2618
+ portalElement: element,
2619
+ setPositionData: store.current.setPositionData,
2620
+ shouldScroll: !step.skipScroll && (index !== 0 || scrollToFirstStep),
2621
+ step,
2622
+ updateState: store.current.updateState
2623
+ }), /* @__PURE__ */ react.default.createElement(JoyridePortal, { element }, /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, showLoader && /* @__PURE__ */ react.default.createElement(JoyrideLoader, {
2624
+ nonce,
2625
+ step
2626
+ }), !hideOverlay && /* @__PURE__ */ react.default.createElement(JoyrideOverlay, {
2627
+ ...step,
2628
+ continuous,
2629
+ lifecycle,
2630
+ onClickOverlay: handleClickOverlay,
2631
+ portalElement: portalElement ? element : null,
2632
+ scrolling: state.scrolling,
2633
+ waiting: state.waiting
2634
+ }))));
2635
+ }
2636
+ //#endregion
2637
+ //#region src/hooks/useJoyride.tsx
2638
+ function useJoyride(props) {
2639
+ const { controls, failures, mergedProps, state, step, store } = useTourEngine(props);
2640
+ return {
2641
+ controls,
2642
+ failures,
2643
+ on: (0, react.useCallback)((eventType, handler) => store.current.on(eventType, handler), [store]),
2644
+ state: (0, react.useMemo)(() => omit(state, "positioned"), [state]),
2645
+ step,
2646
+ Tour: canUseDOM() ? /* @__PURE__ */ react.default.createElement(TourRenderer, {
2647
+ controls,
2648
+ mergedProps,
2649
+ state,
2650
+ step,
2651
+ store
2652
+ }) : null
2653
+ };
2654
+ }
2655
+ //#endregion
2656
+ //#region src/index.tsx
2657
+ function JoyrideTour(props) {
2658
+ const { Tour } = useJoyride(props);
2659
+ return Tour;
2660
+ }
2661
+ function Joyride(props) {
2662
+ if (!canUseDOM()) return null;
2663
+ return /* @__PURE__ */ react.default.createElement(JoyrideTour, props);
2664
+ }
2665
+ //#endregion
2666
+ exports.ACTIONS = ACTIONS;
2667
+ exports.EVENTS = EVENTS;
2668
+ exports.Joyride = Joyride;
2669
+ exports.LIFECYCLE = LIFECYCLE;
2670
+ exports.ORIGIN = ORIGIN;
2671
+ exports.PORTAL_ELEMENT_ID = PORTAL_ELEMENT_ID;
2672
+ exports.STATUS = STATUS;
2673
+ exports.defaultLocale = defaultLocale;
2674
+ exports.defaultOptions = defaultOptions;
2675
+ exports.useJoyride = useJoyride;
2676
+
2677
+ //# sourceMappingURL=index.cjs.map