@aladinbs/react-guided-tour 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.
Files changed (37) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +581 -0
  3. package/dist/components/TourOverlay.d.ts +5 -0
  4. package/dist/components/TourOverlay.d.ts.map +1 -0
  5. package/dist/components/TourPopover.d.ts +5 -0
  6. package/dist/components/TourPopover.d.ts.map +1 -0
  7. package/dist/components/TourProvider.d.ts +15 -0
  8. package/dist/components/TourProvider.d.ts.map +1 -0
  9. package/dist/components/TourRunner.d.ts +5 -0
  10. package/dist/components/TourRunner.d.ts.map +1 -0
  11. package/dist/core/TourActions.d.ts +15 -0
  12. package/dist/core/TourActions.d.ts.map +1 -0
  13. package/dist/core/TourEngine.d.ts +35 -0
  14. package/dist/core/TourEngine.d.ts.map +1 -0
  15. package/dist/core/TourStorage.d.ts +14 -0
  16. package/dist/core/TourStorage.d.ts.map +1 -0
  17. package/dist/hooks/useTourEngine.d.ts +21 -0
  18. package/dist/hooks/useTourEngine.d.ts.map +1 -0
  19. package/dist/hooks/useTourHighlight.d.ts +8 -0
  20. package/dist/hooks/useTourHighlight.d.ts.map +1 -0
  21. package/dist/index.d.ts +326 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.esm.js +2097 -0
  24. package/dist/index.esm.js.map +1 -0
  25. package/dist/index.js +2116 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/integrations/NavigationIntegration.d.ts +24 -0
  28. package/dist/integrations/NavigationIntegration.d.ts.map +1 -0
  29. package/dist/integrations/TabIntegration.d.ts +19 -0
  30. package/dist/integrations/TabIntegration.d.ts.map +1 -0
  31. package/dist/integrations/WizardIntegration.d.ts +23 -0
  32. package/dist/integrations/WizardIntegration.d.ts.map +1 -0
  33. package/dist/types/index.d.ts +137 -0
  34. package/dist/types/index.d.ts.map +1 -0
  35. package/dist/utils/positioning.d.ts +10 -0
  36. package/dist/utils/positioning.d.ts.map +1 -0
  37. package/package.json +75 -0
@@ -0,0 +1,2097 @@
1
+ import require$$0, { useMemo, useState, useEffect, useCallback, createContext, useContext, useRef } from 'react';
2
+
3
+ class TourStorage {
4
+ constructor(key) {
5
+ this.key = key;
6
+ }
7
+ saveState(state) {
8
+ try {
9
+ const stateToSave = {
10
+ currentStepIndex: state.currentStepIndex,
11
+ completedSteps: state.completedSteps,
12
+ skippedSteps: state.skippedSteps,
13
+ isCompleted: false,
14
+ isSkipped: false,
15
+ };
16
+ localStorage.setItem(this.key, JSON.stringify(stateToSave));
17
+ }
18
+ catch (error) {
19
+ console.warn('Failed to save tour state to localStorage:', error);
20
+ }
21
+ }
22
+ getState() {
23
+ try {
24
+ const saved = localStorage.getItem(this.key);
25
+ if (!saved)
26
+ return null;
27
+ return JSON.parse(saved);
28
+ }
29
+ catch (error) {
30
+ console.warn('Failed to load tour state from localStorage:', error);
31
+ return null;
32
+ }
33
+ }
34
+ clearState() {
35
+ try {
36
+ localStorage.removeItem(this.key);
37
+ }
38
+ catch (error) {
39
+ console.warn('Failed to clear tour state from localStorage:', error);
40
+ }
41
+ }
42
+ hasState() {
43
+ try {
44
+ return localStorage.getItem(this.key) !== null;
45
+ }
46
+ catch (error) {
47
+ return false;
48
+ }
49
+ }
50
+ saveCompletion() {
51
+ try {
52
+ const existing = this.getState() || {};
53
+ const stateToSave = {
54
+ ...existing,
55
+ isCompleted: true,
56
+ completedAt: new Date().toISOString(),
57
+ };
58
+ localStorage.setItem(this.key, JSON.stringify(stateToSave));
59
+ }
60
+ catch (error) {
61
+ console.warn('Failed to save tour completion to localStorage:', error);
62
+ }
63
+ }
64
+ saveSkip() {
65
+ try {
66
+ const existing = this.getState() || {};
67
+ const stateToSave = {
68
+ ...existing,
69
+ isSkipped: true,
70
+ skippedAt: new Date().toISOString(),
71
+ };
72
+ localStorage.setItem(this.key, JSON.stringify(stateToSave));
73
+ }
74
+ catch (error) {
75
+ console.warn('Failed to save tour skip to localStorage:', error);
76
+ }
77
+ }
78
+ isCompleted() {
79
+ try {
80
+ const saved = this.getState();
81
+ return saved?.isCompleted === true;
82
+ }
83
+ catch (error) {
84
+ return false;
85
+ }
86
+ }
87
+ isSkipped() {
88
+ try {
89
+ const saved = this.getState();
90
+ return saved?.isSkipped === true;
91
+ }
92
+ catch (error) {
93
+ return false;
94
+ }
95
+ }
96
+ }
97
+
98
+ class TourEngine {
99
+ constructor(config) {
100
+ this.listeners = new Map();
101
+ this.config = config;
102
+ this.storage = new TourStorage(config.storage?.key || `tour-${config.id}`);
103
+ this.state = this.initializeState();
104
+ }
105
+ initializeState() {
106
+ const savedState = this.config.storage?.remember ? this.storage.getState() : null;
107
+ return {
108
+ isRunning: false,
109
+ currentStepIndex: savedState?.currentStepIndex || 0,
110
+ currentStep: null,
111
+ totalSteps: this.config.steps.length,
112
+ isLoading: false,
113
+ error: null,
114
+ completedSteps: savedState?.completedSteps || [],
115
+ skippedSteps: savedState?.skippedSteps || [],
116
+ isCompleted: savedState?.isCompleted || false,
117
+ isSkipped: savedState?.isSkipped || false,
118
+ completedAt: savedState?.completedAt,
119
+ skippedAt: savedState?.skippedAt,
120
+ };
121
+ }
122
+ getState() {
123
+ return { ...this.state };
124
+ }
125
+ getConfig() {
126
+ return { ...this.config };
127
+ }
128
+ async start() {
129
+ try {
130
+ this.setState({
131
+ isRunning: true,
132
+ isLoading: true,
133
+ error: null
134
+ });
135
+ this.emit('tour-start', { tourId: this.config.id });
136
+ await this.goToStep(this.state.currentStepIndex);
137
+ // STOP HERE - don't auto-advance
138
+ return;
139
+ }
140
+ catch (error) {
141
+ console.error('Error in TourEngine.start():', error);
142
+ this.handleError(error);
143
+ }
144
+ }
145
+ async next() {
146
+ if (!this.state.isRunning) {
147
+ return;
148
+ }
149
+ try {
150
+ const currentStep = this.getCurrentStep();
151
+ if (!currentStep) {
152
+ return;
153
+ }
154
+ // Execute after step hook
155
+ if (currentStep.afterStep) {
156
+ await currentStep.afterStep();
157
+ }
158
+ // Mark step as completed
159
+ this.markStepCompleted(currentStep.id);
160
+ // Check if this is the last step
161
+ if (this.state.currentStepIndex >= this.state.totalSteps - 1) {
162
+ await this.complete();
163
+ return;
164
+ }
165
+ // Go to next step
166
+ const nextStepIndex = this.state.currentStepIndex + 1;
167
+ await this.goToStep(nextStepIndex);
168
+ }
169
+ catch (error) {
170
+ console.error('Error in TourEngine.next():', error);
171
+ this.handleError(error);
172
+ }
173
+ }
174
+ async previous() {
175
+ if (!this.state.isRunning || this.state.currentStepIndex <= 0)
176
+ return;
177
+ try {
178
+ await this.goToStep(this.state.currentStepIndex - 1);
179
+ }
180
+ catch (error) {
181
+ this.handleError(error);
182
+ }
183
+ }
184
+ async goToStep(index) {
185
+ if (index < 0 || index >= this.state.totalSteps)
186
+ return;
187
+ try {
188
+ this.setState({ isLoading: true });
189
+ const step = this.config.steps[index];
190
+ // Execute before step hook
191
+ if (step.beforeStep) {
192
+ await step.beforeStep();
193
+ }
194
+ // Wait for element if specified
195
+ if (step.waitForElement && step.target) {
196
+ await this.waitForElement(step.target, step.waitTimeout || 5000);
197
+ }
198
+ this.setState({
199
+ currentStepIndex: index,
200
+ currentStep: step,
201
+ isLoading: false,
202
+ });
203
+ // Save state if persistence is enabled
204
+ if (this.config.storage?.remember) {
205
+ this.storage.saveState(this.state);
206
+ }
207
+ // Emit step change event
208
+ this.emit('step-change', { step, index });
209
+ if (this.config.onStepChange) {
210
+ this.config.onStepChange(step, index);
211
+ }
212
+ }
213
+ catch (error) {
214
+ this.setState({ isLoading: false });
215
+ this.handleError(error);
216
+ }
217
+ }
218
+ async skip() {
219
+ if (!this.state.isRunning)
220
+ return;
221
+ try {
222
+ const currentStep = this.getCurrentStep();
223
+ if (currentStep) {
224
+ this.markStepSkipped(currentStep.id);
225
+ }
226
+ this.setState({ isSkipped: true });
227
+ this.emit('tour-skip', { tourId: this.config.id, stepIndex: this.state.currentStepIndex });
228
+ if (this.config.onSkip) {
229
+ this.config.onSkip();
230
+ }
231
+ // Save skip state to localStorage
232
+ if (this.config.storage?.remember) {
233
+ this.storage.saveSkip();
234
+ }
235
+ await this.stop();
236
+ }
237
+ catch (error) {
238
+ console.error('Error in TourEngine.skip():', error);
239
+ this.handleError(error);
240
+ }
241
+ }
242
+ async complete() {
243
+ try {
244
+ this.setState({ isRunning: false, isCompleted: true });
245
+ this.emit('tour-complete', { tourId: this.config.id });
246
+ if (this.config.onComplete) {
247
+ this.config.onComplete();
248
+ }
249
+ // Save completion state to localStorage
250
+ if (this.config.storage?.remember) {
251
+ this.storage.saveCompletion();
252
+ }
253
+ }
254
+ catch (error) {
255
+ console.error('Error in TourEngine.complete():', error);
256
+ this.handleError(error);
257
+ }
258
+ }
259
+ async stop() {
260
+ this.setState({
261
+ isRunning: false,
262
+ currentStep: null,
263
+ });
264
+ }
265
+ getCurrentStep() {
266
+ return this.state.currentStep;
267
+ }
268
+ isFirstStep() {
269
+ return this.state.currentStepIndex === 0;
270
+ }
271
+ isLastStep() {
272
+ return this.state.currentStepIndex === this.state.totalSteps - 1;
273
+ }
274
+ canGoNext() {
275
+ return this.state.isRunning && !this.isLastStep() && !this.state.isLoading;
276
+ }
277
+ canGoPrevious() {
278
+ return this.state.isRunning && !this.isFirstStep() && !this.state.isLoading;
279
+ }
280
+ shouldShowTour() {
281
+ if (!this.config.storage?.remember)
282
+ return true;
283
+ return !this.storage.isCompleted() && !this.storage.isSkipped();
284
+ }
285
+ resetTourState() {
286
+ if (this.config.storage?.remember) {
287
+ this.storage.clearState();
288
+ }
289
+ this.state = this.initializeState();
290
+ }
291
+ async waitForElement(selector, timeout) {
292
+ return new Promise((resolve, reject) => {
293
+ const element = document.querySelector(selector);
294
+ if (element) {
295
+ resolve(element);
296
+ return;
297
+ }
298
+ const observer = new MutationObserver(() => {
299
+ const element = document.querySelector(selector);
300
+ if (element) {
301
+ observer.disconnect();
302
+ clearTimeout(timeoutId);
303
+ resolve(element);
304
+ }
305
+ });
306
+ const timeoutId = setTimeout(() => {
307
+ observer.disconnect();
308
+ reject(new Error(`Element not found: ${selector}`));
309
+ }, timeout);
310
+ observer.observe(document.body, {
311
+ childList: true,
312
+ subtree: true,
313
+ });
314
+ });
315
+ }
316
+ markStepCompleted(stepId) {
317
+ if (!this.state.completedSteps.includes(stepId)) {
318
+ this.setState({
319
+ completedSteps: [...this.state.completedSteps, stepId],
320
+ });
321
+ }
322
+ }
323
+ markStepSkipped(stepId) {
324
+ if (!this.state.skippedSteps.includes(stepId)) {
325
+ this.setState({
326
+ skippedSteps: [...this.state.skippedSteps, stepId],
327
+ });
328
+ }
329
+ }
330
+ handleError(error) {
331
+ this.setState({
332
+ error: error.message,
333
+ isLoading: false,
334
+ });
335
+ this.emit('error', { error, step: this.getCurrentStep() || undefined });
336
+ }
337
+ setState(updates) {
338
+ this.state = { ...this.state, ...updates };
339
+ // Emit state change event to notify subscribers
340
+ this.emit('state-change', this.state);
341
+ }
342
+ // Event system
343
+ on(event, callback) {
344
+ if (!this.listeners.has(event)) {
345
+ this.listeners.set(event, new Set());
346
+ }
347
+ this.listeners.get(event).add(callback);
348
+ }
349
+ off(event, callback) {
350
+ const callbacks = this.listeners.get(event);
351
+ if (callbacks) {
352
+ callbacks.delete(callback);
353
+ }
354
+ }
355
+ emit(event, data) {
356
+ const callbacks = this.listeners.get(event);
357
+ if (callbacks) {
358
+ callbacks.forEach(callback => callback(data));
359
+ }
360
+ }
361
+ subscribe(callback) {
362
+ const handler = () => callback(this.getState());
363
+ // Listen to all events that might change state
364
+ this.on('step-change', handler);
365
+ this.on('tour-start', handler);
366
+ this.on('tour-complete', handler);
367
+ this.on('tour-skip', handler);
368
+ this.on('error', handler);
369
+ this.on('state-change', handler);
370
+ // Return unsubscribe function
371
+ return () => {
372
+ this.off('step-change', handler);
373
+ this.off('tour-start', handler);
374
+ this.off('tour-complete', handler);
375
+ this.off('tour-skip', handler);
376
+ this.off('error', handler);
377
+ this.off('state-change', handler);
378
+ };
379
+ }
380
+ }
381
+
382
+ class TourActions {
383
+ constructor() {
384
+ this.integrations = new Map();
385
+ }
386
+ registerIntegration(integration) {
387
+ this.integrations.set(integration.name, integration);
388
+ }
389
+ unregisterIntegration(name) {
390
+ this.integrations.delete(name);
391
+ }
392
+ async execute(action, element) {
393
+ // Find the appropriate integration for this action
394
+ const integration = this.findIntegration(action);
395
+ if (!integration) {
396
+ // Fallback to default action handling
397
+ await this.executeDefault(action, element);
398
+ return;
399
+ }
400
+ try {
401
+ await integration.execute(action, element);
402
+ }
403
+ catch (error) {
404
+ console.error(`Integration ${integration.name} failed to execute action:`, error);
405
+ // Fallback to default action handling
406
+ await this.executeDefault(action, element);
407
+ }
408
+ }
409
+ findIntegration(action) {
410
+ for (const integration of this.integrations.values()) {
411
+ if (integration.canHandle(action)) {
412
+ return integration;
413
+ }
414
+ }
415
+ return null;
416
+ }
417
+ async executeDefault(action, element) {
418
+ const delay = action.delay || 0;
419
+ if (delay > 0) {
420
+ await this.sleep(delay);
421
+ }
422
+ switch (action.type) {
423
+ case 'click':
424
+ await this.handleClick(action, element);
425
+ break;
426
+ case 'navigate':
427
+ await this.handleNavigate(action);
428
+ break;
429
+ case 'highlight':
430
+ // Highlighting is handled by the UI components
431
+ break;
432
+ case 'custom':
433
+ if (action.handler) {
434
+ await action.handler();
435
+ }
436
+ break;
437
+ default:
438
+ console.warn(`Unknown action type: ${action.type}`);
439
+ }
440
+ }
441
+ async handleClick(action, element) {
442
+ let targetElement = element;
443
+ if (!targetElement && action.target) {
444
+ targetElement = document.querySelector(action.target);
445
+ }
446
+ if (!targetElement) {
447
+ throw new Error(`Click target not found: ${action.target}`);
448
+ }
449
+ // Ensure element is visible and clickable
450
+ targetElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
451
+ // Wait a bit for scroll to complete
452
+ await this.sleep(300);
453
+ // Dispatch click event
454
+ const clickEvent = new MouseEvent('click', {
455
+ bubbles: true,
456
+ cancelable: true,
457
+ view: window,
458
+ });
459
+ targetElement.dispatchEvent(clickEvent);
460
+ }
461
+ async handleNavigate(action) {
462
+ if (!action.target) {
463
+ throw new Error('Navigate action requires a target URL');
464
+ }
465
+ // Check if it's a hash navigation (same page)
466
+ if (action.target.startsWith('#')) {
467
+ window.location.hash = action.target;
468
+ return;
469
+ }
470
+ // Check if it's a relative path
471
+ if (action.target.startsWith('/')) {
472
+ window.location.pathname = action.target;
473
+ return;
474
+ }
475
+ // Full URL navigation
476
+ window.location.href = action.target;
477
+ }
478
+ sleep(ms) {
479
+ return new Promise(resolve => setTimeout(resolve, ms));
480
+ }
481
+ getRegisteredIntegrations() {
482
+ return Array.from(this.integrations.keys());
483
+ }
484
+ hasIntegration(name) {
485
+ return this.integrations.has(name);
486
+ }
487
+ }
488
+
489
+ var jsxRuntime = {exports: {}};
490
+
491
+ var reactJsxRuntime_production = {};
492
+
493
+ /**
494
+ * @license React
495
+ * react-jsx-runtime.production.js
496
+ *
497
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
498
+ *
499
+ * This source code is licensed under the MIT license found in the
500
+ * LICENSE file in the root directory of this source tree.
501
+ */
502
+
503
+ var hasRequiredReactJsxRuntime_production;
504
+
505
+ function requireReactJsxRuntime_production () {
506
+ if (hasRequiredReactJsxRuntime_production) return reactJsxRuntime_production;
507
+ hasRequiredReactJsxRuntime_production = 1;
508
+ var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
509
+ REACT_FRAGMENT_TYPE = Symbol.for("react.fragment");
510
+ function jsxProd(type, config, maybeKey) {
511
+ var key = null;
512
+ void 0 !== maybeKey && (key = "" + maybeKey);
513
+ void 0 !== config.key && (key = "" + config.key);
514
+ if ("key" in config) {
515
+ maybeKey = {};
516
+ for (var propName in config)
517
+ "key" !== propName && (maybeKey[propName] = config[propName]);
518
+ } else maybeKey = config;
519
+ config = maybeKey.ref;
520
+ return {
521
+ $$typeof: REACT_ELEMENT_TYPE,
522
+ type: type,
523
+ key: key,
524
+ ref: void 0 !== config ? config : null,
525
+ props: maybeKey
526
+ };
527
+ }
528
+ reactJsxRuntime_production.Fragment = REACT_FRAGMENT_TYPE;
529
+ reactJsxRuntime_production.jsx = jsxProd;
530
+ reactJsxRuntime_production.jsxs = jsxProd;
531
+ return reactJsxRuntime_production;
532
+ }
533
+
534
+ var reactJsxRuntime_development = {};
535
+
536
+ /**
537
+ * @license React
538
+ * react-jsx-runtime.development.js
539
+ *
540
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
541
+ *
542
+ * This source code is licensed under the MIT license found in the
543
+ * LICENSE file in the root directory of this source tree.
544
+ */
545
+
546
+ var hasRequiredReactJsxRuntime_development;
547
+
548
+ function requireReactJsxRuntime_development () {
549
+ if (hasRequiredReactJsxRuntime_development) return reactJsxRuntime_development;
550
+ hasRequiredReactJsxRuntime_development = 1;
551
+ "production" !== process.env.NODE_ENV &&
552
+ (function () {
553
+ function getComponentNameFromType(type) {
554
+ if (null == type) return null;
555
+ if ("function" === typeof type)
556
+ return type.$$typeof === REACT_CLIENT_REFERENCE
557
+ ? null
558
+ : type.displayName || type.name || null;
559
+ if ("string" === typeof type) return type;
560
+ switch (type) {
561
+ case REACT_FRAGMENT_TYPE:
562
+ return "Fragment";
563
+ case REACT_PROFILER_TYPE:
564
+ return "Profiler";
565
+ case REACT_STRICT_MODE_TYPE:
566
+ return "StrictMode";
567
+ case REACT_SUSPENSE_TYPE:
568
+ return "Suspense";
569
+ case REACT_SUSPENSE_LIST_TYPE:
570
+ return "SuspenseList";
571
+ case REACT_ACTIVITY_TYPE:
572
+ return "Activity";
573
+ }
574
+ if ("object" === typeof type)
575
+ switch (
576
+ ("number" === typeof type.tag &&
577
+ console.error(
578
+ "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
579
+ ),
580
+ type.$$typeof)
581
+ ) {
582
+ case REACT_PORTAL_TYPE:
583
+ return "Portal";
584
+ case REACT_CONTEXT_TYPE:
585
+ return type.displayName || "Context";
586
+ case REACT_CONSUMER_TYPE:
587
+ return (type._context.displayName || "Context") + ".Consumer";
588
+ case REACT_FORWARD_REF_TYPE:
589
+ var innerType = type.render;
590
+ type = type.displayName;
591
+ type ||
592
+ ((type = innerType.displayName || innerType.name || ""),
593
+ (type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef"));
594
+ return type;
595
+ case REACT_MEMO_TYPE:
596
+ return (
597
+ (innerType = type.displayName || null),
598
+ null !== innerType
599
+ ? innerType
600
+ : getComponentNameFromType(type.type) || "Memo"
601
+ );
602
+ case REACT_LAZY_TYPE:
603
+ innerType = type._payload;
604
+ type = type._init;
605
+ try {
606
+ return getComponentNameFromType(type(innerType));
607
+ } catch (x) {}
608
+ }
609
+ return null;
610
+ }
611
+ function testStringCoercion(value) {
612
+ return "" + value;
613
+ }
614
+ function checkKeyStringCoercion(value) {
615
+ try {
616
+ testStringCoercion(value);
617
+ var JSCompiler_inline_result = !1;
618
+ } catch (e) {
619
+ JSCompiler_inline_result = true;
620
+ }
621
+ if (JSCompiler_inline_result) {
622
+ JSCompiler_inline_result = console;
623
+ var JSCompiler_temp_const = JSCompiler_inline_result.error;
624
+ var JSCompiler_inline_result$jscomp$0 =
625
+ ("function" === typeof Symbol &&
626
+ Symbol.toStringTag &&
627
+ value[Symbol.toStringTag]) ||
628
+ value.constructor.name ||
629
+ "Object";
630
+ JSCompiler_temp_const.call(
631
+ JSCompiler_inline_result,
632
+ "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
633
+ JSCompiler_inline_result$jscomp$0
634
+ );
635
+ return testStringCoercion(value);
636
+ }
637
+ }
638
+ function getTaskName(type) {
639
+ if (type === REACT_FRAGMENT_TYPE) return "<>";
640
+ if (
641
+ "object" === typeof type &&
642
+ null !== type &&
643
+ type.$$typeof === REACT_LAZY_TYPE
644
+ )
645
+ return "<...>";
646
+ try {
647
+ var name = getComponentNameFromType(type);
648
+ return name ? "<" + name + ">" : "<...>";
649
+ } catch (x) {
650
+ return "<...>";
651
+ }
652
+ }
653
+ function getOwner() {
654
+ var dispatcher = ReactSharedInternals.A;
655
+ return null === dispatcher ? null : dispatcher.getOwner();
656
+ }
657
+ function UnknownOwner() {
658
+ return Error("react-stack-top-frame");
659
+ }
660
+ function hasValidKey(config) {
661
+ if (hasOwnProperty.call(config, "key")) {
662
+ var getter = Object.getOwnPropertyDescriptor(config, "key").get;
663
+ if (getter && getter.isReactWarning) return false;
664
+ }
665
+ return void 0 !== config.key;
666
+ }
667
+ function defineKeyPropWarningGetter(props, displayName) {
668
+ function warnAboutAccessingKey() {
669
+ specialPropKeyWarningShown ||
670
+ ((specialPropKeyWarningShown = true),
671
+ console.error(
672
+ "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
673
+ displayName
674
+ ));
675
+ }
676
+ warnAboutAccessingKey.isReactWarning = true;
677
+ Object.defineProperty(props, "key", {
678
+ get: warnAboutAccessingKey,
679
+ configurable: true
680
+ });
681
+ }
682
+ function elementRefGetterWithDeprecationWarning() {
683
+ var componentName = getComponentNameFromType(this.type);
684
+ didWarnAboutElementRef[componentName] ||
685
+ ((didWarnAboutElementRef[componentName] = true),
686
+ console.error(
687
+ "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
688
+ ));
689
+ componentName = this.props.ref;
690
+ return void 0 !== componentName ? componentName : null;
691
+ }
692
+ function ReactElement(type, key, props, owner, debugStack, debugTask) {
693
+ var refProp = props.ref;
694
+ type = {
695
+ $$typeof: REACT_ELEMENT_TYPE,
696
+ type: type,
697
+ key: key,
698
+ props: props,
699
+ _owner: owner
700
+ };
701
+ null !== (void 0 !== refProp ? refProp : null)
702
+ ? Object.defineProperty(type, "ref", {
703
+ enumerable: false,
704
+ get: elementRefGetterWithDeprecationWarning
705
+ })
706
+ : Object.defineProperty(type, "ref", { enumerable: false, value: null });
707
+ type._store = {};
708
+ Object.defineProperty(type._store, "validated", {
709
+ configurable: false,
710
+ enumerable: false,
711
+ writable: true,
712
+ value: 0
713
+ });
714
+ Object.defineProperty(type, "_debugInfo", {
715
+ configurable: false,
716
+ enumerable: false,
717
+ writable: true,
718
+ value: null
719
+ });
720
+ Object.defineProperty(type, "_debugStack", {
721
+ configurable: false,
722
+ enumerable: false,
723
+ writable: true,
724
+ value: debugStack
725
+ });
726
+ Object.defineProperty(type, "_debugTask", {
727
+ configurable: false,
728
+ enumerable: false,
729
+ writable: true,
730
+ value: debugTask
731
+ });
732
+ Object.freeze && (Object.freeze(type.props), Object.freeze(type));
733
+ return type;
734
+ }
735
+ function jsxDEVImpl(
736
+ type,
737
+ config,
738
+ maybeKey,
739
+ isStaticChildren,
740
+ debugStack,
741
+ debugTask
742
+ ) {
743
+ var children = config.children;
744
+ if (void 0 !== children)
745
+ if (isStaticChildren)
746
+ if (isArrayImpl(children)) {
747
+ for (
748
+ isStaticChildren = 0;
749
+ isStaticChildren < children.length;
750
+ isStaticChildren++
751
+ )
752
+ validateChildKeys(children[isStaticChildren]);
753
+ Object.freeze && Object.freeze(children);
754
+ } else
755
+ console.error(
756
+ "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
757
+ );
758
+ else validateChildKeys(children);
759
+ if (hasOwnProperty.call(config, "key")) {
760
+ children = getComponentNameFromType(type);
761
+ var keys = Object.keys(config).filter(function (k) {
762
+ return "key" !== k;
763
+ });
764
+ isStaticChildren =
765
+ 0 < keys.length
766
+ ? "{key: someKey, " + keys.join(": ..., ") + ": ...}"
767
+ : "{key: someKey}";
768
+ didWarnAboutKeySpread[children + isStaticChildren] ||
769
+ ((keys =
770
+ 0 < keys.length ? "{" + keys.join(": ..., ") + ": ...}" : "{}"),
771
+ console.error(
772
+ 'A props object containing a "key" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />',
773
+ isStaticChildren,
774
+ children,
775
+ keys,
776
+ children
777
+ ),
778
+ (didWarnAboutKeySpread[children + isStaticChildren] = true));
779
+ }
780
+ children = null;
781
+ void 0 !== maybeKey &&
782
+ (checkKeyStringCoercion(maybeKey), (children = "" + maybeKey));
783
+ hasValidKey(config) &&
784
+ (checkKeyStringCoercion(config.key), (children = "" + config.key));
785
+ if ("key" in config) {
786
+ maybeKey = {};
787
+ for (var propName in config)
788
+ "key" !== propName && (maybeKey[propName] = config[propName]);
789
+ } else maybeKey = config;
790
+ children &&
791
+ defineKeyPropWarningGetter(
792
+ maybeKey,
793
+ "function" === typeof type
794
+ ? type.displayName || type.name || "Unknown"
795
+ : type
796
+ );
797
+ return ReactElement(
798
+ type,
799
+ children,
800
+ maybeKey,
801
+ getOwner(),
802
+ debugStack,
803
+ debugTask
804
+ );
805
+ }
806
+ function validateChildKeys(node) {
807
+ isValidElement(node)
808
+ ? node._store && (node._store.validated = 1)
809
+ : "object" === typeof node &&
810
+ null !== node &&
811
+ node.$$typeof === REACT_LAZY_TYPE &&
812
+ ("fulfilled" === node._payload.status
813
+ ? isValidElement(node._payload.value) &&
814
+ node._payload.value._store &&
815
+ (node._payload.value._store.validated = 1)
816
+ : node._store && (node._store.validated = 1));
817
+ }
818
+ function isValidElement(object) {
819
+ return (
820
+ "object" === typeof object &&
821
+ null !== object &&
822
+ object.$$typeof === REACT_ELEMENT_TYPE
823
+ );
824
+ }
825
+ var React = require$$0,
826
+ REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
827
+ REACT_PORTAL_TYPE = Symbol.for("react.portal"),
828
+ REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"),
829
+ REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"),
830
+ REACT_PROFILER_TYPE = Symbol.for("react.profiler"),
831
+ REACT_CONSUMER_TYPE = Symbol.for("react.consumer"),
832
+ REACT_CONTEXT_TYPE = Symbol.for("react.context"),
833
+ REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"),
834
+ REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"),
835
+ REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"),
836
+ REACT_MEMO_TYPE = Symbol.for("react.memo"),
837
+ REACT_LAZY_TYPE = Symbol.for("react.lazy"),
838
+ REACT_ACTIVITY_TYPE = Symbol.for("react.activity"),
839
+ REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"),
840
+ ReactSharedInternals =
841
+ React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
842
+ hasOwnProperty = Object.prototype.hasOwnProperty,
843
+ isArrayImpl = Array.isArray,
844
+ createTask = console.createTask
845
+ ? console.createTask
846
+ : function () {
847
+ return null;
848
+ };
849
+ React = {
850
+ react_stack_bottom_frame: function (callStackForError) {
851
+ return callStackForError();
852
+ }
853
+ };
854
+ var specialPropKeyWarningShown;
855
+ var didWarnAboutElementRef = {};
856
+ var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(
857
+ React,
858
+ UnknownOwner
859
+ )();
860
+ var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
861
+ var didWarnAboutKeySpread = {};
862
+ reactJsxRuntime_development.Fragment = REACT_FRAGMENT_TYPE;
863
+ reactJsxRuntime_development.jsx = function (type, config, maybeKey) {
864
+ var trackActualOwner =
865
+ 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
866
+ return jsxDEVImpl(
867
+ type,
868
+ config,
869
+ maybeKey,
870
+ false,
871
+ trackActualOwner
872
+ ? Error("react-stack-top-frame")
873
+ : unknownOwnerDebugStack,
874
+ trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
875
+ );
876
+ };
877
+ reactJsxRuntime_development.jsxs = function (type, config, maybeKey) {
878
+ var trackActualOwner =
879
+ 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
880
+ return jsxDEVImpl(
881
+ type,
882
+ config,
883
+ maybeKey,
884
+ true,
885
+ trackActualOwner
886
+ ? Error("react-stack-top-frame")
887
+ : unknownOwnerDebugStack,
888
+ trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
889
+ );
890
+ };
891
+ })();
892
+ return reactJsxRuntime_development;
893
+ }
894
+
895
+ if (process.env.NODE_ENV === 'production') {
896
+ jsxRuntime.exports = requireReactJsxRuntime_production();
897
+ } else {
898
+ jsxRuntime.exports = requireReactJsxRuntime_development();
899
+ }
900
+
901
+ var jsxRuntimeExports = jsxRuntime.exports;
902
+
903
+ function useTourEngine(config) {
904
+ const actions = useMemo(() => new TourActions(), []);
905
+ const engine = useMemo(() => {
906
+ const tourEngine = new TourEngine(config);
907
+ return tourEngine;
908
+ }, [config]);
909
+ const [state, setState] = useState(engine.getState());
910
+ useEffect(() => {
911
+ const unsubscribe = engine.subscribe(setState);
912
+ return unsubscribe;
913
+ }, [engine]);
914
+ const start = useCallback(async () => {
915
+ try {
916
+ await engine.start();
917
+ }
918
+ catch (error) {
919
+ console.error('Error in useTourEngine.start():', error);
920
+ }
921
+ }, [engine]);
922
+ const stop = useCallback(async () => {
923
+ await engine.stop();
924
+ }, [engine]);
925
+ const next = useCallback(async () => {
926
+ const currentStep = engine.getCurrentStep();
927
+ if (currentStep?.action) {
928
+ // Execute the step action first
929
+ await actions.execute(currentStep.action);
930
+ }
931
+ await engine.next();
932
+ }, [engine, actions]);
933
+ const previous = useCallback(async () => {
934
+ await engine.previous();
935
+ }, [engine]);
936
+ const skip = useCallback(async () => {
937
+ await engine.skip();
938
+ }, [engine]);
939
+ const goToStep = useCallback(async (index) => {
940
+ await engine.goToStep(index);
941
+ }, [engine]);
942
+ return {
943
+ state,
944
+ start,
945
+ stop,
946
+ next,
947
+ previous,
948
+ skip,
949
+ goToStep,
950
+ isFirstStep: engine.isFirstStep(),
951
+ isLastStep: engine.isLastStep(),
952
+ canGoNext: engine.canGoNext(),
953
+ canGoPrevious: engine.canGoPrevious(),
954
+ currentStep: engine.getCurrentStep(),
955
+ engine,
956
+ actions,
957
+ };
958
+ }
959
+
960
+ const TourContext = createContext(null);
961
+ const defaultTheme = {
962
+ primaryColor: '#3b82f6',
963
+ backgroundColor: '#ffffff',
964
+ textColor: '#1f2937',
965
+ borderRadius: '12px',
966
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
967
+ fontSize: '14px',
968
+ zIndex: 9999,
969
+ overlay: {
970
+ backgroundColor: '#000000',
971
+ opacity: 0.5,
972
+ },
973
+ highlight: {
974
+ borderColor: '#3b82f6',
975
+ borderWidth: '4px',
976
+ glowColor: 'rgba(59, 130, 246, 0.3)',
977
+ animation: 'tour-highlight-pulse 2s infinite',
978
+ },
979
+ popover: {
980
+ backgroundColor: '#ffffff',
981
+ borderColor: '#e5e7eb',
982
+ shadow: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
983
+ maxWidth: '384px',
984
+ },
985
+ };
986
+ function TourProvider({ config, children }) {
987
+ const tourEngine = useTourEngine(config);
988
+ const theme = { ...defaultTheme, ...config.theme };
989
+ const contextValue = {
990
+ ...tourEngine,
991
+ config,
992
+ theme,
993
+ };
994
+ return (jsxRuntimeExports.jsx(TourContext.Provider, { value: contextValue, children: children }));
995
+ }
996
+ function useTour() {
997
+ const context = useContext(TourContext);
998
+ if (!context) {
999
+ throw new Error('useTour must be used within a TourProvider');
1000
+ }
1001
+ return context;
1002
+ }
1003
+
1004
+ function getElementPosition(element) {
1005
+ const rect = element.getBoundingClientRect();
1006
+ const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
1007
+ const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
1008
+ return {
1009
+ top: rect.top + scrollTop,
1010
+ left: rect.left + scrollLeft,
1011
+ width: rect.width,
1012
+ height: rect.height,
1013
+ right: rect.right + scrollLeft,
1014
+ bottom: rect.bottom + scrollTop,
1015
+ };
1016
+ }
1017
+ function calculatePopoverPosition(targetElement, popoverElement, preferredPlacement = 'top') {
1018
+ const targetPos = getElementPosition(targetElement);
1019
+ const popoverRect = popoverElement.getBoundingClientRect();
1020
+ const viewport = {
1021
+ width: window.innerWidth,
1022
+ height: window.innerHeight,
1023
+ scrollTop: window.pageYOffset || document.documentElement.scrollTop,
1024
+ scrollLeft: window.pageXOffset || document.documentElement.scrollLeft,
1025
+ };
1026
+ const spacing = 12; // Gap between target and popover
1027
+ const positions = {
1028
+ top: {
1029
+ top: targetPos.top - popoverRect.height - spacing,
1030
+ left: targetPos.left + (targetPos.width - popoverRect.width) / 2,
1031
+ placement: 'top',
1032
+ },
1033
+ bottom: {
1034
+ top: targetPos.bottom + spacing,
1035
+ left: targetPos.left + (targetPos.width - popoverRect.width) / 2,
1036
+ placement: 'bottom',
1037
+ },
1038
+ left: {
1039
+ top: targetPos.top + (targetPos.height - popoverRect.height) / 2,
1040
+ left: targetPos.left - popoverRect.width - spacing,
1041
+ placement: 'left',
1042
+ },
1043
+ right: {
1044
+ top: targetPos.top + (targetPos.height - popoverRect.height) / 2,
1045
+ left: targetPos.right + spacing,
1046
+ placement: 'right',
1047
+ },
1048
+ center: {
1049
+ top: viewport.scrollTop + (viewport.height - popoverRect.height) / 2,
1050
+ left: viewport.scrollLeft + (viewport.width - popoverRect.width) / 2,
1051
+ placement: 'center',
1052
+ },
1053
+ };
1054
+ // Check if preferred placement fits in viewport
1055
+ const preferred = positions[preferredPlacement];
1056
+ if (isPositionInViewport(preferred, popoverRect, viewport)) {
1057
+ return preferred;
1058
+ }
1059
+ // Try other placements in order of preference
1060
+ const fallbackOrder = ['bottom', 'top', 'right', 'left', 'center'];
1061
+ for (const placement of fallbackOrder) {
1062
+ if (placement === preferredPlacement)
1063
+ continue;
1064
+ const position = positions[placement];
1065
+ if (isPositionInViewport(position, popoverRect, viewport)) {
1066
+ return position;
1067
+ }
1068
+ }
1069
+ // If nothing fits, use center as fallback
1070
+ return positions.center;
1071
+ }
1072
+ function isPositionInViewport(position, popoverRect, viewport) {
1073
+ const margin = 16; // Minimum margin from viewport edges
1074
+ return (position.left >= viewport.scrollLeft + margin &&
1075
+ position.left + popoverRect.width <= viewport.scrollLeft + viewport.width - margin &&
1076
+ position.top >= viewport.scrollTop + margin &&
1077
+ position.top + popoverRect.height <= viewport.scrollTop + viewport.height - margin);
1078
+ }
1079
+ function scrollToElement(element, behavior = 'smooth') {
1080
+ element.scrollIntoView({
1081
+ behavior,
1082
+ block: 'center',
1083
+ inline: 'center',
1084
+ });
1085
+ }
1086
+ function isElementInViewport(element) {
1087
+ const rect = element.getBoundingClientRect();
1088
+ return (rect.top >= 0 &&
1089
+ rect.left >= 0 &&
1090
+ rect.bottom <= window.innerHeight &&
1091
+ rect.right <= window.innerWidth);
1092
+ }
1093
+ function getViewportCenter() {
1094
+ return {
1095
+ x: window.innerWidth / 2,
1096
+ y: window.innerHeight / 2,
1097
+ };
1098
+ }
1099
+
1100
+ function useTourHighlight(step) {
1101
+ const [targetElement, setTargetElement] = useState(null);
1102
+ const [highlightStyle, setHighlightStyle] = useState({});
1103
+ const [isVisible, setIsVisible] = useState(false);
1104
+ const observerRef = useRef(null);
1105
+ useEffect(() => {
1106
+ if (!step?.target) {
1107
+ setTargetElement(null);
1108
+ setIsVisible(false);
1109
+ return;
1110
+ }
1111
+ const findAndHighlightElement = () => {
1112
+ const element = step.highlight?.element ||
1113
+ document.querySelector(step.target);
1114
+ if (element) {
1115
+ setTargetElement(element);
1116
+ updateHighlightStyle(element, step.highlight);
1117
+ setIsVisible(true);
1118
+ // Scroll to element if not in viewport
1119
+ if (!isElementInViewport(element)) {
1120
+ scrollToElement(element);
1121
+ }
1122
+ }
1123
+ else {
1124
+ setTargetElement(null);
1125
+ setIsVisible(false);
1126
+ }
1127
+ };
1128
+ // Initial attempt to find element
1129
+ findAndHighlightElement();
1130
+ // Set up mutation observer to watch for DOM changes
1131
+ if (!targetElement && step.waitForElement !== false) {
1132
+ observerRef.current = new MutationObserver(() => {
1133
+ findAndHighlightElement();
1134
+ });
1135
+ observerRef.current.observe(document.body, {
1136
+ childList: true,
1137
+ subtree: true,
1138
+ attributes: true,
1139
+ attributeFilter: ['class', 'id', 'data-tour'],
1140
+ });
1141
+ }
1142
+ return () => {
1143
+ if (observerRef.current) {
1144
+ observerRef.current.disconnect();
1145
+ observerRef.current = null;
1146
+ }
1147
+ };
1148
+ }, [step?.target, step?.highlight, step?.waitForElement, targetElement]);
1149
+ // Update highlight position when element moves (e.g., during animations)
1150
+ useEffect(() => {
1151
+ if (!targetElement || !isVisible)
1152
+ return;
1153
+ const updatePosition = () => {
1154
+ updateHighlightStyle(targetElement, step?.highlight);
1155
+ };
1156
+ const handleScroll = () => updatePosition();
1157
+ const handleResize = () => updatePosition();
1158
+ window.addEventListener('scroll', handleScroll, { passive: true });
1159
+ window.addEventListener('resize', handleResize, { passive: true });
1160
+ // Use ResizeObserver to watch for element size changes
1161
+ let resizeObserver = null;
1162
+ if (window.ResizeObserver) {
1163
+ resizeObserver = new ResizeObserver(updatePosition);
1164
+ resizeObserver.observe(targetElement);
1165
+ }
1166
+ return () => {
1167
+ window.removeEventListener('scroll', handleScroll);
1168
+ window.removeEventListener('resize', handleResize);
1169
+ if (resizeObserver) {
1170
+ resizeObserver.disconnect();
1171
+ }
1172
+ };
1173
+ }, [targetElement, isVisible, step?.highlight]);
1174
+ const updateHighlightStyle = (element, config) => {
1175
+ const position = getElementPosition(element);
1176
+ const padding = config?.padding || 4;
1177
+ const borderRadius = config?.borderRadius || 8;
1178
+ const borderWidth = config?.borderWidth || 4;
1179
+ setHighlightStyle({
1180
+ position: 'absolute',
1181
+ top: position.top - padding,
1182
+ left: position.left - padding,
1183
+ width: position.width + (padding * 2),
1184
+ height: position.height + (padding * 2),
1185
+ border: `${borderWidth}px solid var(--tour-highlight-color, #3b82f6)`,
1186
+ borderRadius: `${borderRadius}px`,
1187
+ boxShadow: config?.animate !== false
1188
+ ? '0 0 0 4px rgba(59, 130, 246, 0.2), 0 0 20px rgba(59, 130, 246, 0.3)'
1189
+ : '0 0 0 4px rgba(59, 130, 246, 0.2)',
1190
+ pointerEvents: 'none',
1191
+ zIndex: 9998,
1192
+ transition: config?.animate !== false
1193
+ ? 'all 0.3s ease-in-out'
1194
+ : 'none',
1195
+ animation: config?.animate !== false
1196
+ ? 'tour-highlight-pulse 2s infinite'
1197
+ : 'none',
1198
+ });
1199
+ };
1200
+ return {
1201
+ targetElement,
1202
+ highlightStyle,
1203
+ isVisible,
1204
+ };
1205
+ }
1206
+
1207
+ function TourOverlay({ className }) {
1208
+ const { state, theme, stop } = useTour();
1209
+ const { targetElement, highlightStyle, isVisible } = useTourHighlight(state.currentStep);
1210
+ if (!state.isRunning || !state.currentStep) {
1211
+ return null;
1212
+ }
1213
+ const overlayStyle = {
1214
+ position: 'fixed',
1215
+ top: 0,
1216
+ left: 0,
1217
+ width: '100%',
1218
+ height: '100%',
1219
+ backgroundColor: theme.overlay?.backgroundColor || '#000000',
1220
+ opacity: theme.overlay?.opacity || 0.5,
1221
+ zIndex: (theme.zIndex || 9999) - 1,
1222
+ pointerEvents: 'auto',
1223
+ };
1224
+ const handleOverlayClick = () => {
1225
+ if (state.currentStep?.canSkip !== false) {
1226
+ stop();
1227
+ }
1228
+ };
1229
+ return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("div", { style: overlayStyle, onClick: handleOverlayClick, className: className, "data-tour-overlay": true }), isVisible && targetElement && (jsxRuntimeExports.jsx("div", { style: highlightStyle, "data-tour-highlight": true })), jsxRuntimeExports.jsx("style", { children: `
1230
+ @keyframes tour-highlight-pulse {
1231
+ 0%, 100% {
1232
+ box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.2), 0 0 20px rgba(59, 130, 246, 0.3);
1233
+ }
1234
+ 50% {
1235
+ box-shadow: 0 0 0 8px rgba(59, 130, 246, 0.3), 0 0 30px rgba(59, 130, 246, 0.5);
1236
+ }
1237
+ }
1238
+
1239
+ @keyframes tour-fade-in {
1240
+ from {
1241
+ opacity: 0;
1242
+ transform: scale(0.95);
1243
+ }
1244
+ to {
1245
+ opacity: 1;
1246
+ transform: scale(1);
1247
+ }
1248
+ }
1249
+
1250
+ [data-tour-overlay] {
1251
+ animation: tour-fade-in 0.2s ease-out;
1252
+ }
1253
+
1254
+ [data-tour-highlight] {
1255
+ animation: tour-fade-in 0.3s ease-out;
1256
+ }
1257
+ ` })] }));
1258
+ }
1259
+
1260
+ function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
1261
+
1262
+ function TourPopover({ className }) {
1263
+ const { state, theme, next, previous, skip, stop, isFirstStep, isLastStep, canGoNext, canGoPrevious } = useTour();
1264
+ const { targetElement } = useTourHighlight(state.currentStep);
1265
+ const popoverRef = useRef(null);
1266
+ const [position, setPosition] = useState({ top: 0, left: 0, placement: 'top' });
1267
+ useEffect(() => {
1268
+ if (!popoverRef.current || !targetElement || !state.currentStep)
1269
+ return;
1270
+ const updatePosition = () => {
1271
+ const newPosition = calculatePopoverPosition(targetElement, popoverRef.current, state.currentStep.placement || 'top');
1272
+ setPosition(newPosition);
1273
+ };
1274
+ updatePosition();
1275
+ const handleResize = () => updatePosition();
1276
+ const handleScroll = () => updatePosition();
1277
+ window.addEventListener('resize', handleResize);
1278
+ window.addEventListener('scroll', handleScroll, { passive: true });
1279
+ return () => {
1280
+ window.removeEventListener('resize', handleResize);
1281
+ window.removeEventListener('scroll', handleScroll);
1282
+ };
1283
+ }, [targetElement, state.currentStep]);
1284
+ if (!state.isRunning || !state.currentStep) {
1285
+ return null;
1286
+ }
1287
+ const step = state.currentStep;
1288
+ const popoverConfig = step.popover || {};
1289
+ const popoverStyle = {
1290
+ position: 'absolute',
1291
+ top: position.top,
1292
+ left: position.left,
1293
+ maxWidth: theme.popover?.maxWidth || '384px',
1294
+ backgroundColor: theme.popover?.backgroundColor || theme.backgroundColor || '#ffffff',
1295
+ borderTopWidth: '1px',
1296
+ borderRightWidth: '1px',
1297
+ borderBottomWidth: '1px',
1298
+ borderLeftWidth: '1px',
1299
+ borderTopStyle: 'solid',
1300
+ borderRightStyle: 'solid',
1301
+ borderBottomStyle: 'solid',
1302
+ borderLeftStyle: 'solid',
1303
+ borderTopColor: theme.popover?.borderColor || '#e5e7eb',
1304
+ borderRightColor: theme.popover?.borderColor || '#e5e7eb',
1305
+ borderBottomColor: theme.popover?.borderColor || '#e5e7eb',
1306
+ borderLeftColor: theme.popover?.borderColor || '#e5e7eb',
1307
+ borderRadius: theme.borderRadius || '12px',
1308
+ boxShadow: theme.popover?.shadow || '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
1309
+ fontFamily: theme.fontFamily || '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
1310
+ fontSize: theme.fontSize || '14px',
1311
+ color: theme.textColor || '#1f2937',
1312
+ zIndex: theme.zIndex || 9999,
1313
+ animation: 'tour-fade-in 0.3s ease-out',
1314
+ };
1315
+ const handleNext = async () => {
1316
+ if (canGoNext || isLastStep) {
1317
+ await next();
1318
+ }
1319
+ };
1320
+ const handlePrevious = async () => {
1321
+ if (canGoPrevious) {
1322
+ await previous();
1323
+ }
1324
+ };
1325
+ const handleSkip = async () => {
1326
+ await skip();
1327
+ };
1328
+ const handleClose = async () => {
1329
+ await stop();
1330
+ };
1331
+ return (jsxRuntimeExports.jsxs("div", { ref: popoverRef, style: {
1332
+ ...popoverStyle,
1333
+ pointerEvents: 'auto',
1334
+ userSelect: 'none',
1335
+ }, className: clsx('tour-popover', className, popoverConfig.className), "data-tour-popover": true, "data-placement": position.placement, onClick: (e) => {
1336
+ e.stopPropagation();
1337
+ }, children: [jsxRuntimeExports.jsxs("div", { style: {
1338
+ display: 'flex',
1339
+ justifyContent: 'space-between',
1340
+ alignItems: 'center',
1341
+ padding: '16px 20px 0 20px'
1342
+ }, children: [jsxRuntimeExports.jsx("button", { onClick: handleClose, style: {
1343
+ background: 'none',
1344
+ borderTopWidth: '0',
1345
+ borderRightWidth: '0',
1346
+ borderBottomWidth: '0',
1347
+ borderLeftWidth: '0',
1348
+ fontSize: '18px',
1349
+ cursor: 'pointer',
1350
+ color: '#6b7280',
1351
+ padding: '4px',
1352
+ borderRadius: '4px',
1353
+ display: 'flex',
1354
+ alignItems: 'center',
1355
+ justifyContent: 'center',
1356
+ width: '24px',
1357
+ height: '24px',
1358
+ }, "aria-label": "Close tour", children: "\u00D7" }), (popoverConfig.showProgress !== false && state.totalSteps > 1) && (jsxRuntimeExports.jsxs("div", { style: {
1359
+ backgroundColor: theme.primaryColor || '#3b82f6',
1360
+ color: 'white',
1361
+ padding: '4px 8px',
1362
+ borderRadius: '12px',
1363
+ fontSize: '12px',
1364
+ fontWeight: '500',
1365
+ }, children: [state.currentStepIndex + 1, " of ", state.totalSteps] }))] }), jsxRuntimeExports.jsxs("div", { style: { padding: '16px 20px' }, children: [(popoverConfig.title || step.title) && (jsxRuntimeExports.jsx("h3", { style: {
1366
+ margin: '0 0 8px 0',
1367
+ fontSize: '16px',
1368
+ fontWeight: '600',
1369
+ color: theme.textColor || '#1f2937',
1370
+ }, children: popoverConfig.title || step.title })), jsxRuntimeExports.jsx("div", { style: {
1371
+ margin: '0 0 16px 0',
1372
+ lineHeight: '1.5',
1373
+ color: theme.textColor || '#374151',
1374
+ }, children: popoverConfig.content || step.content })] }), jsxRuntimeExports.jsxs("div", { style: {
1375
+ display: 'flex',
1376
+ justifyContent: 'space-between',
1377
+ alignItems: 'center',
1378
+ padding: '0 20px 20px 20px',
1379
+ gap: '12px',
1380
+ }, children: [(popoverConfig.showSkip !== false && step.canSkip !== false) && (jsxRuntimeExports.jsx("button", { onClick: (_e) => {
1381
+ handleSkip();
1382
+ }, style: {
1383
+ background: 'none',
1384
+ borderTopWidth: '0',
1385
+ borderRightWidth: '0',
1386
+ borderBottomWidth: '0',
1387
+ borderLeftWidth: '0',
1388
+ color: '#6b7280',
1389
+ cursor: 'pointer',
1390
+ padding: '8px 16px',
1391
+ borderRadius: '8px',
1392
+ fontSize: '14px',
1393
+ fontWeight: '500',
1394
+ transition: 'all 0.2s ease',
1395
+ pointerEvents: 'auto',
1396
+ position: 'relative',
1397
+ zIndex: 99999,
1398
+ }, children: popoverConfig.skipLabel || 'Skip Tour' })), jsxRuntimeExports.jsxs("div", { style: { display: 'flex', gap: '8px', marginLeft: 'auto' }, children: [!isFirstStep && (jsxRuntimeExports.jsx("button", { onClick: handlePrevious, disabled: !canGoPrevious, style: {
1399
+ backgroundColor: 'transparent',
1400
+ borderTopWidth: '1px',
1401
+ borderRightWidth: '1px',
1402
+ borderBottomWidth: '1px',
1403
+ borderLeftWidth: '1px',
1404
+ borderTopStyle: 'solid',
1405
+ borderRightStyle: 'solid',
1406
+ borderBottomStyle: 'solid',
1407
+ borderLeftStyle: 'solid',
1408
+ borderTopColor: theme.primaryColor || '#3b82f6',
1409
+ borderRightColor: theme.primaryColor || '#3b82f6',
1410
+ borderBottomColor: theme.primaryColor || '#3b82f6',
1411
+ borderLeftColor: theme.primaryColor || '#3b82f6',
1412
+ color: theme.primaryColor || '#3b82f6',
1413
+ cursor: canGoPrevious ? 'pointer' : 'not-allowed',
1414
+ padding: '8px 16px',
1415
+ borderRadius: '8px',
1416
+ fontSize: '14px',
1417
+ fontWeight: '500',
1418
+ opacity: canGoPrevious ? 1 : 0.5,
1419
+ transition: 'all 0.2s ease',
1420
+ }, children: "Previous" })), jsxRuntimeExports.jsx("button", { onClick: (e) => {
1421
+ e.preventDefault();
1422
+ e.stopPropagation();
1423
+ handleNext();
1424
+ }, disabled: false, style: {
1425
+ backgroundColor: theme.primaryColor || '#3b82f6',
1426
+ borderTopWidth: '0',
1427
+ borderRightWidth: '0',
1428
+ borderBottomWidth: '0',
1429
+ borderLeftWidth: '0',
1430
+ color: 'white',
1431
+ cursor: 'pointer',
1432
+ padding: '8px 16px',
1433
+ borderRadius: '8px',
1434
+ fontSize: '14px',
1435
+ fontWeight: '500',
1436
+ opacity: 1,
1437
+ transition: 'all 0.2s ease',
1438
+ pointerEvents: 'auto',
1439
+ position: 'relative',
1440
+ zIndex: 99999,
1441
+ }, children: isLastStep
1442
+ ? (popoverConfig.finishLabel || 'Finish')
1443
+ : (popoverConfig.nextLabel || 'Next') })] })] }), position.placement !== 'center' && (jsxRuntimeExports.jsx("div", { style: {
1444
+ position: 'absolute',
1445
+ width: '12px',
1446
+ height: '12px',
1447
+ backgroundColor: theme.popover?.backgroundColor || theme.backgroundColor || '#ffffff',
1448
+ borderTopWidth: '1px',
1449
+ borderRightWidth: '1px',
1450
+ borderBottomWidth: '1px',
1451
+ borderLeftWidth: '1px',
1452
+ borderTopStyle: 'solid',
1453
+ borderRightStyle: 'solid',
1454
+ borderBottomStyle: 'solid',
1455
+ borderLeftStyle: 'solid',
1456
+ borderTopColor: theme.popover?.borderColor || '#e5e7eb',
1457
+ borderRightColor: theme.popover?.borderColor || '#e5e7eb',
1458
+ borderBottomColor: theme.popover?.borderColor || '#e5e7eb',
1459
+ borderLeftColor: theme.popover?.borderColor || '#e5e7eb',
1460
+ transform: 'rotate(45deg)',
1461
+ ...getArrowPosition(position.placement),
1462
+ }, "data-tour-arrow": true }))] }));
1463
+ }
1464
+ function getArrowPosition(placement) {
1465
+ switch (placement) {
1466
+ case 'top':
1467
+ return {
1468
+ bottom: '-6px',
1469
+ left: '50%',
1470
+ marginLeft: '-6px',
1471
+ borderTopWidth: '0',
1472
+ borderLeftWidth: '0',
1473
+ };
1474
+ case 'bottom':
1475
+ return {
1476
+ top: '-6px',
1477
+ left: '50%',
1478
+ marginLeft: '-6px',
1479
+ borderBottomWidth: '0',
1480
+ borderRightWidth: '0',
1481
+ };
1482
+ case 'left':
1483
+ return {
1484
+ right: '-6px',
1485
+ top: '50%',
1486
+ marginTop: '-6px',
1487
+ borderTopWidth: '0',
1488
+ borderLeftWidth: '0',
1489
+ };
1490
+ case 'right':
1491
+ return {
1492
+ left: '-6px',
1493
+ top: '50%',
1494
+ marginTop: '-6px',
1495
+ borderBottomWidth: '0',
1496
+ borderRightWidth: '0',
1497
+ };
1498
+ default:
1499
+ return {};
1500
+ }
1501
+ }
1502
+
1503
+ function TourRunner({ className }) {
1504
+ const { state } = useTour();
1505
+ if (!state.isRunning) {
1506
+ return null;
1507
+ }
1508
+ return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(TourOverlay, { className: className }), jsxRuntimeExports.jsx(TourPopover, { className: className })] }));
1509
+ }
1510
+
1511
+ class TabIntegration {
1512
+ constructor() {
1513
+ this.name = 'tab-integration';
1514
+ }
1515
+ canHandle(action) {
1516
+ return action.type === 'tab-switch';
1517
+ }
1518
+ async execute(action, element) {
1519
+ if (!action.target && !element) {
1520
+ throw new Error('Tab integration requires either a target selector or element');
1521
+ }
1522
+ const targetElement = element || document.querySelector(action.target);
1523
+ if (!targetElement) {
1524
+ throw new Error(`Tab element not found: ${action.target}`);
1525
+ }
1526
+ // Handle different tab implementations
1527
+ const tabValue = typeof action.value === 'string' ? action.value : undefined;
1528
+ await this.handleTabClick(targetElement, tabValue);
1529
+ }
1530
+ async handleTabClick(tabElement, tabValue) {
1531
+ // Check for common tab patterns
1532
+ // 1. Radix UI Tabs
1533
+ if (this.isRadixTab(tabElement)) {
1534
+ await this.handleRadixTab(tabElement);
1535
+ return;
1536
+ }
1537
+ // 2. Material UI Tabs
1538
+ if (this.isMaterialUITab(tabElement)) {
1539
+ await this.handleMaterialUITab(tabElement);
1540
+ return;
1541
+ }
1542
+ // 3. React Router tabs (links)
1543
+ if (this.isRouterTab(tabElement)) {
1544
+ await this.handleRouterTab(tabElement);
1545
+ return;
1546
+ }
1547
+ // 4. Custom tabs with data attributes
1548
+ if (this.isCustomTab(tabElement)) {
1549
+ await this.handleCustomTab(tabElement, tabValue);
1550
+ return;
1551
+ }
1552
+ // 5. Generic button/clickable tab
1553
+ await this.handleGenericTab(tabElement);
1554
+ }
1555
+ isRadixTab(element) {
1556
+ return element.hasAttribute('data-radix-collection-item') ||
1557
+ element.getAttribute('role') === 'tab' ||
1558
+ element.closest('[data-radix-tabs-root]') !== null;
1559
+ }
1560
+ async handleRadixTab(element) {
1561
+ // Radix tabs use standard click events
1562
+ element.click();
1563
+ await this.waitForTabChange();
1564
+ }
1565
+ isMaterialUITab(element) {
1566
+ return element.classList.contains('MuiTab-root') ||
1567
+ element.closest('.MuiTabs-root') !== null;
1568
+ }
1569
+ async handleMaterialUITab(element) {
1570
+ // Material UI tabs use click events
1571
+ element.click();
1572
+ await this.waitForTabChange();
1573
+ }
1574
+ isRouterTab(element) {
1575
+ return element.tagName === 'A' ||
1576
+ element.hasAttribute('href') ||
1577
+ element.closest('a[href]') !== null;
1578
+ }
1579
+ async handleRouterTab(element) {
1580
+ const linkElement = element.tagName === 'A' ? element : element.closest('a');
1581
+ if (linkElement) {
1582
+ linkElement.click();
1583
+ await this.waitForNavigation();
1584
+ }
1585
+ }
1586
+ isCustomTab(element) {
1587
+ return element.hasAttribute('data-tab') ||
1588
+ element.hasAttribute('data-tab-id') ||
1589
+ element.hasAttribute('data-value');
1590
+ }
1591
+ async handleCustomTab(element, tabValue) {
1592
+ // Try to find and activate the correct tab
1593
+ if (tabValue) {
1594
+ const tabContainer = element.closest('[role="tablist"]') ||
1595
+ element.closest('.tabs') ||
1596
+ element.parentElement;
1597
+ if (tabContainer) {
1598
+ const targetTab = tabContainer.querySelector(`[data-tab="${tabValue}"], [data-tab-id="${tabValue}"], [data-value="${tabValue}"]`);
1599
+ if (targetTab) {
1600
+ targetTab.click();
1601
+ await this.waitForTabChange();
1602
+ return;
1603
+ }
1604
+ }
1605
+ }
1606
+ // Fallback to clicking the provided element
1607
+ element.click();
1608
+ await this.waitForTabChange();
1609
+ }
1610
+ async handleGenericTab(element) {
1611
+ // Generic click handling
1612
+ element.click();
1613
+ await this.waitForTabChange();
1614
+ }
1615
+ async waitForTabChange() {
1616
+ // Wait for tab content to change
1617
+ return new Promise(resolve => {
1618
+ setTimeout(resolve, 300); // Allow time for tab transition
1619
+ });
1620
+ }
1621
+ async waitForNavigation() {
1622
+ // Wait for potential page navigation
1623
+ return new Promise(resolve => {
1624
+ setTimeout(resolve, 500); // Allow time for navigation
1625
+ });
1626
+ }
1627
+ }
1628
+
1629
+ class WizardIntegration {
1630
+ constructor() {
1631
+ this.name = 'wizard-integration';
1632
+ }
1633
+ canHandle(action) {
1634
+ return action.type === 'wizard-step';
1635
+ }
1636
+ async execute(action, element) {
1637
+ if (!action.target && !element) {
1638
+ throw new Error('Wizard integration requires either a target selector or element');
1639
+ }
1640
+ const targetElement = element || document.querySelector(action.target);
1641
+ if (!targetElement) {
1642
+ throw new Error(`Wizard element not found: ${action.target}`);
1643
+ }
1644
+ const stepValue = typeof action.value === 'string' || typeof action.value === 'number' ? action.value : undefined;
1645
+ await this.handleWizardNavigation(targetElement, stepValue);
1646
+ }
1647
+ async handleWizardNavigation(element, stepValue) {
1648
+ // Handle different wizard patterns
1649
+ // 1. Multi-step form wizards
1650
+ if (this.isFormWizard(element)) {
1651
+ await this.handleFormWizard(element, stepValue);
1652
+ return;
1653
+ }
1654
+ // 2. Stepper components (Material UI, Ant Design, etc.)
1655
+ if (this.isStepper(element)) {
1656
+ await this.handleStepper(element, stepValue);
1657
+ return;
1658
+ }
1659
+ // 3. Custom wizard with data attributes
1660
+ if (this.isCustomWizard(element)) {
1661
+ await this.handleCustomWizard(element, stepValue);
1662
+ return;
1663
+ }
1664
+ // 4. Generic next/previous buttons
1665
+ await this.handleGenericWizard(element);
1666
+ }
1667
+ isFormWizard(element) {
1668
+ return element.closest('form') !== null ||
1669
+ element.closest('.wizard') !== null ||
1670
+ element.closest('.multi-step') !== null;
1671
+ }
1672
+ async handleFormWizard(element, stepValue) {
1673
+ if (typeof stepValue === 'number') {
1674
+ // Navigate to specific step
1675
+ await this.navigateToStep(element, stepValue);
1676
+ }
1677
+ else if (this.isNextButton(element)) {
1678
+ // Click next button
1679
+ element.click();
1680
+ await this.waitForStepTransition();
1681
+ }
1682
+ else if (this.isPreviousButton(element)) {
1683
+ // Click previous button
1684
+ element.click();
1685
+ await this.waitForStepTransition();
1686
+ }
1687
+ else {
1688
+ // Generic click
1689
+ element.click();
1690
+ await this.waitForStepTransition();
1691
+ }
1692
+ }
1693
+ isStepper(element) {
1694
+ return element.classList.contains('MuiStepper-root') ||
1695
+ element.classList.contains('ant-steps') ||
1696
+ element.closest('.stepper') !== null ||
1697
+ element.closest('[role="progressbar"]') !== null;
1698
+ }
1699
+ async handleStepper(element, stepValue) {
1700
+ if (typeof stepValue === 'number') {
1701
+ // Find and click specific step
1702
+ const stepElement = this.findStepByIndex(element, stepValue);
1703
+ if (stepElement) {
1704
+ stepElement.click();
1705
+ await this.waitForStepTransition();
1706
+ return;
1707
+ }
1708
+ }
1709
+ // Click the provided element
1710
+ element.click();
1711
+ await this.waitForStepTransition();
1712
+ }
1713
+ isCustomWizard(element) {
1714
+ return element.hasAttribute('data-wizard-step') ||
1715
+ element.hasAttribute('data-step') ||
1716
+ element.closest('[data-wizard]') !== null;
1717
+ }
1718
+ async handleCustomWizard(element, stepValue) {
1719
+ const wizard = element.closest('[data-wizard]');
1720
+ if (stepValue && wizard) {
1721
+ // Try to find specific step
1722
+ const stepElement = wizard.querySelector(`[data-step="${stepValue}"], [data-wizard-step="${stepValue}"]`);
1723
+ if (stepElement) {
1724
+ stepElement.click();
1725
+ await this.waitForStepTransition();
1726
+ return;
1727
+ }
1728
+ }
1729
+ // Click the provided element
1730
+ element.click();
1731
+ await this.waitForStepTransition();
1732
+ }
1733
+ async handleGenericWizard(element) {
1734
+ element.click();
1735
+ await this.waitForStepTransition();
1736
+ }
1737
+ isNextButton(element) {
1738
+ const text = element.textContent?.toLowerCase() || '';
1739
+ return text.includes('next') ||
1740
+ text.includes('continue') ||
1741
+ text.includes('proceed') ||
1742
+ element.classList.contains('next') ||
1743
+ element.hasAttribute('data-next');
1744
+ }
1745
+ isPreviousButton(element) {
1746
+ const text = element.textContent?.toLowerCase() || '';
1747
+ return text.includes('previous') ||
1748
+ text.includes('back') ||
1749
+ element.classList.contains('previous') ||
1750
+ element.classList.contains('back') ||
1751
+ element.hasAttribute('data-previous');
1752
+ }
1753
+ async navigateToStep(container, stepIndex) {
1754
+ // Try different methods to navigate to a specific step
1755
+ // Method 1: Find step by index in stepper
1756
+ const stepElement = this.findStepByIndex(container, stepIndex);
1757
+ if (stepElement) {
1758
+ stepElement.click();
1759
+ await this.waitForStepTransition();
1760
+ return;
1761
+ }
1762
+ // Method 2: Use next/previous buttons to reach target step
1763
+ const currentStep = this.getCurrentStepIndex(container);
1764
+ if (currentStep !== null) {
1765
+ const diff = stepIndex - currentStep;
1766
+ if (diff > 0) {
1767
+ // Go forward
1768
+ for (let i = 0; i < diff; i++) {
1769
+ const nextButton = this.findNextButton(container);
1770
+ if (nextButton) {
1771
+ nextButton.click();
1772
+ await this.waitForStepTransition();
1773
+ }
1774
+ }
1775
+ }
1776
+ else if (diff < 0) {
1777
+ // Go backward
1778
+ for (let i = 0; i < Math.abs(diff); i++) {
1779
+ const prevButton = this.findPreviousButton(container);
1780
+ if (prevButton) {
1781
+ prevButton.click();
1782
+ await this.waitForStepTransition();
1783
+ }
1784
+ }
1785
+ }
1786
+ }
1787
+ }
1788
+ findStepByIndex(container, index) {
1789
+ // Try different selectors for step elements
1790
+ const selectors = [
1791
+ `.step:nth-child(${index + 1})`,
1792
+ `[data-step="${index}"]`,
1793
+ `[data-wizard-step="${index}"]`,
1794
+ `.MuiStep-root:nth-child(${index + 1})`,
1795
+ `.ant-steps-item:nth-child(${index + 1})`,
1796
+ ];
1797
+ for (const selector of selectors) {
1798
+ const element = container.querySelector(selector);
1799
+ if (element)
1800
+ return element;
1801
+ }
1802
+ return null;
1803
+ }
1804
+ getCurrentStepIndex(container) {
1805
+ // Try to determine current step index
1806
+ const activeStep = container.querySelector('.active, .current, .MuiStep-active, .ant-steps-item-active');
1807
+ if (activeStep) {
1808
+ const steps = container.querySelectorAll('.step, .MuiStep-root, .ant-steps-item');
1809
+ return Array.from(steps).indexOf(activeStep);
1810
+ }
1811
+ return null;
1812
+ }
1813
+ findNextButton(container) {
1814
+ const selectors = [
1815
+ 'button[data-next]',
1816
+ '.next-button',
1817
+ 'button:contains("Next")',
1818
+ 'button:contains("Continue")',
1819
+ '.wizard-next',
1820
+ ];
1821
+ for (const selector of selectors) {
1822
+ const element = container.querySelector(selector);
1823
+ if (element)
1824
+ return element;
1825
+ }
1826
+ // Fallback: find button with "next" text
1827
+ const buttons = container.querySelectorAll('button');
1828
+ for (const button of buttons) {
1829
+ const text = button.textContent?.toLowerCase() || '';
1830
+ if (text.includes('next') || text.includes('continue')) {
1831
+ return button;
1832
+ }
1833
+ }
1834
+ return null;
1835
+ }
1836
+ findPreviousButton(container) {
1837
+ const selectors = [
1838
+ 'button[data-previous]',
1839
+ '.previous-button',
1840
+ '.back-button',
1841
+ 'button:contains("Previous")',
1842
+ 'button:contains("Back")',
1843
+ '.wizard-previous',
1844
+ ];
1845
+ for (const selector of selectors) {
1846
+ const element = container.querySelector(selector);
1847
+ if (element)
1848
+ return element;
1849
+ }
1850
+ // Fallback: find button with "previous" or "back" text
1851
+ const buttons = container.querySelectorAll('button');
1852
+ for (const button of buttons) {
1853
+ const text = button.textContent?.toLowerCase() || '';
1854
+ if (text.includes('previous') || text.includes('back')) {
1855
+ return button;
1856
+ }
1857
+ }
1858
+ return null;
1859
+ }
1860
+ async waitForStepTransition() {
1861
+ // Wait for step transition animation/content change
1862
+ return new Promise(resolve => {
1863
+ setTimeout(resolve, 400); // Allow time for transition
1864
+ });
1865
+ }
1866
+ }
1867
+
1868
+ class NavigationIntegration {
1869
+ constructor() {
1870
+ this.name = 'navigation-integration';
1871
+ }
1872
+ canHandle(action) {
1873
+ return action.type === 'navigate';
1874
+ }
1875
+ async execute(action, _element) {
1876
+ if (!action.target) {
1877
+ throw new Error('Navigation integration requires a target URL or path');
1878
+ }
1879
+ const options = typeof action.value === 'object' && action.value !== null ? action.value : undefined;
1880
+ await this.handleNavigation(action.target, options);
1881
+ }
1882
+ async handleNavigation(target, options) {
1883
+ // Handle different navigation patterns
1884
+ // 1. Hash navigation (same page)
1885
+ if (target.startsWith('#')) {
1886
+ await this.handleHashNavigation(target);
1887
+ return;
1888
+ }
1889
+ // 2. Relative path navigation
1890
+ if (target.startsWith('/')) {
1891
+ await this.handlePathNavigation(target, options);
1892
+ return;
1893
+ }
1894
+ // 3. Query parameter navigation
1895
+ if (target.includes('?') || target.includes('&')) {
1896
+ await this.handleQueryNavigation(target, options);
1897
+ return;
1898
+ }
1899
+ // 4. Full URL navigation
1900
+ if (target.startsWith('http')) {
1901
+ await this.handleUrlNavigation(target, options);
1902
+ return;
1903
+ }
1904
+ // 5. Router navigation (for SPAs)
1905
+ await this.handleRouterNavigation(target, options);
1906
+ }
1907
+ async handleHashNavigation(hash) {
1908
+ // Update hash without page reload
1909
+ window.location.hash = hash;
1910
+ // Wait for potential scroll or content change
1911
+ await this.waitForNavigation(200);
1912
+ // Try to scroll to element if it exists
1913
+ const targetElement = document.querySelector(hash);
1914
+ if (targetElement) {
1915
+ targetElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
1916
+ }
1917
+ }
1918
+ async handlePathNavigation(path, options) {
1919
+ // Check if we're in a SPA with router
1920
+ if (this.isSPA()) {
1921
+ await this.handleSPANavigation(path, options);
1922
+ }
1923
+ else {
1924
+ // Traditional navigation
1925
+ if (options?.replace) {
1926
+ window.location.replace(path);
1927
+ }
1928
+ else {
1929
+ window.location.href = path;
1930
+ }
1931
+ }
1932
+ }
1933
+ async handleQueryNavigation(target, options) {
1934
+ const url = new URL(window.location.href);
1935
+ // Parse query parameters from target
1936
+ if (target.startsWith('?')) {
1937
+ // Replace entire query string
1938
+ url.search = target;
1939
+ }
1940
+ else if (target.startsWith('&')) {
1941
+ // Append to existing query string
1942
+ url.search += target;
1943
+ }
1944
+ else {
1945
+ // Parse key=value pairs
1946
+ const params = new URLSearchParams(target);
1947
+ params.forEach((value, key) => {
1948
+ url.searchParams.set(key, value);
1949
+ });
1950
+ }
1951
+ // Update URL
1952
+ if (options?.replace) {
1953
+ window.history.replaceState({}, '', url.toString());
1954
+ }
1955
+ else {
1956
+ window.history.pushState({}, '', url.toString());
1957
+ }
1958
+ // Trigger popstate event for SPAs
1959
+ window.dispatchEvent(new PopStateEvent('popstate'));
1960
+ await this.waitForNavigation(300);
1961
+ }
1962
+ async handleUrlNavigation(url, options) {
1963
+ if (options?.newTab) {
1964
+ window.open(url, '_blank');
1965
+ }
1966
+ else if (options?.replace) {
1967
+ window.location.replace(url);
1968
+ }
1969
+ else {
1970
+ window.location.href = url;
1971
+ }
1972
+ }
1973
+ async handleRouterNavigation(path, options) {
1974
+ // Try different router patterns
1975
+ // 1. React Router
1976
+ if (this.hasReactRouter()) {
1977
+ await this.handleReactRouter(path, options);
1978
+ return;
1979
+ }
1980
+ // 2. Vue Router
1981
+ if (this.hasVueRouter()) {
1982
+ await this.handleVueRouter(path, options);
1983
+ return;
1984
+ }
1985
+ // 3. Next.js Router
1986
+ if (this.hasNextRouter()) {
1987
+ await this.handleNextRouter(path, options);
1988
+ return;
1989
+ }
1990
+ // 4. Generic SPA navigation
1991
+ await this.handleSPANavigation(path, options);
1992
+ }
1993
+ async handleSPANavigation(path, options) {
1994
+ // Generic SPA navigation using History API
1995
+ const url = new URL(path, window.location.origin);
1996
+ if (options?.replace) {
1997
+ window.history.replaceState({}, '', url.toString());
1998
+ }
1999
+ else {
2000
+ window.history.pushState({}, '', url.toString());
2001
+ }
2002
+ // Trigger popstate event
2003
+ window.dispatchEvent(new PopStateEvent('popstate'));
2004
+ await this.waitForNavigation(500);
2005
+ }
2006
+ isSPA() {
2007
+ // Detect if we're in a Single Page Application
2008
+ return !!(window.history &&
2009
+ (this.hasReactRouter() || this.hasVueRouter() || this.hasNextRouter() || this.hasGenericSPA()));
2010
+ }
2011
+ hasReactRouter() {
2012
+ // Check for React Router presence
2013
+ return !!(window.__reactRouter ||
2014
+ document.querySelector('[data-reactroot]') ||
2015
+ document.querySelector('#root') ||
2016
+ document.querySelector('#__next'));
2017
+ }
2018
+ hasVueRouter() {
2019
+ // Check for Vue Router presence
2020
+ return !!(window.Vue ||
2021
+ document.querySelector('[data-v-]') ||
2022
+ document.querySelector('#app'));
2023
+ }
2024
+ hasNextRouter() {
2025
+ // Check for Next.js presence
2026
+ return !!(window.__NEXT_DATA__ ||
2027
+ document.querySelector('#__next'));
2028
+ }
2029
+ hasGenericSPA() {
2030
+ // Check for generic SPA indicators
2031
+ return !!(document.querySelector('[data-spa]') ||
2032
+ document.querySelector('[data-router]') ||
2033
+ window.location.pathname !== '/' && !window.location.pathname.includes('.'));
2034
+ }
2035
+ async detectAndCallRouter(path, options) {
2036
+ const router = window.router || window.__ROUTER__ || null;
2037
+ const method = options?.replace ? 'replace' : 'push';
2038
+ if (router && typeof router === 'object' && router !== null && method in router && typeof router[method] === 'function') {
2039
+ await router[method](path, options);
2040
+ return true;
2041
+ }
2042
+ return false;
2043
+ }
2044
+ async handleReactRouter(path, options) {
2045
+ // Try to use React Router's navigate function if available
2046
+ const navigate = window.__reactRouterNavigate;
2047
+ if (navigate) {
2048
+ await navigate(path, options);
2049
+ }
2050
+ else {
2051
+ // Fallback to history API
2052
+ await this.handleSPANavigation(path, options);
2053
+ }
2054
+ }
2055
+ async handleVueRouter(path, options) {
2056
+ // Try to use Vue Router's push/replace methods
2057
+ const vueRouter = window.router || window.__ROUTER__ || null;
2058
+ if (vueRouter && typeof vueRouter === 'object' && vueRouter !== null) {
2059
+ const router = vueRouter;
2060
+ if (options?.replace && typeof router.replace === 'function') {
2061
+ await router.replace(path);
2062
+ }
2063
+ else if (typeof router.push === 'function') {
2064
+ await router.push(path);
2065
+ }
2066
+ }
2067
+ else {
2068
+ // Fallback to history API
2069
+ await this.handleSPANavigation(path, options);
2070
+ }
2071
+ }
2072
+ async handleNextRouter(path, options) {
2073
+ // Try to use Next.js router
2074
+ const nextRouter = window.__nextRouter;
2075
+ if (nextRouter && typeof nextRouter === 'object' && nextRouter !== null) {
2076
+ const router = nextRouter;
2077
+ if (options?.replace && typeof router.replace === 'function') {
2078
+ await router.replace(path);
2079
+ }
2080
+ else if (typeof router.push === 'function') {
2081
+ await router.push(path);
2082
+ }
2083
+ }
2084
+ else {
2085
+ // Fallback to history API
2086
+ await this.handleSPANavigation(path, options);
2087
+ }
2088
+ }
2089
+ async waitForNavigation(delay = 300) {
2090
+ return new Promise(resolve => {
2091
+ setTimeout(resolve, delay);
2092
+ });
2093
+ }
2094
+ }
2095
+
2096
+ export { NavigationIntegration, TabIntegration, TourActions, TourEngine, TourOverlay, TourPopover, TourProvider, TourRunner, TourStorage, WizardIntegration, calculatePopoverPosition, getElementPosition, getViewportCenter, isElementInViewport, scrollToElement, useTour, useTourEngine, useTourHighlight };
2097
+ //# sourceMappingURL=index.esm.js.map