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