@eventop/sdk 1.2.12 → 1.2.14
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/core.cjs +31 -12
- package/dist/core.js +31 -12
- package/dist/index.cjs +51 -51
- package/dist/index.js +52 -52
- package/dist/react/core.cjs +31 -12
- package/dist/react/core.js +31 -12
- package/dist/react/index.cjs +51 -51
- package/dist/react/index.js +52 -52
- package/package.json +1 -1
package/dist/core.cjs
CHANGED
|
@@ -486,7 +486,13 @@ function buildSystemPrompt(config) {
|
|
|
486
486
|
var _f$screen;
|
|
487
487
|
return (_f$screen = f.screen) === null || _f$screen === void 0 ? void 0 : _f$screen.id;
|
|
488
488
|
}).map(f => f.screen.id))];
|
|
489
|
-
|
|
489
|
+
|
|
490
|
+
// Split features into live (current page) and ghost (other pages).
|
|
491
|
+
// This lets the AI understand what's immediately available vs reachable
|
|
492
|
+
// via navigation, and craft the right message when something isn't found.
|
|
493
|
+
const liveFeatures = (config.features || []).filter(f => !f._ghost);
|
|
494
|
+
const ghostFeatures = (config.features || []).filter(f => f._ghost);
|
|
495
|
+
const summarise = f => {
|
|
490
496
|
var _f$screen2, _f$flow;
|
|
491
497
|
const entry = {
|
|
492
498
|
id: f.id,
|
|
@@ -501,15 +507,18 @@ function buildSystemPrompt(config) {
|
|
|
501
507
|
entry.note = `This feature has ${f.flow.length} sequential sub-steps. Include ONE step per flow entry.`;
|
|
502
508
|
}
|
|
503
509
|
return entry;
|
|
504
|
-
}
|
|
510
|
+
};
|
|
511
|
+
const liveSection = liveFeatures.length ? `CURRENT PAGE FEATURES (user is here now):\n${JSON.stringify(liveFeatures.map(summarise), null, 2)}` : `CURRENT PAGE FEATURES: none registered yet.`;
|
|
512
|
+
const ghostSection = ghostFeatures.length ? `OTHER PAGE FEATURES (reachable via navigation — SDK handles it automatically):\n${JSON.stringify(ghostFeatures.map(summarise), null, 2)}` : '';
|
|
505
513
|
return `
|
|
506
514
|
You are an in-app assistant called "${config.assistantName || 'AI Guide'}" for "${config.appName}".
|
|
507
515
|
Your ONLY job: guide users step-by-step through tasks using the feature map below.
|
|
508
516
|
|
|
509
|
-
${screens.length > 1 ? `SCREENS: This app has multiple screens: ${screens.join(', ')}.
|
|
517
|
+
${screens.length > 1 ? `SCREENS: This app has multiple screens: ${screens.join(', ')}. The SDK navigates automatically — just pick the right feature id.` : ''}
|
|
518
|
+
|
|
519
|
+
${liveSection}
|
|
510
520
|
|
|
511
|
-
|
|
512
|
-
${JSON.stringify(featureSummary, null, 2)}
|
|
521
|
+
${ghostSection}
|
|
513
522
|
|
|
514
523
|
RESPOND ONLY with this exact JSON — no markdown, no extra text:
|
|
515
524
|
{
|
|
@@ -526,16 +535,26 @@ RESPOND ONLY with this exact JSON — no markdown, no extra text:
|
|
|
526
535
|
}
|
|
527
536
|
|
|
528
537
|
RULES:
|
|
529
|
-
1. The step "id" MUST match a feature id from the
|
|
538
|
+
1. The step "id" MUST match a feature id from the current page or other page features above.
|
|
530
539
|
2. Only use selectors and IDs from the feature map. Never invent them.
|
|
531
|
-
3.
|
|
532
|
-
4.
|
|
533
|
-
5.
|
|
534
|
-
6. For forms: ALWAYS include a step for the form section or first input BEFORE the
|
|
540
|
+
3. position values: top | bottom | left | right | auto only.
|
|
541
|
+
4. Order steps logically. For multi-step flows, order as the user encounters them.
|
|
542
|
+
5. For forms: ALWAYS include a step for the form section or first input BEFORE the
|
|
535
543
|
continue/submit button. The button step must always be LAST in its section.
|
|
536
|
-
|
|
544
|
+
6. If a feature has a flow, include one step per flow entry using the same feature id —
|
|
537
545
|
the SDK expands them automatically.
|
|
538
|
-
|
|
546
|
+
7. Never skip features in a required sequence. Include every step end-to-end.
|
|
547
|
+
|
|
548
|
+
WHEN THE USER'S REQUEST DOESN'T MATCH ANY FEATURE:
|
|
549
|
+
- If it partially matches something (e.g. they said "create template" and there's a
|
|
550
|
+
"template-gallery" feature): guide them to the closest matching feature and explain
|
|
551
|
+
what it does. Don't say you can't help.
|
|
552
|
+
- If it matches a feature on another page (ghost): include that feature's steps normally.
|
|
553
|
+
The SDK will navigate there automatically. Do NOT tell the user to navigate manually.
|
|
554
|
+
- If there is genuinely no match anywhere in the feature map: set steps to [] and say
|
|
555
|
+
something like "That doesn't seem to be a feature in ${config.appName} yet. Here's
|
|
556
|
+
what I can help you with:" then list 2-3 relevant features from the map by name.
|
|
557
|
+
Never say you "can only guide through available features" — always offer alternatives.
|
|
539
558
|
`.trim();
|
|
540
559
|
}
|
|
541
560
|
|
package/dist/core.js
CHANGED
|
@@ -484,7 +484,13 @@ function buildSystemPrompt(config) {
|
|
|
484
484
|
var _f$screen;
|
|
485
485
|
return (_f$screen = f.screen) === null || _f$screen === void 0 ? void 0 : _f$screen.id;
|
|
486
486
|
}).map(f => f.screen.id))];
|
|
487
|
-
|
|
487
|
+
|
|
488
|
+
// Split features into live (current page) and ghost (other pages).
|
|
489
|
+
// This lets the AI understand what's immediately available vs reachable
|
|
490
|
+
// via navigation, and craft the right message when something isn't found.
|
|
491
|
+
const liveFeatures = (config.features || []).filter(f => !f._ghost);
|
|
492
|
+
const ghostFeatures = (config.features || []).filter(f => f._ghost);
|
|
493
|
+
const summarise = f => {
|
|
488
494
|
var _f$screen2, _f$flow;
|
|
489
495
|
const entry = {
|
|
490
496
|
id: f.id,
|
|
@@ -499,15 +505,18 @@ function buildSystemPrompt(config) {
|
|
|
499
505
|
entry.note = `This feature has ${f.flow.length} sequential sub-steps. Include ONE step per flow entry.`;
|
|
500
506
|
}
|
|
501
507
|
return entry;
|
|
502
|
-
}
|
|
508
|
+
};
|
|
509
|
+
const liveSection = liveFeatures.length ? `CURRENT PAGE FEATURES (user is here now):\n${JSON.stringify(liveFeatures.map(summarise), null, 2)}` : `CURRENT PAGE FEATURES: none registered yet.`;
|
|
510
|
+
const ghostSection = ghostFeatures.length ? `OTHER PAGE FEATURES (reachable via navigation — SDK handles it automatically):\n${JSON.stringify(ghostFeatures.map(summarise), null, 2)}` : '';
|
|
503
511
|
return `
|
|
504
512
|
You are an in-app assistant called "${config.assistantName || 'AI Guide'}" for "${config.appName}".
|
|
505
513
|
Your ONLY job: guide users step-by-step through tasks using the feature map below.
|
|
506
514
|
|
|
507
|
-
${screens.length > 1 ? `SCREENS: This app has multiple screens: ${screens.join(', ')}.
|
|
515
|
+
${screens.length > 1 ? `SCREENS: This app has multiple screens: ${screens.join(', ')}. The SDK navigates automatically — just pick the right feature id.` : ''}
|
|
516
|
+
|
|
517
|
+
${liveSection}
|
|
508
518
|
|
|
509
|
-
|
|
510
|
-
${JSON.stringify(featureSummary, null, 2)}
|
|
519
|
+
${ghostSection}
|
|
511
520
|
|
|
512
521
|
RESPOND ONLY with this exact JSON — no markdown, no extra text:
|
|
513
522
|
{
|
|
@@ -524,16 +533,26 @@ RESPOND ONLY with this exact JSON — no markdown, no extra text:
|
|
|
524
533
|
}
|
|
525
534
|
|
|
526
535
|
RULES:
|
|
527
|
-
1. The step "id" MUST match a feature id from the
|
|
536
|
+
1. The step "id" MUST match a feature id from the current page or other page features above.
|
|
528
537
|
2. Only use selectors and IDs from the feature map. Never invent them.
|
|
529
|
-
3.
|
|
530
|
-
4.
|
|
531
|
-
5.
|
|
532
|
-
6. For forms: ALWAYS include a step for the form section or first input BEFORE the
|
|
538
|
+
3. position values: top | bottom | left | right | auto only.
|
|
539
|
+
4. Order steps logically. For multi-step flows, order as the user encounters them.
|
|
540
|
+
5. For forms: ALWAYS include a step for the form section or first input BEFORE the
|
|
533
541
|
continue/submit button. The button step must always be LAST in its section.
|
|
534
|
-
|
|
542
|
+
6. If a feature has a flow, include one step per flow entry using the same feature id —
|
|
535
543
|
the SDK expands them automatically.
|
|
536
|
-
|
|
544
|
+
7. Never skip features in a required sequence. Include every step end-to-end.
|
|
545
|
+
|
|
546
|
+
WHEN THE USER'S REQUEST DOESN'T MATCH ANY FEATURE:
|
|
547
|
+
- If it partially matches something (e.g. they said "create template" and there's a
|
|
548
|
+
"template-gallery" feature): guide them to the closest matching feature and explain
|
|
549
|
+
what it does. Don't say you can't help.
|
|
550
|
+
- If it matches a feature on another page (ghost): include that feature's steps normally.
|
|
551
|
+
The SDK will navigate there automatically. Do NOT tell the user to navigate manually.
|
|
552
|
+
- If there is genuinely no match anywhere in the feature map: set steps to [] and say
|
|
553
|
+
something like "That doesn't seem to be a feature in ${config.appName} yet. Here's
|
|
554
|
+
what I can help you with:" then list 2-3 relevant features from the map by name.
|
|
555
|
+
Never say you "can only guide through available features" — always offer alternatives.
|
|
537
556
|
`.trim();
|
|
538
557
|
}
|
|
539
558
|
|
package/dist/index.cjs
CHANGED
|
@@ -315,18 +315,28 @@ function EventopTarget({
|
|
|
315
315
|
navigate,
|
|
316
316
|
navigateWaitFor,
|
|
317
317
|
advanceOn,
|
|
318
|
-
waitFor
|
|
319
|
-
...rest
|
|
318
|
+
waitFor
|
|
320
319
|
}) {
|
|
321
320
|
const registry = useRegistry();
|
|
322
|
-
const
|
|
321
|
+
const wrapperRef = react.useRef(null);
|
|
323
322
|
const dataAttr = `data-evtp-${id}`;
|
|
324
323
|
const selector = `[${dataAttr}]`;
|
|
325
324
|
react.useEffect(() => {
|
|
325
|
+
var _wrapperRef$current;
|
|
326
326
|
if (!id || !name) {
|
|
327
327
|
console.warn('[Eventop] <EventopTarget> requires id and name props.');
|
|
328
328
|
return;
|
|
329
329
|
}
|
|
330
|
+
|
|
331
|
+
// Set the attribute directly on the first real child DOM element.
|
|
332
|
+
// This bypasses React's prop system entirely — works regardless of whether
|
|
333
|
+
// the wrapped component forwards unknown props.
|
|
334
|
+
const firstChild = (_wrapperRef$current = wrapperRef.current) === null || _wrapperRef$current === void 0 ? void 0 : _wrapperRef$current.firstElementChild;
|
|
335
|
+
if (firstChild) {
|
|
336
|
+
firstChild.setAttribute(dataAttr, '');
|
|
337
|
+
} else {
|
|
338
|
+
console.warn(`[Eventop] <EventopTarget id="${id}"> could not find a child DOM element to attach to. ` + `Make sure the wrapped component renders at least one DOM element.`);
|
|
339
|
+
}
|
|
330
340
|
registry.registerFeature({
|
|
331
341
|
id,
|
|
332
342
|
name,
|
|
@@ -341,32 +351,24 @@ function EventopTarget({
|
|
|
341
351
|
...advanceOn
|
|
342
352
|
} : null
|
|
343
353
|
});
|
|
344
|
-
return () =>
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
} catch {
|
|
358
|
-
wrapped = /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
359
|
-
[dataAttr]: '',
|
|
360
|
-
ref: ref,
|
|
354
|
+
return () => {
|
|
355
|
+
var _wrapperRef$current2;
|
|
356
|
+
// Clean up the injected attribute on unmount
|
|
357
|
+
const el = (_wrapperRef$current2 = wrapperRef.current) === null || _wrapperRef$current2 === void 0 ? void 0 : _wrapperRef$current2.firstElementChild;
|
|
358
|
+
if (el) el.removeAttribute(dataAttr);
|
|
359
|
+
registry.unregisterFeature(id);
|
|
360
|
+
};
|
|
361
|
+
}, [id, name, description, route]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
362
|
+
|
|
363
|
+
return /*#__PURE__*/jsxRuntime.jsx(EventopFeatureScopeContext.Provider, {
|
|
364
|
+
value: id,
|
|
365
|
+
children: /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
366
|
+
ref: wrapperRef,
|
|
361
367
|
style: {
|
|
362
368
|
display: 'contents'
|
|
363
369
|
},
|
|
364
|
-
children:
|
|
365
|
-
})
|
|
366
|
-
}
|
|
367
|
-
return /*#__PURE__*/jsxRuntime.jsx(EventopFeatureScopeContext.Provider, {
|
|
368
|
-
value: id,
|
|
369
|
-
children: wrapped
|
|
370
|
+
children: react.Children.only(children)
|
|
371
|
+
})
|
|
370
372
|
});
|
|
371
373
|
}
|
|
372
374
|
|
|
@@ -381,7 +383,7 @@ function EventopStep({
|
|
|
381
383
|
const registry = useRegistry();
|
|
382
384
|
const featureScope = useFeatureScope();
|
|
383
385
|
const featureId = feature || featureScope;
|
|
384
|
-
const
|
|
386
|
+
const wrapperRef = react.useRef(null);
|
|
385
387
|
if (!featureId) {
|
|
386
388
|
console.warn('[Eventop] <EventopStep> needs either a feature prop or an <EventopTarget> ancestor.');
|
|
387
389
|
}
|
|
@@ -391,7 +393,14 @@ function EventopStep({
|
|
|
391
393
|
const dataAttr = `data-evtp-step-${featureId}-${parentStep != null ? `${parentStep}-` : ''}${index}`;
|
|
392
394
|
const selector = `[${dataAttr}]`;
|
|
393
395
|
react.useEffect(() => {
|
|
396
|
+
var _wrapperRef$current;
|
|
394
397
|
if (!featureId || index == null) return;
|
|
398
|
+
|
|
399
|
+
// Inject attribute directly onto the first real child DOM element
|
|
400
|
+
const firstChild = (_wrapperRef$current = wrapperRef.current) === null || _wrapperRef$current === void 0 ? void 0 : _wrapperRef$current.firstElementChild;
|
|
401
|
+
if (firstChild) {
|
|
402
|
+
firstChild.setAttribute(dataAttr, '');
|
|
403
|
+
}
|
|
395
404
|
registry.registerStep(featureId, index, parentStep ?? null, {
|
|
396
405
|
selector,
|
|
397
406
|
waitFor: waitFor || null,
|
|
@@ -400,30 +409,21 @@ function EventopStep({
|
|
|
400
409
|
...advanceOn
|
|
401
410
|
} : null
|
|
402
411
|
});
|
|
403
|
-
return () =>
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
[dataAttr]: '',
|
|
419
|
-
ref: ref,
|
|
420
|
-
style: {
|
|
421
|
-
display: 'contents'
|
|
422
|
-
},
|
|
423
|
-
children: child
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
return wrapped;
|
|
412
|
+
return () => {
|
|
413
|
+
var _wrapperRef$current2;
|
|
414
|
+
const el = (_wrapperRef$current2 = wrapperRef.current) === null || _wrapperRef$current2 === void 0 ? void 0 : _wrapperRef$current2.firstElementChild;
|
|
415
|
+
if (el) el.removeAttribute(dataAttr);
|
|
416
|
+
registry.unregisterStep(featureId, index, parentStep ?? null);
|
|
417
|
+
};
|
|
418
|
+
}, [featureId, index, parentStep]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
419
|
+
|
|
420
|
+
return /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
421
|
+
ref: wrapperRef,
|
|
422
|
+
style: {
|
|
423
|
+
display: 'contents'
|
|
424
|
+
},
|
|
425
|
+
children: react.Children.only(children)
|
|
426
|
+
});
|
|
427
427
|
}
|
|
428
428
|
|
|
429
429
|
// ═══════════════════════════════════════════════════════════════════════════
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, useContext, useRef, useCallback, useEffect, Children,
|
|
1
|
+
import { createContext, useContext, useRef, useCallback, useEffect, Children, useState } from 'react';
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -313,18 +313,28 @@ function EventopTarget({
|
|
|
313
313
|
navigate,
|
|
314
314
|
navigateWaitFor,
|
|
315
315
|
advanceOn,
|
|
316
|
-
waitFor
|
|
317
|
-
...rest
|
|
316
|
+
waitFor
|
|
318
317
|
}) {
|
|
319
318
|
const registry = useRegistry();
|
|
320
|
-
const
|
|
319
|
+
const wrapperRef = useRef(null);
|
|
321
320
|
const dataAttr = `data-evtp-${id}`;
|
|
322
321
|
const selector = `[${dataAttr}]`;
|
|
323
322
|
useEffect(() => {
|
|
323
|
+
var _wrapperRef$current;
|
|
324
324
|
if (!id || !name) {
|
|
325
325
|
console.warn('[Eventop] <EventopTarget> requires id and name props.');
|
|
326
326
|
return;
|
|
327
327
|
}
|
|
328
|
+
|
|
329
|
+
// Set the attribute directly on the first real child DOM element.
|
|
330
|
+
// This bypasses React's prop system entirely — works regardless of whether
|
|
331
|
+
// the wrapped component forwards unknown props.
|
|
332
|
+
const firstChild = (_wrapperRef$current = wrapperRef.current) === null || _wrapperRef$current === void 0 ? void 0 : _wrapperRef$current.firstElementChild;
|
|
333
|
+
if (firstChild) {
|
|
334
|
+
firstChild.setAttribute(dataAttr, '');
|
|
335
|
+
} else {
|
|
336
|
+
console.warn(`[Eventop] <EventopTarget id="${id}"> could not find a child DOM element to attach to. ` + `Make sure the wrapped component renders at least one DOM element.`);
|
|
337
|
+
}
|
|
328
338
|
registry.registerFeature({
|
|
329
339
|
id,
|
|
330
340
|
name,
|
|
@@ -339,32 +349,24 @@ function EventopTarget({
|
|
|
339
349
|
...advanceOn
|
|
340
350
|
} : null
|
|
341
351
|
});
|
|
342
|
-
return () =>
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
} catch {
|
|
356
|
-
wrapped = /*#__PURE__*/jsx("span", {
|
|
357
|
-
[dataAttr]: '',
|
|
358
|
-
ref: ref,
|
|
352
|
+
return () => {
|
|
353
|
+
var _wrapperRef$current2;
|
|
354
|
+
// Clean up the injected attribute on unmount
|
|
355
|
+
const el = (_wrapperRef$current2 = wrapperRef.current) === null || _wrapperRef$current2 === void 0 ? void 0 : _wrapperRef$current2.firstElementChild;
|
|
356
|
+
if (el) el.removeAttribute(dataAttr);
|
|
357
|
+
registry.unregisterFeature(id);
|
|
358
|
+
};
|
|
359
|
+
}, [id, name, description, route]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
360
|
+
|
|
361
|
+
return /*#__PURE__*/jsx(EventopFeatureScopeContext.Provider, {
|
|
362
|
+
value: id,
|
|
363
|
+
children: /*#__PURE__*/jsx("span", {
|
|
364
|
+
ref: wrapperRef,
|
|
359
365
|
style: {
|
|
360
366
|
display: 'contents'
|
|
361
367
|
},
|
|
362
|
-
children:
|
|
363
|
-
})
|
|
364
|
-
}
|
|
365
|
-
return /*#__PURE__*/jsx(EventopFeatureScopeContext.Provider, {
|
|
366
|
-
value: id,
|
|
367
|
-
children: wrapped
|
|
368
|
+
children: Children.only(children)
|
|
369
|
+
})
|
|
368
370
|
});
|
|
369
371
|
}
|
|
370
372
|
|
|
@@ -379,7 +381,7 @@ function EventopStep({
|
|
|
379
381
|
const registry = useRegistry();
|
|
380
382
|
const featureScope = useFeatureScope();
|
|
381
383
|
const featureId = feature || featureScope;
|
|
382
|
-
const
|
|
384
|
+
const wrapperRef = useRef(null);
|
|
383
385
|
if (!featureId) {
|
|
384
386
|
console.warn('[Eventop] <EventopStep> needs either a feature prop or an <EventopTarget> ancestor.');
|
|
385
387
|
}
|
|
@@ -389,7 +391,14 @@ function EventopStep({
|
|
|
389
391
|
const dataAttr = `data-evtp-step-${featureId}-${parentStep != null ? `${parentStep}-` : ''}${index}`;
|
|
390
392
|
const selector = `[${dataAttr}]`;
|
|
391
393
|
useEffect(() => {
|
|
394
|
+
var _wrapperRef$current;
|
|
392
395
|
if (!featureId || index == null) return;
|
|
396
|
+
|
|
397
|
+
// Inject attribute directly onto the first real child DOM element
|
|
398
|
+
const firstChild = (_wrapperRef$current = wrapperRef.current) === null || _wrapperRef$current === void 0 ? void 0 : _wrapperRef$current.firstElementChild;
|
|
399
|
+
if (firstChild) {
|
|
400
|
+
firstChild.setAttribute(dataAttr, '');
|
|
401
|
+
}
|
|
393
402
|
registry.registerStep(featureId, index, parentStep ?? null, {
|
|
394
403
|
selector,
|
|
395
404
|
waitFor: waitFor || null,
|
|
@@ -398,30 +407,21 @@ function EventopStep({
|
|
|
398
407
|
...advanceOn
|
|
399
408
|
} : null
|
|
400
409
|
});
|
|
401
|
-
return () =>
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
[dataAttr]: '',
|
|
417
|
-
ref: ref,
|
|
418
|
-
style: {
|
|
419
|
-
display: 'contents'
|
|
420
|
-
},
|
|
421
|
-
children: child
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
return wrapped;
|
|
410
|
+
return () => {
|
|
411
|
+
var _wrapperRef$current2;
|
|
412
|
+
const el = (_wrapperRef$current2 = wrapperRef.current) === null || _wrapperRef$current2 === void 0 ? void 0 : _wrapperRef$current2.firstElementChild;
|
|
413
|
+
if (el) el.removeAttribute(dataAttr);
|
|
414
|
+
registry.unregisterStep(featureId, index, parentStep ?? null);
|
|
415
|
+
};
|
|
416
|
+
}, [featureId, index, parentStep]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
417
|
+
|
|
418
|
+
return /*#__PURE__*/jsx("span", {
|
|
419
|
+
ref: wrapperRef,
|
|
420
|
+
style: {
|
|
421
|
+
display: 'contents'
|
|
422
|
+
},
|
|
423
|
+
children: Children.only(children)
|
|
424
|
+
});
|
|
425
425
|
}
|
|
426
426
|
|
|
427
427
|
// ═══════════════════════════════════════════════════════════════════════════
|
package/dist/react/core.cjs
CHANGED
|
@@ -486,7 +486,13 @@ function buildSystemPrompt(config) {
|
|
|
486
486
|
var _f$screen;
|
|
487
487
|
return (_f$screen = f.screen) === null || _f$screen === void 0 ? void 0 : _f$screen.id;
|
|
488
488
|
}).map(f => f.screen.id))];
|
|
489
|
-
|
|
489
|
+
|
|
490
|
+
// Split features into live (current page) and ghost (other pages).
|
|
491
|
+
// This lets the AI understand what's immediately available vs reachable
|
|
492
|
+
// via navigation, and craft the right message when something isn't found.
|
|
493
|
+
const liveFeatures = (config.features || []).filter(f => !f._ghost);
|
|
494
|
+
const ghostFeatures = (config.features || []).filter(f => f._ghost);
|
|
495
|
+
const summarise = f => {
|
|
490
496
|
var _f$screen2, _f$flow;
|
|
491
497
|
const entry = {
|
|
492
498
|
id: f.id,
|
|
@@ -501,15 +507,18 @@ function buildSystemPrompt(config) {
|
|
|
501
507
|
entry.note = `This feature has ${f.flow.length} sequential sub-steps. Include ONE step per flow entry.`;
|
|
502
508
|
}
|
|
503
509
|
return entry;
|
|
504
|
-
}
|
|
510
|
+
};
|
|
511
|
+
const liveSection = liveFeatures.length ? `CURRENT PAGE FEATURES (user is here now):\n${JSON.stringify(liveFeatures.map(summarise), null, 2)}` : `CURRENT PAGE FEATURES: none registered yet.`;
|
|
512
|
+
const ghostSection = ghostFeatures.length ? `OTHER PAGE FEATURES (reachable via navigation — SDK handles it automatically):\n${JSON.stringify(ghostFeatures.map(summarise), null, 2)}` : '';
|
|
505
513
|
return `
|
|
506
514
|
You are an in-app assistant called "${config.assistantName || 'AI Guide'}" for "${config.appName}".
|
|
507
515
|
Your ONLY job: guide users step-by-step through tasks using the feature map below.
|
|
508
516
|
|
|
509
|
-
${screens.length > 1 ? `SCREENS: This app has multiple screens: ${screens.join(', ')}.
|
|
517
|
+
${screens.length > 1 ? `SCREENS: This app has multiple screens: ${screens.join(', ')}. The SDK navigates automatically — just pick the right feature id.` : ''}
|
|
518
|
+
|
|
519
|
+
${liveSection}
|
|
510
520
|
|
|
511
|
-
|
|
512
|
-
${JSON.stringify(featureSummary, null, 2)}
|
|
521
|
+
${ghostSection}
|
|
513
522
|
|
|
514
523
|
RESPOND ONLY with this exact JSON — no markdown, no extra text:
|
|
515
524
|
{
|
|
@@ -526,16 +535,26 @@ RESPOND ONLY with this exact JSON — no markdown, no extra text:
|
|
|
526
535
|
}
|
|
527
536
|
|
|
528
537
|
RULES:
|
|
529
|
-
1. The step "id" MUST match a feature id from the
|
|
538
|
+
1. The step "id" MUST match a feature id from the current page or other page features above.
|
|
530
539
|
2. Only use selectors and IDs from the feature map. Never invent them.
|
|
531
|
-
3.
|
|
532
|
-
4.
|
|
533
|
-
5.
|
|
534
|
-
6. For forms: ALWAYS include a step for the form section or first input BEFORE the
|
|
540
|
+
3. position values: top | bottom | left | right | auto only.
|
|
541
|
+
4. Order steps logically. For multi-step flows, order as the user encounters them.
|
|
542
|
+
5. For forms: ALWAYS include a step for the form section or first input BEFORE the
|
|
535
543
|
continue/submit button. The button step must always be LAST in its section.
|
|
536
|
-
|
|
544
|
+
6. If a feature has a flow, include one step per flow entry using the same feature id —
|
|
537
545
|
the SDK expands them automatically.
|
|
538
|
-
|
|
546
|
+
7. Never skip features in a required sequence. Include every step end-to-end.
|
|
547
|
+
|
|
548
|
+
WHEN THE USER'S REQUEST DOESN'T MATCH ANY FEATURE:
|
|
549
|
+
- If it partially matches something (e.g. they said "create template" and there's a
|
|
550
|
+
"template-gallery" feature): guide them to the closest matching feature and explain
|
|
551
|
+
what it does. Don't say you can't help.
|
|
552
|
+
- If it matches a feature on another page (ghost): include that feature's steps normally.
|
|
553
|
+
The SDK will navigate there automatically. Do NOT tell the user to navigate manually.
|
|
554
|
+
- If there is genuinely no match anywhere in the feature map: set steps to [] and say
|
|
555
|
+
something like "That doesn't seem to be a feature in ${config.appName} yet. Here's
|
|
556
|
+
what I can help you with:" then list 2-3 relevant features from the map by name.
|
|
557
|
+
Never say you "can only guide through available features" — always offer alternatives.
|
|
539
558
|
`.trim();
|
|
540
559
|
}
|
|
541
560
|
|
package/dist/react/core.js
CHANGED
|
@@ -484,7 +484,13 @@ function buildSystemPrompt(config) {
|
|
|
484
484
|
var _f$screen;
|
|
485
485
|
return (_f$screen = f.screen) === null || _f$screen === void 0 ? void 0 : _f$screen.id;
|
|
486
486
|
}).map(f => f.screen.id))];
|
|
487
|
-
|
|
487
|
+
|
|
488
|
+
// Split features into live (current page) and ghost (other pages).
|
|
489
|
+
// This lets the AI understand what's immediately available vs reachable
|
|
490
|
+
// via navigation, and craft the right message when something isn't found.
|
|
491
|
+
const liveFeatures = (config.features || []).filter(f => !f._ghost);
|
|
492
|
+
const ghostFeatures = (config.features || []).filter(f => f._ghost);
|
|
493
|
+
const summarise = f => {
|
|
488
494
|
var _f$screen2, _f$flow;
|
|
489
495
|
const entry = {
|
|
490
496
|
id: f.id,
|
|
@@ -499,15 +505,18 @@ function buildSystemPrompt(config) {
|
|
|
499
505
|
entry.note = `This feature has ${f.flow.length} sequential sub-steps. Include ONE step per flow entry.`;
|
|
500
506
|
}
|
|
501
507
|
return entry;
|
|
502
|
-
}
|
|
508
|
+
};
|
|
509
|
+
const liveSection = liveFeatures.length ? `CURRENT PAGE FEATURES (user is here now):\n${JSON.stringify(liveFeatures.map(summarise), null, 2)}` : `CURRENT PAGE FEATURES: none registered yet.`;
|
|
510
|
+
const ghostSection = ghostFeatures.length ? `OTHER PAGE FEATURES (reachable via navigation — SDK handles it automatically):\n${JSON.stringify(ghostFeatures.map(summarise), null, 2)}` : '';
|
|
503
511
|
return `
|
|
504
512
|
You are an in-app assistant called "${config.assistantName || 'AI Guide'}" for "${config.appName}".
|
|
505
513
|
Your ONLY job: guide users step-by-step through tasks using the feature map below.
|
|
506
514
|
|
|
507
|
-
${screens.length > 1 ? `SCREENS: This app has multiple screens: ${screens.join(', ')}.
|
|
515
|
+
${screens.length > 1 ? `SCREENS: This app has multiple screens: ${screens.join(', ')}. The SDK navigates automatically — just pick the right feature id.` : ''}
|
|
516
|
+
|
|
517
|
+
${liveSection}
|
|
508
518
|
|
|
509
|
-
|
|
510
|
-
${JSON.stringify(featureSummary, null, 2)}
|
|
519
|
+
${ghostSection}
|
|
511
520
|
|
|
512
521
|
RESPOND ONLY with this exact JSON — no markdown, no extra text:
|
|
513
522
|
{
|
|
@@ -524,16 +533,26 @@ RESPOND ONLY with this exact JSON — no markdown, no extra text:
|
|
|
524
533
|
}
|
|
525
534
|
|
|
526
535
|
RULES:
|
|
527
|
-
1. The step "id" MUST match a feature id from the
|
|
536
|
+
1. The step "id" MUST match a feature id from the current page or other page features above.
|
|
528
537
|
2. Only use selectors and IDs from the feature map. Never invent them.
|
|
529
|
-
3.
|
|
530
|
-
4.
|
|
531
|
-
5.
|
|
532
|
-
6. For forms: ALWAYS include a step for the form section or first input BEFORE the
|
|
538
|
+
3. position values: top | bottom | left | right | auto only.
|
|
539
|
+
4. Order steps logically. For multi-step flows, order as the user encounters them.
|
|
540
|
+
5. For forms: ALWAYS include a step for the form section or first input BEFORE the
|
|
533
541
|
continue/submit button. The button step must always be LAST in its section.
|
|
534
|
-
|
|
542
|
+
6. If a feature has a flow, include one step per flow entry using the same feature id —
|
|
535
543
|
the SDK expands them automatically.
|
|
536
|
-
|
|
544
|
+
7. Never skip features in a required sequence. Include every step end-to-end.
|
|
545
|
+
|
|
546
|
+
WHEN THE USER'S REQUEST DOESN'T MATCH ANY FEATURE:
|
|
547
|
+
- If it partially matches something (e.g. they said "create template" and there's a
|
|
548
|
+
"template-gallery" feature): guide them to the closest matching feature and explain
|
|
549
|
+
what it does. Don't say you can't help.
|
|
550
|
+
- If it matches a feature on another page (ghost): include that feature's steps normally.
|
|
551
|
+
The SDK will navigate there automatically. Do NOT tell the user to navigate manually.
|
|
552
|
+
- If there is genuinely no match anywhere in the feature map: set steps to [] and say
|
|
553
|
+
something like "That doesn't seem to be a feature in ${config.appName} yet. Here's
|
|
554
|
+
what I can help you with:" then list 2-3 relevant features from the map by name.
|
|
555
|
+
Never say you "can only guide through available features" — always offer alternatives.
|
|
537
556
|
`.trim();
|
|
538
557
|
}
|
|
539
558
|
|
package/dist/react/index.cjs
CHANGED
|
@@ -315,18 +315,28 @@ function EventopTarget({
|
|
|
315
315
|
navigate,
|
|
316
316
|
navigateWaitFor,
|
|
317
317
|
advanceOn,
|
|
318
|
-
waitFor
|
|
319
|
-
...rest
|
|
318
|
+
waitFor
|
|
320
319
|
}) {
|
|
321
320
|
const registry = useRegistry();
|
|
322
|
-
const
|
|
321
|
+
const wrapperRef = react.useRef(null);
|
|
323
322
|
const dataAttr = `data-evtp-${id}`;
|
|
324
323
|
const selector = `[${dataAttr}]`;
|
|
325
324
|
react.useEffect(() => {
|
|
325
|
+
var _wrapperRef$current;
|
|
326
326
|
if (!id || !name) {
|
|
327
327
|
console.warn('[Eventop] <EventopTarget> requires id and name props.');
|
|
328
328
|
return;
|
|
329
329
|
}
|
|
330
|
+
|
|
331
|
+
// Set the attribute directly on the first real child DOM element.
|
|
332
|
+
// This bypasses React's prop system entirely — works regardless of whether
|
|
333
|
+
// the wrapped component forwards unknown props.
|
|
334
|
+
const firstChild = (_wrapperRef$current = wrapperRef.current) === null || _wrapperRef$current === void 0 ? void 0 : _wrapperRef$current.firstElementChild;
|
|
335
|
+
if (firstChild) {
|
|
336
|
+
firstChild.setAttribute(dataAttr, '');
|
|
337
|
+
} else {
|
|
338
|
+
console.warn(`[Eventop] <EventopTarget id="${id}"> could not find a child DOM element to attach to. ` + `Make sure the wrapped component renders at least one DOM element.`);
|
|
339
|
+
}
|
|
330
340
|
registry.registerFeature({
|
|
331
341
|
id,
|
|
332
342
|
name,
|
|
@@ -341,32 +351,24 @@ function EventopTarget({
|
|
|
341
351
|
...advanceOn
|
|
342
352
|
} : null
|
|
343
353
|
});
|
|
344
|
-
return () =>
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
} catch {
|
|
358
|
-
wrapped = /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
359
|
-
[dataAttr]: '',
|
|
360
|
-
ref: ref,
|
|
354
|
+
return () => {
|
|
355
|
+
var _wrapperRef$current2;
|
|
356
|
+
// Clean up the injected attribute on unmount
|
|
357
|
+
const el = (_wrapperRef$current2 = wrapperRef.current) === null || _wrapperRef$current2 === void 0 ? void 0 : _wrapperRef$current2.firstElementChild;
|
|
358
|
+
if (el) el.removeAttribute(dataAttr);
|
|
359
|
+
registry.unregisterFeature(id);
|
|
360
|
+
};
|
|
361
|
+
}, [id, name, description, route]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
362
|
+
|
|
363
|
+
return /*#__PURE__*/jsxRuntime.jsx(EventopFeatureScopeContext.Provider, {
|
|
364
|
+
value: id,
|
|
365
|
+
children: /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
366
|
+
ref: wrapperRef,
|
|
361
367
|
style: {
|
|
362
368
|
display: 'contents'
|
|
363
369
|
},
|
|
364
|
-
children:
|
|
365
|
-
})
|
|
366
|
-
}
|
|
367
|
-
return /*#__PURE__*/jsxRuntime.jsx(EventopFeatureScopeContext.Provider, {
|
|
368
|
-
value: id,
|
|
369
|
-
children: wrapped
|
|
370
|
+
children: react.Children.only(children)
|
|
371
|
+
})
|
|
370
372
|
});
|
|
371
373
|
}
|
|
372
374
|
|
|
@@ -381,7 +383,7 @@ function EventopStep({
|
|
|
381
383
|
const registry = useRegistry();
|
|
382
384
|
const featureScope = useFeatureScope();
|
|
383
385
|
const featureId = feature || featureScope;
|
|
384
|
-
const
|
|
386
|
+
const wrapperRef = react.useRef(null);
|
|
385
387
|
if (!featureId) {
|
|
386
388
|
console.warn('[Eventop] <EventopStep> needs either a feature prop or an <EventopTarget> ancestor.');
|
|
387
389
|
}
|
|
@@ -391,7 +393,14 @@ function EventopStep({
|
|
|
391
393
|
const dataAttr = `data-evtp-step-${featureId}-${parentStep != null ? `${parentStep}-` : ''}${index}`;
|
|
392
394
|
const selector = `[${dataAttr}]`;
|
|
393
395
|
react.useEffect(() => {
|
|
396
|
+
var _wrapperRef$current;
|
|
394
397
|
if (!featureId || index == null) return;
|
|
398
|
+
|
|
399
|
+
// Inject attribute directly onto the first real child DOM element
|
|
400
|
+
const firstChild = (_wrapperRef$current = wrapperRef.current) === null || _wrapperRef$current === void 0 ? void 0 : _wrapperRef$current.firstElementChild;
|
|
401
|
+
if (firstChild) {
|
|
402
|
+
firstChild.setAttribute(dataAttr, '');
|
|
403
|
+
}
|
|
395
404
|
registry.registerStep(featureId, index, parentStep ?? null, {
|
|
396
405
|
selector,
|
|
397
406
|
waitFor: waitFor || null,
|
|
@@ -400,30 +409,21 @@ function EventopStep({
|
|
|
400
409
|
...advanceOn
|
|
401
410
|
} : null
|
|
402
411
|
});
|
|
403
|
-
return () =>
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
[dataAttr]: '',
|
|
419
|
-
ref: ref,
|
|
420
|
-
style: {
|
|
421
|
-
display: 'contents'
|
|
422
|
-
},
|
|
423
|
-
children: child
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
return wrapped;
|
|
412
|
+
return () => {
|
|
413
|
+
var _wrapperRef$current2;
|
|
414
|
+
const el = (_wrapperRef$current2 = wrapperRef.current) === null || _wrapperRef$current2 === void 0 ? void 0 : _wrapperRef$current2.firstElementChild;
|
|
415
|
+
if (el) el.removeAttribute(dataAttr);
|
|
416
|
+
registry.unregisterStep(featureId, index, parentStep ?? null);
|
|
417
|
+
};
|
|
418
|
+
}, [featureId, index, parentStep]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
419
|
+
|
|
420
|
+
return /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
421
|
+
ref: wrapperRef,
|
|
422
|
+
style: {
|
|
423
|
+
display: 'contents'
|
|
424
|
+
},
|
|
425
|
+
children: react.Children.only(children)
|
|
426
|
+
});
|
|
427
427
|
}
|
|
428
428
|
|
|
429
429
|
// ═══════════════════════════════════════════════════════════════════════════
|
package/dist/react/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, useContext, useRef, useCallback, useEffect, Children,
|
|
1
|
+
import { createContext, useContext, useRef, useCallback, useEffect, Children, useState } from 'react';
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -313,18 +313,28 @@ function EventopTarget({
|
|
|
313
313
|
navigate,
|
|
314
314
|
navigateWaitFor,
|
|
315
315
|
advanceOn,
|
|
316
|
-
waitFor
|
|
317
|
-
...rest
|
|
316
|
+
waitFor
|
|
318
317
|
}) {
|
|
319
318
|
const registry = useRegistry();
|
|
320
|
-
const
|
|
319
|
+
const wrapperRef = useRef(null);
|
|
321
320
|
const dataAttr = `data-evtp-${id}`;
|
|
322
321
|
const selector = `[${dataAttr}]`;
|
|
323
322
|
useEffect(() => {
|
|
323
|
+
var _wrapperRef$current;
|
|
324
324
|
if (!id || !name) {
|
|
325
325
|
console.warn('[Eventop] <EventopTarget> requires id and name props.');
|
|
326
326
|
return;
|
|
327
327
|
}
|
|
328
|
+
|
|
329
|
+
// Set the attribute directly on the first real child DOM element.
|
|
330
|
+
// This bypasses React's prop system entirely — works regardless of whether
|
|
331
|
+
// the wrapped component forwards unknown props.
|
|
332
|
+
const firstChild = (_wrapperRef$current = wrapperRef.current) === null || _wrapperRef$current === void 0 ? void 0 : _wrapperRef$current.firstElementChild;
|
|
333
|
+
if (firstChild) {
|
|
334
|
+
firstChild.setAttribute(dataAttr, '');
|
|
335
|
+
} else {
|
|
336
|
+
console.warn(`[Eventop] <EventopTarget id="${id}"> could not find a child DOM element to attach to. ` + `Make sure the wrapped component renders at least one DOM element.`);
|
|
337
|
+
}
|
|
328
338
|
registry.registerFeature({
|
|
329
339
|
id,
|
|
330
340
|
name,
|
|
@@ -339,32 +349,24 @@ function EventopTarget({
|
|
|
339
349
|
...advanceOn
|
|
340
350
|
} : null
|
|
341
351
|
});
|
|
342
|
-
return () =>
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
} catch {
|
|
356
|
-
wrapped = /*#__PURE__*/jsx("span", {
|
|
357
|
-
[dataAttr]: '',
|
|
358
|
-
ref: ref,
|
|
352
|
+
return () => {
|
|
353
|
+
var _wrapperRef$current2;
|
|
354
|
+
// Clean up the injected attribute on unmount
|
|
355
|
+
const el = (_wrapperRef$current2 = wrapperRef.current) === null || _wrapperRef$current2 === void 0 ? void 0 : _wrapperRef$current2.firstElementChild;
|
|
356
|
+
if (el) el.removeAttribute(dataAttr);
|
|
357
|
+
registry.unregisterFeature(id);
|
|
358
|
+
};
|
|
359
|
+
}, [id, name, description, route]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
360
|
+
|
|
361
|
+
return /*#__PURE__*/jsx(EventopFeatureScopeContext.Provider, {
|
|
362
|
+
value: id,
|
|
363
|
+
children: /*#__PURE__*/jsx("span", {
|
|
364
|
+
ref: wrapperRef,
|
|
359
365
|
style: {
|
|
360
366
|
display: 'contents'
|
|
361
367
|
},
|
|
362
|
-
children:
|
|
363
|
-
})
|
|
364
|
-
}
|
|
365
|
-
return /*#__PURE__*/jsx(EventopFeatureScopeContext.Provider, {
|
|
366
|
-
value: id,
|
|
367
|
-
children: wrapped
|
|
368
|
+
children: Children.only(children)
|
|
369
|
+
})
|
|
368
370
|
});
|
|
369
371
|
}
|
|
370
372
|
|
|
@@ -379,7 +381,7 @@ function EventopStep({
|
|
|
379
381
|
const registry = useRegistry();
|
|
380
382
|
const featureScope = useFeatureScope();
|
|
381
383
|
const featureId = feature || featureScope;
|
|
382
|
-
const
|
|
384
|
+
const wrapperRef = useRef(null);
|
|
383
385
|
if (!featureId) {
|
|
384
386
|
console.warn('[Eventop] <EventopStep> needs either a feature prop or an <EventopTarget> ancestor.');
|
|
385
387
|
}
|
|
@@ -389,7 +391,14 @@ function EventopStep({
|
|
|
389
391
|
const dataAttr = `data-evtp-step-${featureId}-${parentStep != null ? `${parentStep}-` : ''}${index}`;
|
|
390
392
|
const selector = `[${dataAttr}]`;
|
|
391
393
|
useEffect(() => {
|
|
394
|
+
var _wrapperRef$current;
|
|
392
395
|
if (!featureId || index == null) return;
|
|
396
|
+
|
|
397
|
+
// Inject attribute directly onto the first real child DOM element
|
|
398
|
+
const firstChild = (_wrapperRef$current = wrapperRef.current) === null || _wrapperRef$current === void 0 ? void 0 : _wrapperRef$current.firstElementChild;
|
|
399
|
+
if (firstChild) {
|
|
400
|
+
firstChild.setAttribute(dataAttr, '');
|
|
401
|
+
}
|
|
393
402
|
registry.registerStep(featureId, index, parentStep ?? null, {
|
|
394
403
|
selector,
|
|
395
404
|
waitFor: waitFor || null,
|
|
@@ -398,30 +407,21 @@ function EventopStep({
|
|
|
398
407
|
...advanceOn
|
|
399
408
|
} : null
|
|
400
409
|
});
|
|
401
|
-
return () =>
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
[dataAttr]: '',
|
|
417
|
-
ref: ref,
|
|
418
|
-
style: {
|
|
419
|
-
display: 'contents'
|
|
420
|
-
},
|
|
421
|
-
children: child
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
return wrapped;
|
|
410
|
+
return () => {
|
|
411
|
+
var _wrapperRef$current2;
|
|
412
|
+
const el = (_wrapperRef$current2 = wrapperRef.current) === null || _wrapperRef$current2 === void 0 ? void 0 : _wrapperRef$current2.firstElementChild;
|
|
413
|
+
if (el) el.removeAttribute(dataAttr);
|
|
414
|
+
registry.unregisterStep(featureId, index, parentStep ?? null);
|
|
415
|
+
};
|
|
416
|
+
}, [featureId, index, parentStep]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
417
|
+
|
|
418
|
+
return /*#__PURE__*/jsx("span", {
|
|
419
|
+
ref: wrapperRef,
|
|
420
|
+
style: {
|
|
421
|
+
display: 'contents'
|
|
422
|
+
},
|
|
423
|
+
children: Children.only(children)
|
|
424
|
+
});
|
|
425
425
|
}
|
|
426
426
|
|
|
427
427
|
// ═══════════════════════════════════════════════════════════════════════════
|