@eventop/sdk 1.1.3 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/index.cjs +214 -195
- package/dist/react/index.js +213 -197
- package/package.json +1 -1
package/dist/react/index.cjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
3
5
|
var react = require('react');
|
|
4
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
7
|
|
|
@@ -26,6 +28,202 @@ function useFeatureScope() {
|
|
|
26
28
|
return react.useContext(EventopFeatureScopeContext); // null is fine — steps can declare feature explicitly
|
|
27
29
|
}
|
|
28
30
|
|
|
31
|
+
function EventopTarget({
|
|
32
|
+
children,
|
|
33
|
+
id,
|
|
34
|
+
name,
|
|
35
|
+
description,
|
|
36
|
+
navigate,
|
|
37
|
+
navigateWaitFor,
|
|
38
|
+
advanceOn,
|
|
39
|
+
waitFor,
|
|
40
|
+
...rest
|
|
41
|
+
}) {
|
|
42
|
+
const registry = useRegistry();
|
|
43
|
+
const ref = react.useRef(null);
|
|
44
|
+
const dataAttr = `data-evtp-${id}`;
|
|
45
|
+
const selector = `[${dataAttr}]`;
|
|
46
|
+
react.useEffect(() => {
|
|
47
|
+
if (!id || !name) {
|
|
48
|
+
console.warn('[Eventop] <EventopTarget> requires id and name props.');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
registry.registerFeature({
|
|
52
|
+
id,
|
|
53
|
+
name,
|
|
54
|
+
description,
|
|
55
|
+
selector,
|
|
56
|
+
navigate,
|
|
57
|
+
navigateWaitFor,
|
|
58
|
+
waitFor,
|
|
59
|
+
advanceOn: advanceOn ? {
|
|
60
|
+
selector,
|
|
61
|
+
...advanceOn
|
|
62
|
+
} : null
|
|
63
|
+
});
|
|
64
|
+
return () => registry.unregisterFeature(id);
|
|
65
|
+
}, [id, name, description]);
|
|
66
|
+
const child = react.Children.only(children);
|
|
67
|
+
let wrapped;
|
|
68
|
+
try {
|
|
69
|
+
wrapped = /*#__PURE__*/react.cloneElement(child, {
|
|
70
|
+
[dataAttr]: '',
|
|
71
|
+
ref: node => {
|
|
72
|
+
ref.current = node;
|
|
73
|
+
const originalRef = child.ref;
|
|
74
|
+
if (typeof originalRef === 'function') originalRef(node);else if (originalRef && 'current' in originalRef) originalRef.current = node;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
} catch {
|
|
78
|
+
wrapped = /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
79
|
+
[dataAttr]: '',
|
|
80
|
+
ref: ref,
|
|
81
|
+
style: {
|
|
82
|
+
display: 'contents'
|
|
83
|
+
},
|
|
84
|
+
children: child
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return /*#__PURE__*/jsxRuntime.jsx(EventopFeatureScopeContext.Provider, {
|
|
88
|
+
value: id,
|
|
89
|
+
children: wrapped
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function EventopStep({
|
|
94
|
+
children,
|
|
95
|
+
feature,
|
|
96
|
+
index,
|
|
97
|
+
parentStep,
|
|
98
|
+
waitFor,
|
|
99
|
+
advanceOn
|
|
100
|
+
}) {
|
|
101
|
+
const registry = useRegistry();
|
|
102
|
+
const featureScope = useFeatureScope();
|
|
103
|
+
const featureId = feature || featureScope;
|
|
104
|
+
const ref = react.useRef(null);
|
|
105
|
+
if (!featureId) {
|
|
106
|
+
console.warn('[Eventop] <EventopStep> needs either a feature prop or an <EventopTarget> ancestor.');
|
|
107
|
+
}
|
|
108
|
+
if (index == null) {
|
|
109
|
+
console.warn('[Eventop] <EventopStep> requires an index prop.');
|
|
110
|
+
}
|
|
111
|
+
const dataAttr = `data-evtp-step-${featureId}-${parentStep != null ? `${parentStep}-` : ''}${index}`;
|
|
112
|
+
const selector = `[${dataAttr}]`;
|
|
113
|
+
react.useEffect(() => {
|
|
114
|
+
if (!featureId || index == null) return;
|
|
115
|
+
registry.registerStep(featureId, index, parentStep ?? null, {
|
|
116
|
+
selector,
|
|
117
|
+
waitFor: waitFor || null,
|
|
118
|
+
advanceOn: advanceOn ? {
|
|
119
|
+
selector,
|
|
120
|
+
...advanceOn
|
|
121
|
+
} : null
|
|
122
|
+
});
|
|
123
|
+
return () => registry.unregisterStep(featureId, index, parentStep ?? null);
|
|
124
|
+
}, [featureId, index, parentStep]);
|
|
125
|
+
const child = react.Children.only(children);
|
|
126
|
+
let wrapped;
|
|
127
|
+
try {
|
|
128
|
+
wrapped = /*#__PURE__*/react.cloneElement(child, {
|
|
129
|
+
[dataAttr]: '',
|
|
130
|
+
ref: node => {
|
|
131
|
+
ref.current = node;
|
|
132
|
+
const originalRef = child.ref;
|
|
133
|
+
if (typeof originalRef === 'function') originalRef(node);else if (originalRef && 'current' in originalRef) originalRef.current = node;
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
} catch {
|
|
137
|
+
wrapped = /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
138
|
+
[dataAttr]: '',
|
|
139
|
+
ref: ref,
|
|
140
|
+
style: {
|
|
141
|
+
display: 'contents'
|
|
142
|
+
},
|
|
143
|
+
children: child
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return wrapped;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
150
|
+
// useEventopAI
|
|
151
|
+
//
|
|
152
|
+
// Access the SDK programmatic API from inside any component.
|
|
153
|
+
// Use for stepComplete(), stepFail(), open(), close() etc.
|
|
154
|
+
//
|
|
155
|
+
// @example
|
|
156
|
+
// function CheckoutForm() {
|
|
157
|
+
// const { stepComplete, stepFail } = useEventopAI();
|
|
158
|
+
//
|
|
159
|
+
// async function handleNext() {
|
|
160
|
+
// const ok = await validateEmail(email);
|
|
161
|
+
// if (ok) stepComplete();
|
|
162
|
+
// else stepFail('Please enter a valid email address.');
|
|
163
|
+
// }
|
|
164
|
+
// }
|
|
165
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
166
|
+
|
|
167
|
+
function useEventopAI() {
|
|
168
|
+
const sdk = () => window.Eventop;
|
|
169
|
+
return {
|
|
170
|
+
open: () => sdk()?.open(),
|
|
171
|
+
close: () => sdk()?.close(),
|
|
172
|
+
cancelTour: () => sdk()?.cancelTour(),
|
|
173
|
+
resumeTour: () => sdk()?.resumeTour(),
|
|
174
|
+
isActive: () => sdk()?.isActive() ?? false,
|
|
175
|
+
isPaused: () => sdk()?.isPaused() ?? false,
|
|
176
|
+
stepComplete: () => sdk()?.stepComplete(),
|
|
177
|
+
stepFail: msg => sdk()?.stepFail(msg),
|
|
178
|
+
runTour: steps => sdk()?.runTour(steps)
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
183
|
+
// useEventopTour
|
|
184
|
+
//
|
|
185
|
+
// Reactively tracks tour state so you can render your own UI.
|
|
186
|
+
// Polls at 300ms — lightweight enough for a status indicator.
|
|
187
|
+
//
|
|
188
|
+
// @example
|
|
189
|
+
// function TourBar() {
|
|
190
|
+
// const { isActive, isPaused, resume, cancel } = useEventopTour();
|
|
191
|
+
// if (!isActive && !isPaused) return null;
|
|
192
|
+
// return (
|
|
193
|
+
// <div>
|
|
194
|
+
// {isPaused && <button onClick={resume}>Resume tour</button>}
|
|
195
|
+
// <button onClick={cancel}>End</button>
|
|
196
|
+
// </div>
|
|
197
|
+
// );
|
|
198
|
+
// }
|
|
199
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
200
|
+
|
|
201
|
+
function useEventopTour() {
|
|
202
|
+
const [state, setState] = react.useState({
|
|
203
|
+
isActive: false,
|
|
204
|
+
isPaused: false
|
|
205
|
+
});
|
|
206
|
+
react.useEffect(() => {
|
|
207
|
+
const id = setInterval(() => {
|
|
208
|
+
const sdk = window.Eventop;
|
|
209
|
+
if (!sdk) return;
|
|
210
|
+
const next = {
|
|
211
|
+
isActive: sdk.isActive(),
|
|
212
|
+
isPaused: sdk.isPaused()
|
|
213
|
+
};
|
|
214
|
+
setState(prev => prev.isActive !== next.isActive || prev.isPaused !== next.isPaused ? next : prev);
|
|
215
|
+
}, 300);
|
|
216
|
+
return () => clearInterval(id);
|
|
217
|
+
}, []);
|
|
218
|
+
return {
|
|
219
|
+
...state,
|
|
220
|
+
resume: react.useCallback(() => window.Eventop?.resumeTour(), []),
|
|
221
|
+
cancel: react.useCallback(() => window.Eventop?.cancelTour(), []),
|
|
222
|
+
open: react.useCallback(() => window.Eventop?.open(), []),
|
|
223
|
+
close: react.useCallback(() => window.Eventop?.close(), [])
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
29
227
|
/**
|
|
30
228
|
* FeatureRegistry
|
|
31
229
|
*
|
|
@@ -244,204 +442,25 @@ function EventopProvider({
|
|
|
244
442
|
});
|
|
245
443
|
}
|
|
246
444
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
react.useEffect(() => {
|
|
263
|
-
if (!id || !name) {
|
|
264
|
-
console.warn('[Eventop] <EventopTarget> requires id and name props.');
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
registry.registerFeature({
|
|
268
|
-
id,
|
|
269
|
-
name,
|
|
270
|
-
description,
|
|
271
|
-
selector,
|
|
272
|
-
navigate,
|
|
273
|
-
navigateWaitFor,
|
|
274
|
-
waitFor,
|
|
275
|
-
advanceOn: advanceOn ? {
|
|
276
|
-
selector,
|
|
277
|
-
...advanceOn
|
|
278
|
-
} : null
|
|
279
|
-
});
|
|
280
|
-
return () => registry.unregisterFeature(id);
|
|
281
|
-
}, [id, name, description]);
|
|
282
|
-
const child = react.Children.only(children);
|
|
283
|
-
let wrapped;
|
|
284
|
-
try {
|
|
285
|
-
wrapped = /*#__PURE__*/react.cloneElement(child, {
|
|
286
|
-
[dataAttr]: '',
|
|
287
|
-
ref: node => {
|
|
288
|
-
ref.current = node;
|
|
289
|
-
const originalRef = child.ref;
|
|
290
|
-
if (typeof originalRef === 'function') originalRef(node);else if (originalRef && 'current' in originalRef) originalRef.current = node;
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
} catch {
|
|
294
|
-
wrapped = /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
295
|
-
[dataAttr]: '',
|
|
296
|
-
ref: ref,
|
|
297
|
-
style: {
|
|
298
|
-
display: 'contents'
|
|
299
|
-
},
|
|
300
|
-
children: child
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
return /*#__PURE__*/jsxRuntime.jsx(EventopFeatureScopeContext.Provider, {
|
|
304
|
-
value: id,
|
|
305
|
-
children: wrapped
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
function EventopStep({
|
|
310
|
-
children,
|
|
311
|
-
feature,
|
|
312
|
-
index,
|
|
313
|
-
parentStep,
|
|
314
|
-
waitFor,
|
|
315
|
-
advanceOn
|
|
316
|
-
}) {
|
|
317
|
-
const registry = useRegistry();
|
|
318
|
-
const featureScope = useFeatureScope();
|
|
319
|
-
const featureId = feature || featureScope;
|
|
320
|
-
const ref = react.useRef(null);
|
|
321
|
-
if (!featureId) {
|
|
322
|
-
console.warn('[Eventop] <EventopStep> needs either a feature prop or an <EventopTarget> ancestor.');
|
|
323
|
-
}
|
|
324
|
-
if (index == null) {
|
|
325
|
-
console.warn('[Eventop] <EventopStep> requires an index prop.');
|
|
326
|
-
}
|
|
327
|
-
const dataAttr = `data-evtp-step-${featureId}-${parentStep != null ? `${parentStep}-` : ''}${index}`;
|
|
328
|
-
const selector = `[${dataAttr}]`;
|
|
329
|
-
react.useEffect(() => {
|
|
330
|
-
if (!featureId || index == null) return;
|
|
331
|
-
registry.registerStep(featureId, index, parentStep ?? null, {
|
|
332
|
-
selector,
|
|
333
|
-
waitFor: waitFor || null,
|
|
334
|
-
advanceOn: advanceOn ? {
|
|
335
|
-
selector,
|
|
336
|
-
...advanceOn
|
|
337
|
-
} : null
|
|
338
|
-
});
|
|
339
|
-
return () => registry.unregisterStep(featureId, index, parentStep ?? null);
|
|
340
|
-
}, [featureId, index, parentStep]);
|
|
341
|
-
const child = react.Children.only(children);
|
|
342
|
-
let wrapped;
|
|
343
|
-
try {
|
|
344
|
-
wrapped = /*#__PURE__*/react.cloneElement(child, {
|
|
345
|
-
[dataAttr]: '',
|
|
346
|
-
ref: node => {
|
|
347
|
-
ref.current = node;
|
|
348
|
-
const originalRef = child.ref;
|
|
349
|
-
if (typeof originalRef === 'function') originalRef(node);else if (originalRef && 'current' in originalRef) originalRef.current = node;
|
|
350
|
-
}
|
|
351
|
-
});
|
|
352
|
-
} catch {
|
|
353
|
-
wrapped = /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
354
|
-
[dataAttr]: '',
|
|
355
|
-
ref: ref,
|
|
356
|
-
style: {
|
|
357
|
-
display: 'contents'
|
|
358
|
-
},
|
|
359
|
-
children: child
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
return wrapped;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
366
|
-
// useEventopAI
|
|
367
|
-
//
|
|
368
|
-
// Access the SDK programmatic API from inside any component.
|
|
369
|
-
// Use for stepComplete(), stepFail(), open(), close() etc.
|
|
370
|
-
//
|
|
371
|
-
// @example
|
|
372
|
-
// function CheckoutForm() {
|
|
373
|
-
// const { stepComplete, stepFail } = useEventopAI();
|
|
374
|
-
//
|
|
375
|
-
// async function handleNext() {
|
|
376
|
-
// const ok = await validateEmail(email);
|
|
377
|
-
// if (ok) stepComplete();
|
|
378
|
-
// else stepFail('Please enter a valid email address.');
|
|
379
|
-
// }
|
|
380
|
-
// }
|
|
381
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
382
|
-
|
|
383
|
-
function useEventopAI() {
|
|
384
|
-
const sdk = () => window.Eventop;
|
|
385
|
-
return {
|
|
386
|
-
open: () => sdk()?.open(),
|
|
387
|
-
close: () => sdk()?.close(),
|
|
388
|
-
cancelTour: () => sdk()?.cancelTour(),
|
|
389
|
-
resumeTour: () => sdk()?.resumeTour(),
|
|
390
|
-
isActive: () => sdk()?.isActive() ?? false,
|
|
391
|
-
isPaused: () => sdk()?.isPaused() ?? false,
|
|
392
|
-
stepComplete: () => sdk()?.stepComplete(),
|
|
393
|
-
stepFail: msg => sdk()?.stepFail(msg),
|
|
394
|
-
runTour: steps => sdk()?.runTour(steps)
|
|
395
|
-
};
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
399
|
-
// useEventopTour
|
|
400
|
-
//
|
|
401
|
-
// Reactively tracks tour state so you can render your own UI.
|
|
402
|
-
// Polls at 300ms — lightweight enough for a status indicator.
|
|
403
|
-
//
|
|
404
|
-
// @example
|
|
405
|
-
// function TourBar() {
|
|
406
|
-
// const { isActive, isPaused, resume, cancel } = useEventopTour();
|
|
407
|
-
// if (!isActive && !isPaused) return null;
|
|
408
|
-
// return (
|
|
409
|
-
// <div>
|
|
410
|
-
// {isPaused && <button onClick={resume}>Resume tour</button>}
|
|
411
|
-
// <button onClick={cancel}>End</button>
|
|
412
|
-
// </div>
|
|
413
|
-
// );
|
|
414
|
-
// }
|
|
415
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
416
|
-
|
|
417
|
-
function useEventopTour() {
|
|
418
|
-
const [state, setState] = react.useState({
|
|
419
|
-
isActive: false,
|
|
420
|
-
isPaused: false
|
|
421
|
-
});
|
|
422
|
-
react.useEffect(() => {
|
|
423
|
-
const id = setInterval(() => {
|
|
424
|
-
const sdk = window.Eventop;
|
|
425
|
-
if (!sdk) return;
|
|
426
|
-
const next = {
|
|
427
|
-
isActive: sdk.isActive(),
|
|
428
|
-
isPaused: sdk.isPaused()
|
|
429
|
-
};
|
|
430
|
-
setState(prev => prev.isActive !== next.isActive || prev.isPaused !== next.isPaused ? next : prev);
|
|
431
|
-
}, 300);
|
|
432
|
-
return () => clearInterval(id);
|
|
433
|
-
}, []);
|
|
434
|
-
return {
|
|
435
|
-
...state,
|
|
436
|
-
resume: react.useCallback(() => window.Eventop?.resumeTour(), []),
|
|
437
|
-
cancel: react.useCallback(() => window.Eventop?.cancelTour(), []),
|
|
438
|
-
open: react.useCallback(() => window.Eventop?.open(), []),
|
|
439
|
-
close: react.useCallback(() => window.Eventop?.close(), [])
|
|
440
|
-
};
|
|
441
|
-
}
|
|
445
|
+
window.EventopAI = {
|
|
446
|
+
init,
|
|
447
|
+
open,
|
|
448
|
+
close,
|
|
449
|
+
cancelTour,
|
|
450
|
+
resumeTour,
|
|
451
|
+
stepComplete,
|
|
452
|
+
stepFail,
|
|
453
|
+
isActive,
|
|
454
|
+
isPaused,
|
|
455
|
+
runTour,
|
|
456
|
+
_updateConfig,
|
|
457
|
+
providers
|
|
458
|
+
};
|
|
459
|
+
var index = window.EventopAI;
|
|
442
460
|
|
|
443
461
|
exports.EventopAIProvider = EventopProvider;
|
|
444
462
|
exports.EventopStep = EventopStep;
|
|
445
463
|
exports.EventopTarget = EventopTarget;
|
|
464
|
+
exports.default = index;
|
|
446
465
|
exports.useEventopAI = useEventopAI;
|
|
447
466
|
exports.useEventopTour = useEventopTour;
|
package/dist/react/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, useContext, useRef,
|
|
1
|
+
import { createContext, useContext, useRef, useEffect, Children, cloneElement, useState, useCallback } from 'react';
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -24,6 +24,202 @@ function useFeatureScope() {
|
|
|
24
24
|
return useContext(EventopFeatureScopeContext); // null is fine — steps can declare feature explicitly
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
function EventopTarget({
|
|
28
|
+
children,
|
|
29
|
+
id,
|
|
30
|
+
name,
|
|
31
|
+
description,
|
|
32
|
+
navigate,
|
|
33
|
+
navigateWaitFor,
|
|
34
|
+
advanceOn,
|
|
35
|
+
waitFor,
|
|
36
|
+
...rest
|
|
37
|
+
}) {
|
|
38
|
+
const registry = useRegistry();
|
|
39
|
+
const ref = useRef(null);
|
|
40
|
+
const dataAttr = `data-evtp-${id}`;
|
|
41
|
+
const selector = `[${dataAttr}]`;
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (!id || !name) {
|
|
44
|
+
console.warn('[Eventop] <EventopTarget> requires id and name props.');
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
registry.registerFeature({
|
|
48
|
+
id,
|
|
49
|
+
name,
|
|
50
|
+
description,
|
|
51
|
+
selector,
|
|
52
|
+
navigate,
|
|
53
|
+
navigateWaitFor,
|
|
54
|
+
waitFor,
|
|
55
|
+
advanceOn: advanceOn ? {
|
|
56
|
+
selector,
|
|
57
|
+
...advanceOn
|
|
58
|
+
} : null
|
|
59
|
+
});
|
|
60
|
+
return () => registry.unregisterFeature(id);
|
|
61
|
+
}, [id, name, description]);
|
|
62
|
+
const child = Children.only(children);
|
|
63
|
+
let wrapped;
|
|
64
|
+
try {
|
|
65
|
+
wrapped = /*#__PURE__*/cloneElement(child, {
|
|
66
|
+
[dataAttr]: '',
|
|
67
|
+
ref: node => {
|
|
68
|
+
ref.current = node;
|
|
69
|
+
const originalRef = child.ref;
|
|
70
|
+
if (typeof originalRef === 'function') originalRef(node);else if (originalRef && 'current' in originalRef) originalRef.current = node;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
} catch {
|
|
74
|
+
wrapped = /*#__PURE__*/jsx("span", {
|
|
75
|
+
[dataAttr]: '',
|
|
76
|
+
ref: ref,
|
|
77
|
+
style: {
|
|
78
|
+
display: 'contents'
|
|
79
|
+
},
|
|
80
|
+
children: child
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return /*#__PURE__*/jsx(EventopFeatureScopeContext.Provider, {
|
|
84
|
+
value: id,
|
|
85
|
+
children: wrapped
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function EventopStep({
|
|
90
|
+
children,
|
|
91
|
+
feature,
|
|
92
|
+
index,
|
|
93
|
+
parentStep,
|
|
94
|
+
waitFor,
|
|
95
|
+
advanceOn
|
|
96
|
+
}) {
|
|
97
|
+
const registry = useRegistry();
|
|
98
|
+
const featureScope = useFeatureScope();
|
|
99
|
+
const featureId = feature || featureScope;
|
|
100
|
+
const ref = useRef(null);
|
|
101
|
+
if (!featureId) {
|
|
102
|
+
console.warn('[Eventop] <EventopStep> needs either a feature prop or an <EventopTarget> ancestor.');
|
|
103
|
+
}
|
|
104
|
+
if (index == null) {
|
|
105
|
+
console.warn('[Eventop] <EventopStep> requires an index prop.');
|
|
106
|
+
}
|
|
107
|
+
const dataAttr = `data-evtp-step-${featureId}-${parentStep != null ? `${parentStep}-` : ''}${index}`;
|
|
108
|
+
const selector = `[${dataAttr}]`;
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
if (!featureId || index == null) return;
|
|
111
|
+
registry.registerStep(featureId, index, parentStep ?? null, {
|
|
112
|
+
selector,
|
|
113
|
+
waitFor: waitFor || null,
|
|
114
|
+
advanceOn: advanceOn ? {
|
|
115
|
+
selector,
|
|
116
|
+
...advanceOn
|
|
117
|
+
} : null
|
|
118
|
+
});
|
|
119
|
+
return () => registry.unregisterStep(featureId, index, parentStep ?? null);
|
|
120
|
+
}, [featureId, index, parentStep]);
|
|
121
|
+
const child = Children.only(children);
|
|
122
|
+
let wrapped;
|
|
123
|
+
try {
|
|
124
|
+
wrapped = /*#__PURE__*/cloneElement(child, {
|
|
125
|
+
[dataAttr]: '',
|
|
126
|
+
ref: node => {
|
|
127
|
+
ref.current = node;
|
|
128
|
+
const originalRef = child.ref;
|
|
129
|
+
if (typeof originalRef === 'function') originalRef(node);else if (originalRef && 'current' in originalRef) originalRef.current = node;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
} catch {
|
|
133
|
+
wrapped = /*#__PURE__*/jsx("span", {
|
|
134
|
+
[dataAttr]: '',
|
|
135
|
+
ref: ref,
|
|
136
|
+
style: {
|
|
137
|
+
display: 'contents'
|
|
138
|
+
},
|
|
139
|
+
children: child
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
return wrapped;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
146
|
+
// useEventopAI
|
|
147
|
+
//
|
|
148
|
+
// Access the SDK programmatic API from inside any component.
|
|
149
|
+
// Use for stepComplete(), stepFail(), open(), close() etc.
|
|
150
|
+
//
|
|
151
|
+
// @example
|
|
152
|
+
// function CheckoutForm() {
|
|
153
|
+
// const { stepComplete, stepFail } = useEventopAI();
|
|
154
|
+
//
|
|
155
|
+
// async function handleNext() {
|
|
156
|
+
// const ok = await validateEmail(email);
|
|
157
|
+
// if (ok) stepComplete();
|
|
158
|
+
// else stepFail('Please enter a valid email address.');
|
|
159
|
+
// }
|
|
160
|
+
// }
|
|
161
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
162
|
+
|
|
163
|
+
function useEventopAI() {
|
|
164
|
+
const sdk = () => window.Eventop;
|
|
165
|
+
return {
|
|
166
|
+
open: () => sdk()?.open(),
|
|
167
|
+
close: () => sdk()?.close(),
|
|
168
|
+
cancelTour: () => sdk()?.cancelTour(),
|
|
169
|
+
resumeTour: () => sdk()?.resumeTour(),
|
|
170
|
+
isActive: () => sdk()?.isActive() ?? false,
|
|
171
|
+
isPaused: () => sdk()?.isPaused() ?? false,
|
|
172
|
+
stepComplete: () => sdk()?.stepComplete(),
|
|
173
|
+
stepFail: msg => sdk()?.stepFail(msg),
|
|
174
|
+
runTour: steps => sdk()?.runTour(steps)
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
179
|
+
// useEventopTour
|
|
180
|
+
//
|
|
181
|
+
// Reactively tracks tour state so you can render your own UI.
|
|
182
|
+
// Polls at 300ms — lightweight enough for a status indicator.
|
|
183
|
+
//
|
|
184
|
+
// @example
|
|
185
|
+
// function TourBar() {
|
|
186
|
+
// const { isActive, isPaused, resume, cancel } = useEventopTour();
|
|
187
|
+
// if (!isActive && !isPaused) return null;
|
|
188
|
+
// return (
|
|
189
|
+
// <div>
|
|
190
|
+
// {isPaused && <button onClick={resume}>Resume tour</button>}
|
|
191
|
+
// <button onClick={cancel}>End</button>
|
|
192
|
+
// </div>
|
|
193
|
+
// );
|
|
194
|
+
// }
|
|
195
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
196
|
+
|
|
197
|
+
function useEventopTour() {
|
|
198
|
+
const [state, setState] = useState({
|
|
199
|
+
isActive: false,
|
|
200
|
+
isPaused: false
|
|
201
|
+
});
|
|
202
|
+
useEffect(() => {
|
|
203
|
+
const id = setInterval(() => {
|
|
204
|
+
const sdk = window.Eventop;
|
|
205
|
+
if (!sdk) return;
|
|
206
|
+
const next = {
|
|
207
|
+
isActive: sdk.isActive(),
|
|
208
|
+
isPaused: sdk.isPaused()
|
|
209
|
+
};
|
|
210
|
+
setState(prev => prev.isActive !== next.isActive || prev.isPaused !== next.isPaused ? next : prev);
|
|
211
|
+
}, 300);
|
|
212
|
+
return () => clearInterval(id);
|
|
213
|
+
}, []);
|
|
214
|
+
return {
|
|
215
|
+
...state,
|
|
216
|
+
resume: useCallback(() => window.Eventop?.resumeTour(), []),
|
|
217
|
+
cancel: useCallback(() => window.Eventop?.cancelTour(), []),
|
|
218
|
+
open: useCallback(() => window.Eventop?.open(), []),
|
|
219
|
+
close: useCallback(() => window.Eventop?.close(), [])
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
27
223
|
/**
|
|
28
224
|
* FeatureRegistry
|
|
29
225
|
*
|
|
@@ -242,200 +438,20 @@ function EventopProvider({
|
|
|
242
438
|
});
|
|
243
439
|
}
|
|
244
440
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
useEffect(() => {
|
|
261
|
-
if (!id || !name) {
|
|
262
|
-
console.warn('[Eventop] <EventopTarget> requires id and name props.');
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
registry.registerFeature({
|
|
266
|
-
id,
|
|
267
|
-
name,
|
|
268
|
-
description,
|
|
269
|
-
selector,
|
|
270
|
-
navigate,
|
|
271
|
-
navigateWaitFor,
|
|
272
|
-
waitFor,
|
|
273
|
-
advanceOn: advanceOn ? {
|
|
274
|
-
selector,
|
|
275
|
-
...advanceOn
|
|
276
|
-
} : null
|
|
277
|
-
});
|
|
278
|
-
return () => registry.unregisterFeature(id);
|
|
279
|
-
}, [id, name, description]);
|
|
280
|
-
const child = Children.only(children);
|
|
281
|
-
let wrapped;
|
|
282
|
-
try {
|
|
283
|
-
wrapped = /*#__PURE__*/cloneElement(child, {
|
|
284
|
-
[dataAttr]: '',
|
|
285
|
-
ref: node => {
|
|
286
|
-
ref.current = node;
|
|
287
|
-
const originalRef = child.ref;
|
|
288
|
-
if (typeof originalRef === 'function') originalRef(node);else if (originalRef && 'current' in originalRef) originalRef.current = node;
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
} catch {
|
|
292
|
-
wrapped = /*#__PURE__*/jsx("span", {
|
|
293
|
-
[dataAttr]: '',
|
|
294
|
-
ref: ref,
|
|
295
|
-
style: {
|
|
296
|
-
display: 'contents'
|
|
297
|
-
},
|
|
298
|
-
children: child
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
return /*#__PURE__*/jsx(EventopFeatureScopeContext.Provider, {
|
|
302
|
-
value: id,
|
|
303
|
-
children: wrapped
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
function EventopStep({
|
|
308
|
-
children,
|
|
309
|
-
feature,
|
|
310
|
-
index,
|
|
311
|
-
parentStep,
|
|
312
|
-
waitFor,
|
|
313
|
-
advanceOn
|
|
314
|
-
}) {
|
|
315
|
-
const registry = useRegistry();
|
|
316
|
-
const featureScope = useFeatureScope();
|
|
317
|
-
const featureId = feature || featureScope;
|
|
318
|
-
const ref = useRef(null);
|
|
319
|
-
if (!featureId) {
|
|
320
|
-
console.warn('[Eventop] <EventopStep> needs either a feature prop or an <EventopTarget> ancestor.');
|
|
321
|
-
}
|
|
322
|
-
if (index == null) {
|
|
323
|
-
console.warn('[Eventop] <EventopStep> requires an index prop.');
|
|
324
|
-
}
|
|
325
|
-
const dataAttr = `data-evtp-step-${featureId}-${parentStep != null ? `${parentStep}-` : ''}${index}`;
|
|
326
|
-
const selector = `[${dataAttr}]`;
|
|
327
|
-
useEffect(() => {
|
|
328
|
-
if (!featureId || index == null) return;
|
|
329
|
-
registry.registerStep(featureId, index, parentStep ?? null, {
|
|
330
|
-
selector,
|
|
331
|
-
waitFor: waitFor || null,
|
|
332
|
-
advanceOn: advanceOn ? {
|
|
333
|
-
selector,
|
|
334
|
-
...advanceOn
|
|
335
|
-
} : null
|
|
336
|
-
});
|
|
337
|
-
return () => registry.unregisterStep(featureId, index, parentStep ?? null);
|
|
338
|
-
}, [featureId, index, parentStep]);
|
|
339
|
-
const child = Children.only(children);
|
|
340
|
-
let wrapped;
|
|
341
|
-
try {
|
|
342
|
-
wrapped = /*#__PURE__*/cloneElement(child, {
|
|
343
|
-
[dataAttr]: '',
|
|
344
|
-
ref: node => {
|
|
345
|
-
ref.current = node;
|
|
346
|
-
const originalRef = child.ref;
|
|
347
|
-
if (typeof originalRef === 'function') originalRef(node);else if (originalRef && 'current' in originalRef) originalRef.current = node;
|
|
348
|
-
}
|
|
349
|
-
});
|
|
350
|
-
} catch {
|
|
351
|
-
wrapped = /*#__PURE__*/jsx("span", {
|
|
352
|
-
[dataAttr]: '',
|
|
353
|
-
ref: ref,
|
|
354
|
-
style: {
|
|
355
|
-
display: 'contents'
|
|
356
|
-
},
|
|
357
|
-
children: child
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
|
-
return wrapped;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
364
|
-
// useEventopAI
|
|
365
|
-
//
|
|
366
|
-
// Access the SDK programmatic API from inside any component.
|
|
367
|
-
// Use for stepComplete(), stepFail(), open(), close() etc.
|
|
368
|
-
//
|
|
369
|
-
// @example
|
|
370
|
-
// function CheckoutForm() {
|
|
371
|
-
// const { stepComplete, stepFail } = useEventopAI();
|
|
372
|
-
//
|
|
373
|
-
// async function handleNext() {
|
|
374
|
-
// const ok = await validateEmail(email);
|
|
375
|
-
// if (ok) stepComplete();
|
|
376
|
-
// else stepFail('Please enter a valid email address.');
|
|
377
|
-
// }
|
|
378
|
-
// }
|
|
379
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
380
|
-
|
|
381
|
-
function useEventopAI() {
|
|
382
|
-
const sdk = () => window.Eventop;
|
|
383
|
-
return {
|
|
384
|
-
open: () => sdk()?.open(),
|
|
385
|
-
close: () => sdk()?.close(),
|
|
386
|
-
cancelTour: () => sdk()?.cancelTour(),
|
|
387
|
-
resumeTour: () => sdk()?.resumeTour(),
|
|
388
|
-
isActive: () => sdk()?.isActive() ?? false,
|
|
389
|
-
isPaused: () => sdk()?.isPaused() ?? false,
|
|
390
|
-
stepComplete: () => sdk()?.stepComplete(),
|
|
391
|
-
stepFail: msg => sdk()?.stepFail(msg),
|
|
392
|
-
runTour: steps => sdk()?.runTour(steps)
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
397
|
-
// useEventopTour
|
|
398
|
-
//
|
|
399
|
-
// Reactively tracks tour state so you can render your own UI.
|
|
400
|
-
// Polls at 300ms — lightweight enough for a status indicator.
|
|
401
|
-
//
|
|
402
|
-
// @example
|
|
403
|
-
// function TourBar() {
|
|
404
|
-
// const { isActive, isPaused, resume, cancel } = useEventopTour();
|
|
405
|
-
// if (!isActive && !isPaused) return null;
|
|
406
|
-
// return (
|
|
407
|
-
// <div>
|
|
408
|
-
// {isPaused && <button onClick={resume}>Resume tour</button>}
|
|
409
|
-
// <button onClick={cancel}>End</button>
|
|
410
|
-
// </div>
|
|
411
|
-
// );
|
|
412
|
-
// }
|
|
413
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
414
|
-
|
|
415
|
-
function useEventopTour() {
|
|
416
|
-
const [state, setState] = useState({
|
|
417
|
-
isActive: false,
|
|
418
|
-
isPaused: false
|
|
419
|
-
});
|
|
420
|
-
useEffect(() => {
|
|
421
|
-
const id = setInterval(() => {
|
|
422
|
-
const sdk = window.Eventop;
|
|
423
|
-
if (!sdk) return;
|
|
424
|
-
const next = {
|
|
425
|
-
isActive: sdk.isActive(),
|
|
426
|
-
isPaused: sdk.isPaused()
|
|
427
|
-
};
|
|
428
|
-
setState(prev => prev.isActive !== next.isActive || prev.isPaused !== next.isPaused ? next : prev);
|
|
429
|
-
}, 300);
|
|
430
|
-
return () => clearInterval(id);
|
|
431
|
-
}, []);
|
|
432
|
-
return {
|
|
433
|
-
...state,
|
|
434
|
-
resume: useCallback(() => window.Eventop?.resumeTour(), []),
|
|
435
|
-
cancel: useCallback(() => window.Eventop?.cancelTour(), []),
|
|
436
|
-
open: useCallback(() => window.Eventop?.open(), []),
|
|
437
|
-
close: useCallback(() => window.Eventop?.close(), [])
|
|
438
|
-
};
|
|
439
|
-
}
|
|
441
|
+
window.EventopAI = {
|
|
442
|
+
init,
|
|
443
|
+
open,
|
|
444
|
+
close,
|
|
445
|
+
cancelTour,
|
|
446
|
+
resumeTour,
|
|
447
|
+
stepComplete,
|
|
448
|
+
stepFail,
|
|
449
|
+
isActive,
|
|
450
|
+
isPaused,
|
|
451
|
+
runTour,
|
|
452
|
+
_updateConfig,
|
|
453
|
+
providers
|
|
454
|
+
};
|
|
455
|
+
var index = window.EventopAI;
|
|
440
456
|
|
|
441
|
-
export { EventopProvider as EventopAIProvider, EventopStep, EventopTarget, useEventopAI, useEventopTour };
|
|
457
|
+
export { EventopProvider as EventopAIProvider, EventopStep, EventopTarget, index as default, useEventopAI, useEventopTour };
|