react-product-tour-guide 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,1311 @@
1
+ import React5, { createContext, memo, useMemo, useState, useRef, useEffect, useCallback, Component, useContext } from 'react';
2
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
+ import { createPortal } from 'react-dom';
4
+ import { offset, flip, shift, useFloating, autoUpdate } from '@floating-ui/react';
5
+ import { clsx } from 'clsx';
6
+
7
+ var __defProp = Object.defineProperty;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
10
+
11
+ // src/styles/inject.ts
12
+ var __tourStyles__ = `@layer react-product-tour {
13
+
14
+ :root {
15
+ /* Tour Component Colors */
16
+ --tour--overlay--background: rgba(0, 0, 0, 0.5);
17
+ --tour--tooltip--background: white;
18
+ --tour--tooltip--border: #e5e7eb;
19
+ --tour--tooltip--text: black;
20
+ --tour--tooltip--shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
21
+
22
+ /* Tour Component Spacing */
23
+ --tour--tooltip--padding: 1rem;
24
+ --tour--tooltip--gap: 0.5rem;
25
+
26
+ /* Tour Component Border */
27
+ --tour--tooltip--radius: 0.5rem;
28
+ --tour--tooltip--border-width: 1px;
29
+
30
+ /* Tour Component Animation */
31
+ --tour--tooltip--transition: all 0.2s ease-in-out;
32
+
33
+ /* Tour Highlight */
34
+ --tour--highlight--padding: 8px;
35
+ --tour--highlight--radius: 10px;
36
+
37
+ /* Tour Button Colors */
38
+ --tour--button--primary--background: #646cff;
39
+ --tour--button--primary--text: white;
40
+ --tour--button--secondary--background: #e5e7eb;
41
+ --tour--button--secondary--text: #374151;
42
+
43
+ /* Tour Tooltip Size */
44
+ --tour--tooltip--max-width: 300px;
45
+
46
+ /* Tour Progress Bar */
47
+ --tour--progress--background: #e5e7eb;
48
+ --tour--progress--fill: #f43f5e;
49
+ }
50
+
51
+ /* Dark mode variables */
52
+ .dark {
53
+ --tour--tooltip--background: #1f2937;
54
+ --tour--tooltip--border: #374151;
55
+ --tour--tooltip--text: #f9fafb;
56
+ }
57
+
58
+ /* Screen reader utilities */
59
+ .sr-only {
60
+ position: absolute;
61
+ width: 1px;
62
+ height: 1px;
63
+ padding: 0;
64
+ margin: -1px;
65
+ overflow: hidden;
66
+ clip: rect(0, 0, 0, 0);
67
+ white-space: nowrap;
68
+ border: 0;
69
+ }
70
+
71
+ /* Focus styles */
72
+ .tour-button:focus-visible {
73
+ outline: 2px solid #3b82f6;
74
+ outline-offset: 2px;
75
+ }
76
+
77
+ .tour-button:focus:not(:focus-visible) {
78
+ outline: none;
79
+ }
80
+
81
+ /* High contrast mode support */
82
+ @media (forced-colors: active) {
83
+ .tour-button {
84
+ border: 2px solid currentColor;
85
+ }
86
+
87
+ .tour-tooltip {
88
+ border: 2px solid currentColor;
89
+ }
90
+
91
+ .tour-highlight {
92
+ border: 2px solid currentColor;
93
+ }
94
+ }
95
+
96
+ /* Reduced motion */
97
+ @media (prefers-reduced-motion: reduce) {
98
+ .tour-tooltip,
99
+ .tour-highlight,
100
+ .tour-overlay,
101
+ .tour-button {
102
+ animation: none !important;
103
+ transition: none !important;
104
+ }
105
+ }
106
+
107
+ /* Base tooltip styles */
108
+ .tour-tooltip {
109
+ position: absolute;
110
+ background-color: var(--tour--tooltip--background);
111
+ color: var(--tour--tooltip--text);
112
+ padding: var(--tour--tooltip--padding);
113
+ border-radius: var(--tour--tooltip--radius);
114
+ box-shadow: var(--tour--tooltip--shadow);
115
+ max-width: var(--tour--tooltip--max-width);
116
+ z-index: 1001;
117
+ opacity: 0;
118
+ border: var(--tour--tooltip--border-width) solid var(--tour--tooltip--border);
119
+ }
120
+
121
+ /* Allow Tailwind classes to override base styles */
122
+ .tour-tooltip[class*="bg-"] {
123
+ background-color: inherit;
124
+ }
125
+
126
+ .tour-tooltip[class*="text-"] {
127
+ color: inherit;
128
+ }
129
+
130
+ .tour-tooltip[class*="border-"] {
131
+ border-color: inherit;
132
+ }
133
+
134
+ .tour-tooltip[class*="rounded-"] {
135
+ border-radius: inherit;
136
+ }
137
+
138
+ .tour-tooltip[class*="shadow-"] {
139
+ box-shadow: inherit;
140
+ }
141
+
142
+ .tour-tooltip[class*="p-"] {
143
+ padding: inherit;
144
+ }
145
+
146
+ /* Animation variants */
147
+ .tour-tooltip[data-animation="slide"] {
148
+ transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out;
149
+ transform-origin: center;
150
+ transform: scale(0.95);
151
+ }
152
+
153
+ .tour-tooltip[data-animation="slide"][data-placement="top"] {
154
+ transform: translateY(10px) scale(0.95);
155
+ }
156
+
157
+ .tour-tooltip[data-animation="slide"][data-placement="bottom"] {
158
+ transform: translateY(-10px) scale(0.95);
159
+ }
160
+
161
+ .tour-tooltip[data-animation="slide"][data-placement="left"] {
162
+ transform: translateX(10px) scale(0.95);
163
+ }
164
+
165
+ .tour-tooltip[data-animation="slide"][data-placement="right"] {
166
+ transform: translateX(-10px) scale(0.95);
167
+ }
168
+
169
+ .tour-tooltip[data-animation="slide"].visible {
170
+ opacity: 1;
171
+ transform: scale(1) translate(0, 0);
172
+ }
173
+
174
+ .tour-tooltip[data-animation="bounce"] {
175
+ transition: transform 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55), opacity 0.3s ease-in-out;
176
+ transform-origin: center;
177
+ transform: scale(0.3);
178
+ }
179
+
180
+ .tour-tooltip[data-animation="bounce"][data-placement="top"] {
181
+ transform: translateY(20px) scale(0.3);
182
+ }
183
+
184
+ .tour-tooltip[data-animation="bounce"][data-placement="bottom"] {
185
+ transform: translateY(-20px) scale(0.3);
186
+ }
187
+
188
+ .tour-tooltip[data-animation="bounce"][data-placement="left"] {
189
+ transform: translateX(20px) scale(0.3);
190
+ }
191
+
192
+ .tour-tooltip[data-animation="bounce"][data-placement="right"] {
193
+ transform: translateX(-20px) scale(0.3);
194
+ }
195
+
196
+ .tour-tooltip[data-animation="bounce"].visible {
197
+ opacity: 1;
198
+ transform: scale(1) translate(0, 0);
199
+ }
200
+
201
+ .tour-tooltip[data-animation="fade"] {
202
+ transition: all 0.4s ease-out;
203
+ transform: translateY(10px);
204
+ opacity: 0;
205
+ }
206
+
207
+ .tour-tooltip[data-animation="fade"].visible {
208
+ opacity: 1;
209
+ transform: translateY(0);
210
+ }
211
+
212
+ .tour-tooltip-title {
213
+ margin: 0 0 0.5rem 0;
214
+ font-size: 1rem;
215
+ font-weight: 600;
216
+ color: var(--tour--tooltip--text);
217
+ line-height: 1.3;
218
+ }
219
+
220
+ .tour-tooltip-content {
221
+ margin-bottom: 1rem;
222
+ }
223
+
224
+ .tour-buttons {
225
+ display: flex;
226
+ gap: var(--tour--tooltip--gap);
227
+ justify-content: flex-end;
228
+ }
229
+
230
+ /* Tooltip arrow */
231
+ .tour-tooltip::before {
232
+ content: '';
233
+ position: absolute;
234
+ width: 0.75rem;
235
+ height: 0.75rem;
236
+ background-color: var(--tour--tooltip--background);
237
+ border: var(--tour--tooltip--border-width) solid var(--tour--tooltip--border);
238
+ transform: rotate(45deg);
239
+ }
240
+
241
+ /* Tooltip arrow positions */
242
+ .tour-tooltip[data-placement="top"]::before {
243
+ bottom: -0.375rem;
244
+ border-right: none;
245
+ border-bottom: none;
246
+ }
247
+
248
+ .tour-tooltip[data-placement="bottom"]::before {
249
+ top: -0.375rem;
250
+ border-left: none;
251
+ border-top: none;
252
+ }
253
+
254
+ .tour-tooltip[data-placement="left"]::before {
255
+ right: -0.375rem;
256
+ border-top: none;
257
+ border-right: none;
258
+ }
259
+
260
+ .tour-tooltip[data-placement="right"]::before {
261
+ left: -0.375rem;
262
+ border-bottom: none;
263
+ border-left: none;
264
+ }
265
+
266
+ /* Button styles */
267
+ .tour-button {
268
+ border-radius: var(--tour--tooltip--radius);
269
+ font-weight: 500;
270
+ font-family: inherit;
271
+ cursor: pointer;
272
+ padding: 0.5rem 1rem;
273
+ border: none;
274
+ transition: var(--tour--tooltip--transition);
275
+ }
276
+
277
+ .tour-button-primary {
278
+ background-color: var(--tour--button--primary--background);
279
+ color: var(--tour--button--primary--text);
280
+ }
281
+
282
+ .tour-button-secondary {
283
+ background-color: var(--tour--button--secondary--background);
284
+ color: var(--tour--button--secondary--text);
285
+ }
286
+
287
+ /* Allow Tailwind classes to override button styles */
288
+ .tour-button[class*="bg-"] {
289
+ background-color: inherit;
290
+ }
291
+
292
+ .tour-button[class*="text-"] {
293
+ color: inherit;
294
+ }
295
+
296
+ .tour-button[class*="rounded-"] {
297
+ border-radius: inherit;
298
+ }
299
+
300
+ .tour-button[class*="p-"] {
301
+ padding: inherit;
302
+ }
303
+
304
+ .tour-button[class*="font-"] {
305
+ font-weight: inherit;
306
+ }
307
+
308
+ .tour-button:disabled {
309
+ opacity: 0.5;
310
+ cursor: not-allowed;
311
+ }
312
+
313
+ .dark .tour-button-secondary {
314
+ background-color: #4b5563;
315
+ }
316
+
317
+ /* Overlay styles */
318
+ .tour-overlay {
319
+ position: fixed;
320
+ top: 0;
321
+ left: 0;
322
+ right: 0;
323
+ bottom: 0;
324
+ background-color: var(--tour--overlay--background);
325
+ z-index: 1000;
326
+ }
327
+
328
+ .tour-overlay[class*="bg-"] {
329
+ background-color: inherit;
330
+ }
331
+
332
+ .tour-overlay-blur {
333
+ backdrop-filter: blur(2px);
334
+ }
335
+
336
+ /* Highlight styles */
337
+ .tour-highlight {
338
+ position: absolute;
339
+ border-radius: var(--tour--highlight--radius);
340
+ box-shadow: 0 0 0 9999px var(--tour--overlay--background);
341
+ z-index: 1001;
342
+ opacity: 0;
343
+ }
344
+
345
+ .tour-highlight[class*="rounded-"] {
346
+ border-radius: inherit;
347
+ }
348
+
349
+ .tour-highlight[class*="shadow-"] {
350
+ box-shadow: inherit;
351
+ }
352
+
353
+ .tour-highlight[data-animation="slide"] {
354
+ transition: all 0.3s ease-in-out;
355
+ transform: scale(0.98);
356
+ }
357
+
358
+ .tour-highlight[data-animation="slide"].visible {
359
+ opacity: 1;
360
+ transform: scale(1);
361
+ }
362
+
363
+ .tour-highlight[data-animation="bounce"] {
364
+ transition: all 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
365
+ transform: translateY(20px) scale(0.95);
366
+ opacity: 0;
367
+ }
368
+
369
+ .tour-highlight[data-animation="bounce"].visible {
370
+ opacity: 1;
371
+ transform: translateY(0) scale(1);
372
+ }
373
+
374
+ .tour-highlight[data-animation="fade"] {
375
+ transition: all 0.4s ease-out;
376
+ transform: translateY(10px);
377
+ opacity: 0;
378
+ }
379
+
380
+ .tour-highlight[data-animation="fade"].visible {
381
+ opacity: 1;
382
+ transform: translateY(0);
383
+ }
384
+
385
+ .dark .tour-highlight {
386
+ background-color: rgba(255, 255, 255, 0.05);
387
+ border-color: rgba(255, 255, 255, 0.2);
388
+ }
389
+
390
+ } /* end @layer react-product-tour */
391
+ `;
392
+ if (typeof document !== "undefined") {
393
+ const id = "__react_product_tour_styles__";
394
+ if (!document.getElementById(id)) {
395
+ const style = document.createElement("style");
396
+ style.id = id;
397
+ style.textContent = __tourStyles__;
398
+ document.head.insertBefore(style, document.head.firstChild);
399
+ }
400
+ }
401
+
402
+ // src/manager/TourManager.ts
403
+ var _TourManager = class _TourManager {
404
+ constructor() {
405
+ __publicField(this, "state");
406
+ __publicField(this, "listeners");
407
+ this.state = {
408
+ steps: [],
409
+ currentStep: 0,
410
+ isActive: false
411
+ };
412
+ this.listeners = /* @__PURE__ */ new Set();
413
+ }
414
+ static getInstance() {
415
+ if (!_TourManager.instance) {
416
+ _TourManager.instance = new _TourManager();
417
+ }
418
+ return _TourManager.instance;
419
+ }
420
+ getState() {
421
+ return { ...this.state, steps: [...this.state.steps] };
422
+ }
423
+ initialize(steps) {
424
+ this.state.steps = steps;
425
+ this.state.currentStep = 0;
426
+ this.state.isActive = false;
427
+ this.notifyListeners();
428
+ }
429
+ start() {
430
+ if (this.state.steps.length === 0) return;
431
+ this.state.isActive = true;
432
+ this.state.currentStep = 0;
433
+ this.notifyListeners();
434
+ }
435
+ stop() {
436
+ this.state.isActive = false;
437
+ this.notifyListeners();
438
+ }
439
+ next() {
440
+ if (!this.state.isActive || this.state.currentStep >= this.state.steps.length - 1) {
441
+ this.stop();
442
+ return;
443
+ }
444
+ this.state.currentStep += 1;
445
+ this.notifyListeners();
446
+ }
447
+ back() {
448
+ if (!this.state.isActive || this.state.currentStep <= 0) return;
449
+ this.state.currentStep -= 1;
450
+ this.notifyListeners();
451
+ }
452
+ skip() {
453
+ this.stop();
454
+ }
455
+ subscribe(listener) {
456
+ this.listeners.add(listener);
457
+ return () => this.listeners.delete(listener);
458
+ }
459
+ notifyListeners() {
460
+ this.listeners.forEach((listener) => listener({ ...this.state }));
461
+ }
462
+ };
463
+ __publicField(_TourManager, "instance");
464
+ var TourManager = _TourManager;
465
+ var tourManager = TourManager.getInstance();
466
+ var TourContext = createContext(null);
467
+ var TourProvider = ({
468
+ steps,
469
+ children,
470
+ defaultActive = false,
471
+ onComplete,
472
+ onSkip,
473
+ onStepChange,
474
+ onStepEnter,
475
+ onStepExit
476
+ }) => {
477
+ const [currentStep, setCurrentStep] = useState(0);
478
+ const [isActive, setIsActive] = useState(defaultActive);
479
+ useEffect(() => {
480
+ tourManager.initialize(steps);
481
+ }, [steps]);
482
+ const start = useCallback(() => {
483
+ setIsActive(true);
484
+ setCurrentStep(0);
485
+ onStepEnter?.(0, steps[0]);
486
+ }, [steps, onStepEnter]);
487
+ const stop = useCallback(() => {
488
+ if (isActive) {
489
+ onStepExit?.(currentStep, steps[currentStep]);
490
+ }
491
+ setIsActive(false);
492
+ }, [isActive, currentStep, steps, onStepExit]);
493
+ const next = useCallback(async () => {
494
+ const currentStepData = steps[currentStep];
495
+ if (currentStepData?.waitFor) {
496
+ await currentStepData.waitFor();
497
+ }
498
+ if (currentStep < steps.length - 1) {
499
+ onStepExit?.(currentStep, currentStepData);
500
+ const nextStepIndex = currentStep + 1;
501
+ setCurrentStep(nextStepIndex);
502
+ onStepChange?.(nextStepIndex, steps[nextStepIndex]);
503
+ onStepEnter?.(nextStepIndex, steps[nextStepIndex]);
504
+ } else {
505
+ stop();
506
+ onComplete?.();
507
+ }
508
+ }, [currentStep, steps, stop, onComplete, onStepExit, onStepChange, onStepEnter]);
509
+ const back = useCallback(() => {
510
+ if (currentStep > 0) {
511
+ const currentStepData = steps[currentStep];
512
+ onStepExit?.(currentStep, currentStepData);
513
+ const prevStepIndex = currentStep - 1;
514
+ setCurrentStep(prevStepIndex);
515
+ onStepChange?.(prevStepIndex, steps[prevStepIndex]);
516
+ onStepEnter?.(prevStepIndex, steps[prevStepIndex]);
517
+ }
518
+ }, [currentStep, steps, onStepExit, onStepChange, onStepEnter]);
519
+ const skip = useCallback(() => {
520
+ stop();
521
+ onSkip?.();
522
+ }, [stop, onSkip]);
523
+ const value = useMemo(() => ({
524
+ steps,
525
+ currentStep,
526
+ isActive,
527
+ start,
528
+ stop,
529
+ next,
530
+ back,
531
+ skip
532
+ }), [steps, currentStep, isActive, start, stop, next, back, skip]);
533
+ return /* @__PURE__ */ jsx(TourContext.Provider, { value, children });
534
+ };
535
+ var useTour = () => {
536
+ const context = useContext(TourContext);
537
+ if (!context) {
538
+ throw new Error("useTour must be used within a TourProvider");
539
+ }
540
+ return context;
541
+ };
542
+ var useTour2 = () => {
543
+ const context = useContext(TourContext);
544
+ const [globalState, setGlobalState] = useState(tourManager.getState());
545
+ useEffect(() => {
546
+ return tourManager.subscribe(setGlobalState);
547
+ }, []);
548
+ if (context) {
549
+ return context;
550
+ }
551
+ return {
552
+ steps: globalState.steps,
553
+ currentStep: globalState.currentStep,
554
+ isActive: globalState.isActive,
555
+ start: tourManager.start.bind(tourManager),
556
+ stop: tourManager.stop.bind(tourManager),
557
+ next: tourManager.next.bind(tourManager),
558
+ back: tourManager.back.bind(tourManager),
559
+ skip: tourManager.skip.bind(tourManager)
560
+ };
561
+ };
562
+ var ProgressBar = ({
563
+ currentStep,
564
+ totalSteps,
565
+ className = ""
566
+ }) => {
567
+ const progress = (currentStep + 1) / totalSteps * 100;
568
+ return /* @__PURE__ */ jsx("div", { className: `w-full h-1 rounded-full ${className}`, style: { background: "var(--tour--progress--background)" }, children: /* @__PURE__ */ jsx(
569
+ "div",
570
+ {
571
+ className: "h-full rounded-full transition-all duration-300 ease-in-out",
572
+ style: { width: `${progress}%`, background: "var(--tour--progress--fill)" },
573
+ role: "progressbar",
574
+ "aria-valuenow": progress,
575
+ "aria-valuemin": 0,
576
+ "aria-valuemax": 100
577
+ }
578
+ ) });
579
+ };
580
+ var MediaFallback = ({ type, className = "" }) => {
581
+ return /* @__PURE__ */ jsx("div", { className: `flex items-center justify-center p-4 bg-gray-100 rounded-lg ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
582
+ /* @__PURE__ */ jsx("div", { className: "text-gray-400 mb-2", children: type === "image" ? "\u{1F5BC}\uFE0F" : "\u{1F3A5}" }),
583
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: type === "image" ? "Image failed to load" : "Video failed to load" })
584
+ ] }) });
585
+ };
586
+ var ErrorBoundary = class extends Component {
587
+ constructor(props) {
588
+ super(props);
589
+ this.state = {
590
+ hasError: false,
591
+ error: null
592
+ };
593
+ }
594
+ /**
595
+ * Updates state when an error occurs
596
+ * @param error - The error that occurred
597
+ * @returns New state
598
+ */
599
+ static getDerivedStateFromError(error) {
600
+ return {
601
+ hasError: true,
602
+ error
603
+ };
604
+ }
605
+ /**
606
+ * Called when an error occurs
607
+ * @param error - The error that occurred
608
+ * @param errorInfo - Additional error information
609
+ */
610
+ componentDidCatch(error, errorInfo) {
611
+ this.props.onError?.(error, errorInfo);
612
+ }
613
+ render() {
614
+ if (this.state.hasError) {
615
+ if (this.props.fallback) {
616
+ return this.props.fallback;
617
+ }
618
+ return /* @__PURE__ */ jsxs("div", { className: "p-4 bg-red-50 border border-red-200 rounded-lg", children: [
619
+ /* @__PURE__ */ jsx("div", { className: "text-red-600 mb-2", children: "Something went wrong" }),
620
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-red-500", children: this.state.error?.message || "An unexpected error occurred" })
621
+ ] });
622
+ }
623
+ return this.props.children;
624
+ }
625
+ };
626
+ var getMediaSource = (value) => {
627
+ if (typeof value === "string") return value;
628
+ if (typeof value === "object" && value !== null && "type" in value && "src" in value) {
629
+ const mediaSource = value;
630
+ return mediaSource.src;
631
+ }
632
+ return String(value);
633
+ };
634
+ var SAFE_IMG_ATTRS = /* @__PURE__ */ new Set(["alt", "width", "height", "loading", "decoding", "crossOrigin", "referrerPolicy", "sizes", "srcSet", "className", "style"]);
635
+ var SAFE_VIDEO_ATTRS = /* @__PURE__ */ new Set(["width", "height", "loop", "muted", "autoPlay", "playsInline", "preload", "poster", "crossOrigin", "className", "style"]);
636
+ var filterProps = (props, allowList) => {
637
+ if (!props) return {};
638
+ return Object.fromEntries(Object.entries(props).filter(([k]) => allowList.has(k)));
639
+ };
640
+ var ImageContent = ({ src, alt = "Tour content", props }) => {
641
+ const [hasError, setHasError] = useState(false);
642
+ if (hasError) return /* @__PURE__ */ jsx(MediaFallback, { type: "image", className: "w-full h-auto" });
643
+ return /* @__PURE__ */ jsx(
644
+ "img",
645
+ {
646
+ src,
647
+ alt,
648
+ className: "w-full h-auto rounded-lg",
649
+ onError: () => setHasError(true),
650
+ ...filterProps(props, SAFE_IMG_ATTRS)
651
+ }
652
+ );
653
+ };
654
+ var VideoContent = ({ src, props }) => {
655
+ const [hasError, setHasError] = useState(false);
656
+ if (hasError) return /* @__PURE__ */ jsx(MediaFallback, { type: "video", className: "w-full h-auto" });
657
+ return /* @__PURE__ */ jsx(
658
+ "video",
659
+ {
660
+ src,
661
+ controls: true,
662
+ className: "w-full h-auto rounded-lg",
663
+ role: "presentation",
664
+ "aria-label": "Tour video content",
665
+ onError: () => setHasError(true),
666
+ ...filterProps(props, SAFE_VIDEO_ATTRS)
667
+ }
668
+ );
669
+ };
670
+ var renderContent = (content) => {
671
+ if (!content) return null;
672
+ if (typeof content === "string" || React5.isValidElement(content)) {
673
+ return content;
674
+ }
675
+ const contentObj = content;
676
+ if (typeof contentObj === "object" && contentObj !== null && "type" in contentObj && "value" in contentObj) {
677
+ const typedContent = contentObj;
678
+ switch (typedContent.type) {
679
+ case "image":
680
+ return /* @__PURE__ */ jsx(ImageContent, { src: getMediaSource(typedContent.value), alt: typedContent.alt, props: typedContent.props });
681
+ case "video":
682
+ return /* @__PURE__ */ jsx(VideoContent, { src: getMediaSource(typedContent.value), props: typedContent.props });
683
+ case "custom":
684
+ return typedContent.value;
685
+ case "text":
686
+ default:
687
+ return typedContent.value;
688
+ }
689
+ }
690
+ return content;
691
+ };
692
+ var renderButtons = (props, config) => {
693
+ const {
694
+ onNext,
695
+ onBack,
696
+ onSkip,
697
+ onComplete,
698
+ isFirstStep,
699
+ isLastStep,
700
+ skip
701
+ } = props;
702
+ if (config?.container?.render) {
703
+ return config.container.render(props);
704
+ }
705
+ return /* @__PURE__ */ jsxs(
706
+ "div",
707
+ {
708
+ className: clsx(
709
+ "flex justify-between items-center gap-2",
710
+ config?.container?.className
711
+ ),
712
+ style: {
713
+ flexDirection: config?.container?.direction || "row",
714
+ alignItems: config?.container?.align || "center",
715
+ gap: config?.container?.gap || "0.5rem",
716
+ ...config?.container?.style
717
+ },
718
+ role: "toolbar",
719
+ "aria-label": "Tour navigation",
720
+ children: [
721
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
722
+ !isFirstStep && (config?.secondary?.render ? config.secondary.render(props) : /* @__PURE__ */ jsx(
723
+ "button",
724
+ {
725
+ onClick: onBack,
726
+ className: clsx("tour-button tour-button-secondary", config?.secondary?.className),
727
+ style: config?.secondary?.style,
728
+ "aria-label": "Go to previous step",
729
+ children: config?.secondary?.content || "Back"
730
+ }
731
+ )),
732
+ skip && (config?.secondary?.render ? config.secondary.render(props) : /* @__PURE__ */ jsx(
733
+ "button",
734
+ {
735
+ onClick: onSkip,
736
+ className: clsx("tour-button tour-button-secondary", config?.secondary?.className),
737
+ style: config?.secondary?.style,
738
+ "aria-label": "Skip tour",
739
+ children: config?.secondary?.content || "Skip"
740
+ }
741
+ ))
742
+ ] }),
743
+ config?.primary?.render ? config.primary.render(props) : /* @__PURE__ */ jsx(
744
+ "button",
745
+ {
746
+ onClick: isLastStep ? onComplete : onNext,
747
+ className: clsx("tour-button tour-button-primary", config?.primary?.className),
748
+ style: config?.primary?.style,
749
+ "aria-label": isLastStep ? "Complete tour" : "Go to next step",
750
+ children: config?.primary?.content || (isLastStep ? "Done" : "Next")
751
+ }
752
+ )
753
+ ]
754
+ }
755
+ );
756
+ };
757
+ var TourTooltip = ({
758
+ content,
759
+ placement,
760
+ animation = "slide",
761
+ isFirstStep,
762
+ isLastStep,
763
+ skip,
764
+ onNext,
765
+ onBack,
766
+ onSkip,
767
+ onComplete,
768
+ tooltipClassName,
769
+ buttonClassName,
770
+ buttonContainerClassName,
771
+ targetLabel,
772
+ title,
773
+ floatingStyles,
774
+ setFloating,
775
+ showProgress = false,
776
+ currentStep,
777
+ totalSteps,
778
+ buttonConfig
779
+ }) => {
780
+ const [isVisible, setIsVisible] = useState(false);
781
+ useEffect(() => {
782
+ const timer = setTimeout(() => {
783
+ setIsVisible(true);
784
+ }, 50);
785
+ return () => {
786
+ clearTimeout(timer);
787
+ setIsVisible(false);
788
+ };
789
+ }, [placement]);
790
+ return /* @__PURE__ */ jsxs(
791
+ "div",
792
+ {
793
+ ref: setFloating,
794
+ style: floatingStyles,
795
+ className: clsx("tour-tooltip z-50", tooltipClassName, { visible: isVisible }),
796
+ role: "dialog",
797
+ "aria-modal": "true",
798
+ "aria-labelledby": "tour-step-title",
799
+ "aria-describedby": "tour-step-content",
800
+ "data-placement": placement,
801
+ "data-animation": animation,
802
+ children: [
803
+ title ? /* @__PURE__ */ jsx("h3", { id: "tour-step-title", className: "tour-tooltip-title", children: title }) : /* @__PURE__ */ jsx("div", { id: "tour-step-title", className: "sr-only", children: `Tour Step: ${targetLabel}` }),
804
+ showProgress && currentStep !== void 0 && totalSteps !== void 0 && /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
805
+ /* @__PURE__ */ jsx("div", { className: "flex justify-between items-center mb-1", children: /* @__PURE__ */ jsx("span", { className: "text-xs", style: { opacity: 0.6 }, "aria-hidden": "true", children: `Step ${currentStep + 1} of ${totalSteps}` }) }),
806
+ /* @__PURE__ */ jsx(ProgressBar, { currentStep, totalSteps })
807
+ ] }),
808
+ /* @__PURE__ */ jsx("div", { id: "tour-step-content", className: "mb-4", children: /* @__PURE__ */ jsx(
809
+ ErrorBoundary,
810
+ {
811
+ fallback: /* @__PURE__ */ jsxs("div", { className: "p-4 bg-gray-50 border border-gray-200 rounded-lg", children: [
812
+ /* @__PURE__ */ jsx("div", { className: "text-gray-600 mb-2", children: "Content Error" }),
813
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-500", children: "Failed to render tour content" })
814
+ ] }),
815
+ children: renderContent(content)
816
+ }
817
+ ) }),
818
+ renderButtons(
819
+ {
820
+ onNext,
821
+ onBack,
822
+ onSkip,
823
+ onComplete,
824
+ isFirstStep,
825
+ isLastStep,
826
+ currentStep,
827
+ totalSteps,
828
+ skip
829
+ },
830
+ buttonConfig || {
831
+ primary: { className: buttonClassName },
832
+ secondary: { className: buttonClassName },
833
+ container: { className: buttonContainerClassName }
834
+ }
835
+ )
836
+ ]
837
+ }
838
+ );
839
+ };
840
+ var TourOverlay = ({
841
+ overlayClassName,
842
+ isPartialBlur,
843
+ hasHighlight,
844
+ onDismiss
845
+ }) => {
846
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
847
+ isPartialBlur && /* @__PURE__ */ jsx(
848
+ "div",
849
+ {
850
+ className: "fixed inset-0 z-40 backdrop-blur-sm bg-black/40",
851
+ style: {
852
+ mixBlendMode: "multiply"
853
+ },
854
+ onClick: onDismiss,
855
+ role: "presentation",
856
+ "aria-hidden": "true"
857
+ }
858
+ ),
859
+ !hasHighlight && /* @__PURE__ */ jsx(
860
+ "div",
861
+ {
862
+ className: clsx("tour-overlay fixed inset-0 z-40", overlayClassName),
863
+ onClick: onDismiss,
864
+ role: "presentation",
865
+ "aria-hidden": "true"
866
+ }
867
+ )
868
+ ] });
869
+ };
870
+ var TourHighlight = ({
871
+ targetRect,
872
+ highlightConfig,
873
+ animation = "slide"
874
+ }) => {
875
+ const padding = parseFloat(
876
+ getComputedStyle(document.documentElement).getPropertyValue("--tour--highlight--padding") || "8"
877
+ );
878
+ const [isVisible, setIsVisible] = useState(false);
879
+ useEffect(() => {
880
+ const timer = setTimeout(() => {
881
+ setIsVisible(true);
882
+ }, 50);
883
+ return () => {
884
+ clearTimeout(timer);
885
+ setIsVisible(false);
886
+ };
887
+ }, [targetRect]);
888
+ return /* @__PURE__ */ jsx(
889
+ "div",
890
+ {
891
+ style: {
892
+ position: "fixed",
893
+ top: targetRect.top - padding,
894
+ left: targetRect.left - padding,
895
+ width: targetRect.width + padding * 2,
896
+ height: targetRect.height + padding * 2,
897
+ ...highlightConfig.style
898
+ },
899
+ className: clsx(
900
+ "tour-highlight z-50",
901
+ highlightConfig.className,
902
+ { visible: isVisible }
903
+ ),
904
+ "data-animation": animation,
905
+ role: "presentation",
906
+ "aria-hidden": "true"
907
+ }
908
+ );
909
+ };
910
+ var LiveRegion = ({
911
+ currentStep,
912
+ totalSteps,
913
+ targetLabel,
914
+ content,
915
+ isActive,
916
+ announcements
917
+ }) => {
918
+ const ref = useRef(null);
919
+ useEffect(() => {
920
+ if (!isActive || !ref.current) return;
921
+ const contentText = typeof content === "string" ? content : "";
922
+ const defaultStepAnnouncement = `Step ${currentStep + 1} of ${totalSteps}: ${targetLabel}.${contentText ? ` ${contentText}` : ""}`;
923
+ const stepAnnouncement = announcements?.step ? announcements.step.replace("{step}", String(currentStep + 1)).replace("{total}", String(totalSteps)).replace("{content}", contentText) : defaultStepAnnouncement;
924
+ ref.current.textContent = stepAnnouncement;
925
+ }, [currentStep, totalSteps, targetLabel, content, isActive, announcements]);
926
+ return React5.createElement("div", {
927
+ ref,
928
+ role: "status",
929
+ "aria-live": "polite",
930
+ "aria-atomic": "true",
931
+ className: "sr-only"
932
+ });
933
+ };
934
+ var useTourAccessibility = ({
935
+ currentStep,
936
+ totalSteps,
937
+ targetLabel,
938
+ content,
939
+ isActive,
940
+ enableScreenReader = false,
941
+ announcements,
942
+ focusManagement = "auto",
943
+ focusTrap = true
944
+ }) => {
945
+ const previousFocusRef = useRef(null);
946
+ useEffect(() => {
947
+ if (focusManagement === "manual") return;
948
+ previousFocusRef.current = document.activeElement;
949
+ const focusableElements = document.querySelectorAll(
950
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
951
+ );
952
+ if (focusableElements.length > 0) {
953
+ focusableElements[0].focus();
954
+ }
955
+ return () => {
956
+ if (previousFocusRef.current && document.contains(previousFocusRef.current)) {
957
+ previousFocusRef.current.focus();
958
+ }
959
+ };
960
+ }, [isActive, focusManagement]);
961
+ useEffect(() => {
962
+ if (!focusTrap) return;
963
+ const handleTabKey = (e) => {
964
+ const focusableElements = document.querySelectorAll(
965
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
966
+ );
967
+ if (focusableElements.length === 0) return;
968
+ const firstFocusableElement = focusableElements[0];
969
+ const lastFocusableElement = focusableElements[focusableElements.length - 1];
970
+ if (e.key === "Tab") {
971
+ if (e.shiftKey) {
972
+ if (document.activeElement === firstFocusableElement) {
973
+ e.preventDefault();
974
+ lastFocusableElement.focus();
975
+ }
976
+ } else {
977
+ if (document.activeElement === lastFocusableElement) {
978
+ e.preventDefault();
979
+ firstFocusableElement.focus();
980
+ }
981
+ }
982
+ }
983
+ };
984
+ document.addEventListener("keydown", handleTabKey);
985
+ return () => document.removeEventListener("keydown", handleTabKey);
986
+ }, [isActive, focusTrap]);
987
+ return {
988
+ LiveRegion: () => React5.createElement(LiveRegion, {
989
+ currentStep,
990
+ totalSteps,
991
+ targetLabel,
992
+ content,
993
+ isActive,
994
+ announcements
995
+ }),
996
+ targetLabel
997
+ };
998
+ };
999
+ function useDebounce(callback, delay) {
1000
+ const timeoutRef = useRef();
1001
+ return useCallback(
1002
+ (...args) => {
1003
+ if (timeoutRef.current) {
1004
+ clearTimeout(timeoutRef.current);
1005
+ }
1006
+ timeoutRef.current = setTimeout(() => {
1007
+ callback(...args);
1008
+ }, delay);
1009
+ },
1010
+ [callback, delay]
1011
+ );
1012
+ }
1013
+ var Spotlight = memo(({
1014
+ targetElement,
1015
+ placement,
1016
+ content,
1017
+ onNext,
1018
+ onBack,
1019
+ onSkip,
1020
+ onComplete,
1021
+ isFirstStep,
1022
+ isLastStep,
1023
+ skip = true,
1024
+ overlayClassName,
1025
+ tooltipClassName,
1026
+ buttonClassName,
1027
+ buttonContainerClassName,
1028
+ highlightTarget = true,
1029
+ currentStep,
1030
+ totalSteps,
1031
+ showProgress = false,
1032
+ accessibility = {},
1033
+ animation = "slide",
1034
+ tooltipOffset = 10,
1035
+ buttonConfig,
1036
+ dismissOnOverlayClick = true,
1037
+ title
1038
+ }) => {
1039
+ const middleware = useMemo(
1040
+ () => [offset(tooltipOffset), flip(), shift()],
1041
+ [tooltipOffset]
1042
+ );
1043
+ const { refs: tooltipRefs, floatingStyles, update } = useFloating({
1044
+ placement,
1045
+ middleware,
1046
+ whileElementsMounted: autoUpdate
1047
+ });
1048
+ const { LiveRegion: LiveRegion2, targetLabel } = useTourAccessibility({
1049
+ currentStep: currentStep ?? 0,
1050
+ totalSteps: totalSteps ?? 0,
1051
+ targetLabel: targetElement?.getAttribute("aria-label") || "target element",
1052
+ content,
1053
+ isActive: true,
1054
+ enableScreenReader: accessibility.enableScreenReader,
1055
+ announcements: accessibility.announcements,
1056
+ focusManagement: accessibility.focusManagement,
1057
+ focusTrap: accessibility.focusTrap
1058
+ });
1059
+ const highlightConfig = typeof highlightTarget === "object" ? highlightTarget : { className: "tour-highlight" };
1060
+ const isPartialBlur = overlayClassName?.includes("tour-overlay-partial-blur");
1061
+ const [rect, setRect] = useState(
1062
+ () => targetElement ? targetElement.getBoundingClientRect() : null
1063
+ );
1064
+ const debouncedUpdate = useDebounce(update, 100);
1065
+ const debouncedUpdateRef = useRef(debouncedUpdate);
1066
+ useEffect(() => {
1067
+ debouncedUpdateRef.current = debouncedUpdate;
1068
+ });
1069
+ useEffect(() => {
1070
+ if (!targetElement) return;
1071
+ tooltipRefs.setReference(targetElement);
1072
+ targetElement.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
1073
+ setRect(targetElement.getBoundingClientRect());
1074
+ }, [targetElement, tooltipRefs]);
1075
+ useEffect(() => {
1076
+ if (!targetElement) return;
1077
+ const updateRect = () => {
1078
+ setRect(targetElement.getBoundingClientRect());
1079
+ debouncedUpdateRef.current();
1080
+ };
1081
+ window.addEventListener("scroll", updateRect, { passive: true });
1082
+ window.addEventListener("resize", updateRect, { passive: true });
1083
+ return () => {
1084
+ window.removeEventListener("scroll", updateRect);
1085
+ window.removeEventListener("resize", updateRect);
1086
+ };
1087
+ }, [targetElement]);
1088
+ if (!targetElement || !rect) return null;
1089
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1090
+ accessibility.enableScreenReader !== false && /* @__PURE__ */ jsx(LiveRegion2, {}),
1091
+ /* @__PURE__ */ jsx(
1092
+ TourOverlay,
1093
+ {
1094
+ overlayClassName,
1095
+ isPartialBlur,
1096
+ hasHighlight: !!highlightTarget,
1097
+ onDismiss: dismissOnOverlayClick ? onSkip : void 0
1098
+ }
1099
+ ),
1100
+ highlightTarget && /* @__PURE__ */ jsx(
1101
+ TourHighlight,
1102
+ {
1103
+ targetRect: rect,
1104
+ highlightConfig,
1105
+ animation
1106
+ }
1107
+ ),
1108
+ isPartialBlur && targetElement.id && /* @__PURE__ */ jsx("style", { children: `
1109
+ #${CSS.escape(targetElement.id)} {
1110
+ isolation: isolate;
1111
+ position: relative;
1112
+ z-index: 50;
1113
+ transform: translateZ(0);
1114
+ will-change: transform;
1115
+ }
1116
+ ` }),
1117
+ /* @__PURE__ */ jsx(
1118
+ TourTooltip,
1119
+ {
1120
+ content,
1121
+ placement,
1122
+ isFirstStep,
1123
+ isLastStep,
1124
+ skip,
1125
+ onNext,
1126
+ onBack,
1127
+ onSkip,
1128
+ onComplete,
1129
+ tooltipClassName,
1130
+ buttonClassName,
1131
+ buttonContainerClassName,
1132
+ targetLabel,
1133
+ floatingStyles,
1134
+ setFloating: tooltipRefs.setFloating,
1135
+ showProgress,
1136
+ currentStep,
1137
+ totalSteps,
1138
+ animation,
1139
+ buttonConfig,
1140
+ title
1141
+ }
1142
+ )
1143
+ ] });
1144
+ });
1145
+ var Tour = ({
1146
+ overlayClassName,
1147
+ tooltipClassName,
1148
+ buttonClassName,
1149
+ buttonContainerClassName,
1150
+ highlightTarget,
1151
+ skip = true,
1152
+ showProgress = false,
1153
+ accessibility = {},
1154
+ animation = "slide",
1155
+ tooltipOffset,
1156
+ buttonConfig,
1157
+ dismissOnOverlayClick = true
1158
+ }) => {
1159
+ const { steps, currentStep, isActive, next, back, skip: skipTour } = useTour();
1160
+ const [targetElement, setTargetElement] = useState(null);
1161
+ const enableScreenReader = accessibility.enableScreenReader;
1162
+ const startAnnouncement = accessibility.announcements?.start ?? "Tour started. Use arrow keys to navigate between steps.";
1163
+ const endAnnouncement = accessibility.announcements?.end ?? "Tour ended.";
1164
+ useEffect(() => {
1165
+ if (!isActive) return;
1166
+ const handleKeyDown = (e) => {
1167
+ if (e.key === "Escape") {
1168
+ skipTour();
1169
+ return;
1170
+ }
1171
+ const target = e.target;
1172
+ if (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.tagName === "SELECT" || target.isContentEditable) return;
1173
+ if (e.key === "ArrowRight" || e.key === "ArrowDown") {
1174
+ e.preventDefault();
1175
+ next();
1176
+ } else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
1177
+ e.preventDefault();
1178
+ back();
1179
+ }
1180
+ };
1181
+ document.addEventListener("keydown", handleKeyDown);
1182
+ return () => document.removeEventListener("keydown", handleKeyDown);
1183
+ }, [isActive, skipTour, next, back]);
1184
+ useEffect(() => {
1185
+ if (!isActive || enableScreenReader === false) return;
1186
+ const announcement = document.createElement("div");
1187
+ announcement.setAttribute("role", "status");
1188
+ announcement.setAttribute("aria-live", "polite");
1189
+ announcement.setAttribute("aria-atomic", "true");
1190
+ announcement.className = "sr-only";
1191
+ announcement.textContent = startAnnouncement;
1192
+ document.body.appendChild(announcement);
1193
+ const startTimerId = setTimeout(() => {
1194
+ if (announcement.isConnected) document.body.removeChild(announcement);
1195
+ }, 3e3);
1196
+ return () => {
1197
+ clearTimeout(startTimerId);
1198
+ if (announcement.isConnected) document.body.removeChild(announcement);
1199
+ const endEl = document.createElement("div");
1200
+ endEl.setAttribute("role", "status");
1201
+ endEl.setAttribute("aria-live", "polite");
1202
+ endEl.setAttribute("aria-atomic", "true");
1203
+ endEl.className = "sr-only";
1204
+ endEl.textContent = endAnnouncement;
1205
+ document.body.appendChild(endEl);
1206
+ setTimeout(() => {
1207
+ if (endEl.isConnected) document.body.removeChild(endEl);
1208
+ }, 3e3);
1209
+ };
1210
+ }, [isActive, enableScreenReader, startAnnouncement, endAnnouncement]);
1211
+ useEffect(() => {
1212
+ if (!isActive) return;
1213
+ let mounted = true;
1214
+ const currentStepData2 = steps[currentStep];
1215
+ if (!currentStepData2) return;
1216
+ setTargetElement(null);
1217
+ let element = null;
1218
+ try {
1219
+ element = document.querySelector(currentStepData2.selector);
1220
+ } catch {
1221
+ return;
1222
+ }
1223
+ if (element) {
1224
+ setTargetElement(element);
1225
+ } else if (currentStepData2.waitFor) {
1226
+ currentStepData2.waitFor().then(() => {
1227
+ if (!mounted) return;
1228
+ try {
1229
+ const el = document.querySelector(currentStepData2.selector);
1230
+ setTargetElement(el);
1231
+ } catch {
1232
+ }
1233
+ }).catch(() => {
1234
+ });
1235
+ }
1236
+ return () => {
1237
+ mounted = false;
1238
+ };
1239
+ }, [isActive, currentStep, steps]);
1240
+ const currentStepData = steps[currentStep];
1241
+ if (!isActive || !currentStepData) return null;
1242
+ if (!targetElement) {
1243
+ const isLastStep = currentStep === steps.length - 1;
1244
+ return createPortal(
1245
+ /* @__PURE__ */ jsxs(Fragment, { children: [
1246
+ /* @__PURE__ */ jsx(
1247
+ "div",
1248
+ {
1249
+ className: "tour-overlay fixed inset-0 z-40",
1250
+ onClick: dismissOnOverlayClick ? skipTour : void 0,
1251
+ role: "presentation",
1252
+ "aria-hidden": "true"
1253
+ }
1254
+ ),
1255
+ /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs(
1256
+ "div",
1257
+ {
1258
+ className: "tour-tooltip pointer-events-auto",
1259
+ role: "dialog",
1260
+ "aria-modal": "true",
1261
+ "aria-label": "Tour step unavailable",
1262
+ children: [
1263
+ /* @__PURE__ */ jsx("p", { className: "mb-4 text-sm", style: { opacity: 0.7 }, children: "This step is currently unavailable." }),
1264
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
1265
+ /* @__PURE__ */ jsx("button", { onClick: skipTour, className: "tour-button tour-button-secondary", "aria-label": "Skip tour", children: "Skip" }),
1266
+ !isLastStep && /* @__PURE__ */ jsx("button", { onClick: next, className: "tour-button tour-button-primary", "aria-label": "Go to next step", children: "Next" })
1267
+ ] })
1268
+ ]
1269
+ }
1270
+ ) })
1271
+ ] }),
1272
+ document.body
1273
+ );
1274
+ }
1275
+ return createPortal(
1276
+ /* @__PURE__ */ jsx(
1277
+ Spotlight,
1278
+ {
1279
+ targetElement,
1280
+ placement: currentStepData.placement || "bottom",
1281
+ title: currentStepData.title,
1282
+ content: currentStepData.content,
1283
+ onNext: next,
1284
+ onBack: back,
1285
+ onSkip: skipTour,
1286
+ onComplete: next,
1287
+ isFirstStep: currentStep === 0,
1288
+ isLastStep: currentStep === steps.length - 1,
1289
+ overlayClassName,
1290
+ tooltipClassName,
1291
+ buttonClassName,
1292
+ buttonContainerClassName,
1293
+ highlightTarget,
1294
+ skip,
1295
+ showProgress,
1296
+ currentStep,
1297
+ totalSteps: steps.length,
1298
+ accessibility,
1299
+ animation,
1300
+ tooltipOffset,
1301
+ buttonConfig,
1302
+ dismissOnOverlayClick
1303
+ }
1304
+ ),
1305
+ document.body
1306
+ );
1307
+ };
1308
+
1309
+ export { Tour, TourProvider, tourManager, useTour2 as useTour };
1310
+ //# sourceMappingURL=index.mjs.map
1311
+ //# sourceMappingURL=index.mjs.map