@eventop/sdk 1.2.2 → 1.2.11
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/README.md +113 -22
- package/dist/core.cjs +1347 -983
- package/dist/core.js +1347 -983
- package/dist/index.cjs +40 -37
- package/dist/index.d.ts +118 -35
- package/dist/index.js +40 -37
- package/dist/react/core.cjs +1347 -983
- package/dist/react/core.js +1347 -983
- package/dist/react/index.cjs +40 -37
- package/dist/react/index.d.ts +91 -13
- package/dist/react/index.js +40 -37
- package/package.json +1 -1
package/dist/react/index.cjs
CHANGED
|
@@ -52,12 +52,16 @@ function useFeatureScope() {
|
|
|
52
52
|
*
|
|
53
53
|
* In practice most flows are flat (index 0, 1, 2, 3...) but the
|
|
54
54
|
* registry supports nested depth for complex interactions.
|
|
55
|
+
*
|
|
56
|
+
* Route awareness:
|
|
57
|
+
* Features can declare the pathname they live on via `route`.
|
|
58
|
+
* The snapshot() includes this so the SDK core can navigate
|
|
59
|
+
* automatically when a tour step targets a feature on a different page.
|
|
55
60
|
*/
|
|
56
61
|
function createFeatureRegistry() {
|
|
57
62
|
// Map<featureId, featureData>
|
|
58
63
|
const features = new Map();
|
|
59
64
|
// Map<featureId, Map<stepKey, stepData>>
|
|
60
|
-
// stepKey is either a number (flat) or "parentIndex.childIndex" (nested)
|
|
61
65
|
const flowSteps = new Map();
|
|
62
66
|
const listeners = new Set();
|
|
63
67
|
function notify() {
|
|
@@ -74,21 +78,19 @@ function createFeatureRegistry() {
|
|
|
74
78
|
notify();
|
|
75
79
|
}
|
|
76
80
|
function unregisterFeature(id) {
|
|
77
|
-
features.
|
|
81
|
+
features.set(id, {
|
|
82
|
+
...existing,
|
|
83
|
+
selector: null,
|
|
84
|
+
advanceOn: null,
|
|
85
|
+
waitFor: null,
|
|
86
|
+
_ghost: true
|
|
87
|
+
});
|
|
78
88
|
flowSteps.delete(id);
|
|
79
89
|
notify();
|
|
80
90
|
}
|
|
81
91
|
|
|
82
92
|
// ── Step registration ────────────────────────────────────────────────────
|
|
83
93
|
|
|
84
|
-
/**
|
|
85
|
-
* Register a flow step.
|
|
86
|
-
*
|
|
87
|
-
* @param {string} featureId - Parent feature id
|
|
88
|
-
* @param {number} index - Position in the flat flow (0, 1, 2…)
|
|
89
|
-
* @param {number|null} parentStep - If set, this is a sub-step of parentStep
|
|
90
|
-
* @param {object} stepData - { selector, waitFor, advanceOn, ... }
|
|
91
|
-
*/
|
|
92
94
|
function registerStep(featureId, index, parentStep, stepData) {
|
|
93
95
|
if (!flowSteps.has(featureId)) {
|
|
94
96
|
flowSteps.set(featureId, new Map());
|
|
@@ -113,35 +115,14 @@ function createFeatureRegistry() {
|
|
|
113
115
|
|
|
114
116
|
// ── Snapshot ─────────────────────────────────────────────────────────────
|
|
115
117
|
|
|
116
|
-
/**
|
|
117
|
-
* Build the flat flow array the SDK core expects.
|
|
118
|
-
*
|
|
119
|
-
* For nested steps we inline sub-steps after their parent step,
|
|
120
|
-
* in index order. This means a flow like:
|
|
121
|
-
*
|
|
122
|
-
* Step 0 (flat)
|
|
123
|
-
* Step 1 (flat)
|
|
124
|
-
* Step 1.0 (sub-step of 1)
|
|
125
|
-
* Step 1.1 (sub-step of 1)
|
|
126
|
-
* Step 2 (flat)
|
|
127
|
-
*
|
|
128
|
-
* becomes the SDK flow: [step0, step1, step1.0, step1.1, step2]
|
|
129
|
-
*
|
|
130
|
-
* The AI writes titles/text for the parent feature.
|
|
131
|
-
* Sub-steps inherit the parent step's text with a "(N/M)" suffix added
|
|
132
|
-
* by the SDK's expandFlowSteps() function.
|
|
133
|
-
*/
|
|
134
118
|
function buildFlow(featureId) {
|
|
135
119
|
const map = flowSteps.get(featureId);
|
|
136
120
|
if (!map || map.size === 0) return null;
|
|
137
121
|
const allSteps = Array.from(map.values());
|
|
138
|
-
|
|
139
|
-
// Separate top-level and nested steps
|
|
140
122
|
const topLevel = allSteps.filter(s => s.parentStep == null).sort((a, b) => a.index - b.index);
|
|
141
123
|
const result = [];
|
|
142
124
|
topLevel.forEach(step => {
|
|
143
125
|
result.push(step);
|
|
144
|
-
// Inline any sub-steps after the parent
|
|
145
126
|
const children = allSteps.filter(s => s.parentStep === step.index).sort((a, b) => a.index - b.index);
|
|
146
127
|
result.push(...children);
|
|
147
128
|
});
|
|
@@ -150,7 +131,9 @@ function createFeatureRegistry() {
|
|
|
150
131
|
|
|
151
132
|
/**
|
|
152
133
|
* Returns the live feature array in the format the SDK core expects.
|
|
153
|
-
*
|
|
134
|
+
*
|
|
135
|
+
* `route` is now included in every feature entry so the core can detect
|
|
136
|
+
* when navigation is needed before showing a step.
|
|
154
137
|
*/
|
|
155
138
|
function snapshot() {
|
|
156
139
|
return Array.from(features.values()).map(feature => {
|
|
@@ -160,6 +143,7 @@ function createFeatureRegistry() {
|
|
|
160
143
|
name: feature.name,
|
|
161
144
|
description: feature.description,
|
|
162
145
|
selector: feature.selector,
|
|
146
|
+
route: feature.route || null,
|
|
163
147
|
advanceOn: feature.advanceOn || null,
|
|
164
148
|
waitFor: feature.waitFor || null,
|
|
165
149
|
...(flow ? {
|
|
@@ -195,7 +179,8 @@ function EventopProvider({
|
|
|
195
179
|
assistantName,
|
|
196
180
|
suggestions,
|
|
197
181
|
theme,
|
|
198
|
-
position
|
|
182
|
+
position,
|
|
183
|
+
router
|
|
199
184
|
}) {
|
|
200
185
|
if (!provider) throw new Error('[Eventop] <EventopProvider> requires a provider prop.');
|
|
201
186
|
if (!appName) throw new Error('[Eventop] <EventopProvider> requires an appName prop.');
|
|
@@ -209,10 +194,9 @@ function EventopProvider({
|
|
|
209
194
|
});
|
|
210
195
|
}, [registry]);
|
|
211
196
|
react.useEffect(() => {
|
|
212
|
-
// Dynamically import core.js only in the browser
|
|
213
197
|
async function boot() {
|
|
214
|
-
//
|
|
215
|
-
|
|
198
|
+
await Promise.resolve().then(function () { return require('./core.cjs'); }); // Ensure the UMD bundle is loaded (for Shepherd and global Eventop)
|
|
199
|
+
|
|
216
200
|
window.Eventop.init({
|
|
217
201
|
provider,
|
|
218
202
|
config: {
|
|
@@ -221,6 +205,7 @@ function EventopProvider({
|
|
|
221
205
|
suggestions,
|
|
222
206
|
theme,
|
|
223
207
|
position,
|
|
208
|
+
router,
|
|
224
209
|
features: registry.snapshot(),
|
|
225
210
|
_providerName: 'custom'
|
|
226
211
|
}
|
|
@@ -238,6 +223,22 @@ function EventopProvider({
|
|
|
238
223
|
}
|
|
239
224
|
};
|
|
240
225
|
}, [provider, appName, assistantName, suggestions, theme, position, registry, syncToSDK]);
|
|
226
|
+
// Note: `router` is intentionally omitted from the deps array above.
|
|
227
|
+
// Router instances from useNavigate / useRouter are stable references —
|
|
228
|
+
// including them would re-boot the SDK on every render.
|
|
229
|
+
// Instead, we sync router updates via a separate effect below.
|
|
230
|
+
|
|
231
|
+
// ── Keep the router reference fresh without re-booting the SDK ─────────────
|
|
232
|
+
// When the router instance changes (rare, but can happen in Next.js during
|
|
233
|
+
// hydration), we push the new reference into the already-running SDK core.
|
|
234
|
+
react.useEffect(() => {
|
|
235
|
+
if (sdkReady.current && window.Eventop) {
|
|
236
|
+
var _window$Eventop$_upda2, _window$Eventop3;
|
|
237
|
+
(_window$Eventop$_upda2 = (_window$Eventop3 = window.Eventop)._updateConfig) === null || _window$Eventop$_upda2 === void 0 || _window$Eventop$_upda2.call(_window$Eventop3, {
|
|
238
|
+
router
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
}, [router]);
|
|
241
242
|
const ctx = {
|
|
242
243
|
registerFeature: registry.registerFeature,
|
|
243
244
|
unregisterFeature: registry.unregisterFeature,
|
|
@@ -256,6 +257,7 @@ function EventopTarget({
|
|
|
256
257
|
id,
|
|
257
258
|
name,
|
|
258
259
|
description,
|
|
260
|
+
route,
|
|
259
261
|
navigate,
|
|
260
262
|
navigateWaitFor,
|
|
261
263
|
advanceOn,
|
|
@@ -275,6 +277,7 @@ function EventopTarget({
|
|
|
275
277
|
id,
|
|
276
278
|
name,
|
|
277
279
|
description,
|
|
280
|
+
route,
|
|
278
281
|
selector,
|
|
279
282
|
navigate,
|
|
280
283
|
navigateWaitFor,
|
|
@@ -285,7 +288,7 @@ function EventopTarget({
|
|
|
285
288
|
} : null
|
|
286
289
|
});
|
|
287
290
|
return () => registry.unregisterFeature(id);
|
|
288
|
-
}, [id, name, description]);
|
|
291
|
+
}, [id, name, description, route]);
|
|
289
292
|
const child = react.Children.only(children);
|
|
290
293
|
let wrapped;
|
|
291
294
|
try {
|
package/dist/react/index.d.ts
CHANGED
|
@@ -15,6 +15,29 @@ export interface EventopAIProviderProps {
|
|
|
15
15
|
suggestions?: string[];
|
|
16
16
|
theme?: Theme;
|
|
17
17
|
position?: Position;
|
|
18
|
+
/**
|
|
19
|
+
* Navigation function for cross-page tours.
|
|
20
|
+
*
|
|
21
|
+
* When a tour step lives on a different route, the SDK calls this function
|
|
22
|
+
* with the target pathname, shows the user a message explaining the navigation,
|
|
23
|
+
* then waits for the target element to appear before showing the step.
|
|
24
|
+
*
|
|
25
|
+
* If omitted, the SDK falls back to window.history.pushState + popstate
|
|
26
|
+
* (best-effort; works for simple SPAs but not React Router / Next.js).
|
|
27
|
+
*
|
|
28
|
+
* @example — React Router v6
|
|
29
|
+
* const navigate = useNavigate();
|
|
30
|
+
* <EventopAIProvider router={navigate} ...>
|
|
31
|
+
*
|
|
32
|
+
* @example — Next.js App Router
|
|
33
|
+
* const router = useRouter(); // from 'next/navigation'
|
|
34
|
+
* <EventopAIProvider router={(path) => router.push(path)} ...>
|
|
35
|
+
*
|
|
36
|
+
* @example — Next.js Pages Router
|
|
37
|
+
* const router = useRouter(); // from 'next/router'
|
|
38
|
+
* <EventopAIProvider router={(path) => router.push(path)} ...>
|
|
39
|
+
*/
|
|
40
|
+
router?: (path: string) => void | Promise<void>;
|
|
18
41
|
}
|
|
19
42
|
|
|
20
43
|
/**
|
|
@@ -23,13 +46,36 @@ export interface EventopAIProviderProps {
|
|
|
23
46
|
* register with this provider automatically.
|
|
24
47
|
*
|
|
25
48
|
* @example
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
49
|
+
* // React Router v6
|
|
50
|
+
* function Root() {
|
|
51
|
+
* const navigate = useNavigate();
|
|
52
|
+
* return (
|
|
53
|
+
* <EventopAIProvider
|
|
54
|
+
* router={navigate}
|
|
55
|
+
* provider={myServerFetcher}
|
|
56
|
+
* appName="My App"
|
|
57
|
+
* theme={{ mode: 'auto', tokens: { accent: '#6366f1' } }}
|
|
58
|
+
* >
|
|
59
|
+
* <App />
|
|
60
|
+
* </EventopAIProvider>
|
|
61
|
+
* );
|
|
62
|
+
* }
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* // Next.js App Router (must be 'use client')
|
|
66
|
+
* 'use client';
|
|
67
|
+
* export function EventopProvider({ children }) {
|
|
68
|
+
* const router = useRouter();
|
|
69
|
+
* return (
|
|
70
|
+
* <EventopAIProvider
|
|
71
|
+
* router={(path) => router.push(path)}
|
|
72
|
+
* provider={myServerFetcher}
|
|
73
|
+
* appName="My App"
|
|
74
|
+
* >
|
|
75
|
+
* {children}
|
|
76
|
+
* </EventopAIProvider>
|
|
77
|
+
* );
|
|
78
|
+
* }
|
|
33
79
|
*/
|
|
34
80
|
export const EventopAIProvider: FC<EventopAIProviderProps>;
|
|
35
81
|
|
|
@@ -44,9 +90,34 @@ export interface EventopTargetProps {
|
|
|
44
90
|
name: string;
|
|
45
91
|
/** What the feature does — AI uses this to match user intent */
|
|
46
92
|
description?: string;
|
|
93
|
+
/**
|
|
94
|
+
* The pathname where this feature lives (e.g. "/settings/billing").
|
|
95
|
+
*
|
|
96
|
+
* When a tour step targets this feature and the user is on a different page,
|
|
97
|
+
* the SDK will automatically:
|
|
98
|
+
* 1. Tell the user which page it's navigating to and why
|
|
99
|
+
* 2. Call the `router` function passed to EventopAIProvider
|
|
100
|
+
* 3. Wait for this feature's element to appear before showing the step
|
|
101
|
+
*
|
|
102
|
+
* Only required for features that live on a different page than where
|
|
103
|
+
* the tour is typically started from. Features on the same page don't
|
|
104
|
+
* need this prop.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* <EventopTarget
|
|
108
|
+
* id="billing"
|
|
109
|
+
* name="Billing Settings"
|
|
110
|
+
* route="/settings/billing"
|
|
111
|
+
* >
|
|
112
|
+
* <BillingSection />
|
|
113
|
+
* </EventopTarget>
|
|
114
|
+
*/
|
|
115
|
+
route?: string;
|
|
47
116
|
/**
|
|
48
117
|
* Navigate to this screen if the component is not currently mounted.
|
|
49
|
-
*
|
|
118
|
+
* @deprecated Prefer `route` + the `router` prop on EventopAIProvider
|
|
119
|
+
* for React Router and Next.js apps. `navigate` is still
|
|
120
|
+
* supported for custom or non-URL-based navigation logic.
|
|
50
121
|
*/
|
|
51
122
|
navigate?: () => void | Promise<void>;
|
|
52
123
|
/** CSS selector to wait for after navigating */
|
|
@@ -61,20 +132,27 @@ export interface EventopTargetProps {
|
|
|
61
132
|
}
|
|
62
133
|
|
|
63
134
|
/**
|
|
64
|
-
* Wraps any component and registers it as
|
|
135
|
+
* Wraps any component and registers it as an Eventop feature.
|
|
65
136
|
* Registration happens at the CALL SITE — the wrapped component is unchanged.
|
|
66
137
|
*
|
|
67
138
|
* Works with any component: your own, shadcn, MUI, Radix, anything.
|
|
68
|
-
* The wrapped component does not need to accept refs or know about
|
|
139
|
+
* The wrapped component does not need to accept refs or know about Eventop.
|
|
69
140
|
*
|
|
70
141
|
* @example
|
|
71
|
-
* //
|
|
142
|
+
* // Feature on the same page — no route needed
|
|
72
143
|
* <EventopTarget id="export" name="Export Design" description="Download as PNG or SVG">
|
|
73
144
|
* <Button onClick={handleExport}>Export</Button>
|
|
74
145
|
* </EventopTarget>
|
|
75
146
|
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
147
|
+
* @example
|
|
148
|
+
* // Feature on a different page — add route so the SDK can navigate there
|
|
149
|
+
* <EventopTarget
|
|
150
|
+
* id="billing"
|
|
151
|
+
* name="Billing Settings"
|
|
152
|
+
* description="Manage your subscription"
|
|
153
|
+
* route="/settings/billing"
|
|
154
|
+
* >
|
|
155
|
+
* <BillingSection />
|
|
78
156
|
* </EventopTarget>
|
|
79
157
|
*/
|
|
80
158
|
export const EventopTarget: FC<EventopTargetProps>;
|
package/dist/react/index.js
CHANGED
|
@@ -50,12 +50,16 @@ function useFeatureScope() {
|
|
|
50
50
|
*
|
|
51
51
|
* In practice most flows are flat (index 0, 1, 2, 3...) but the
|
|
52
52
|
* registry supports nested depth for complex interactions.
|
|
53
|
+
*
|
|
54
|
+
* Route awareness:
|
|
55
|
+
* Features can declare the pathname they live on via `route`.
|
|
56
|
+
* The snapshot() includes this so the SDK core can navigate
|
|
57
|
+
* automatically when a tour step targets a feature on a different page.
|
|
53
58
|
*/
|
|
54
59
|
function createFeatureRegistry() {
|
|
55
60
|
// Map<featureId, featureData>
|
|
56
61
|
const features = new Map();
|
|
57
62
|
// Map<featureId, Map<stepKey, stepData>>
|
|
58
|
-
// stepKey is either a number (flat) or "parentIndex.childIndex" (nested)
|
|
59
63
|
const flowSteps = new Map();
|
|
60
64
|
const listeners = new Set();
|
|
61
65
|
function notify() {
|
|
@@ -72,21 +76,19 @@ function createFeatureRegistry() {
|
|
|
72
76
|
notify();
|
|
73
77
|
}
|
|
74
78
|
function unregisterFeature(id) {
|
|
75
|
-
features.
|
|
79
|
+
features.set(id, {
|
|
80
|
+
...existing,
|
|
81
|
+
selector: null,
|
|
82
|
+
advanceOn: null,
|
|
83
|
+
waitFor: null,
|
|
84
|
+
_ghost: true
|
|
85
|
+
});
|
|
76
86
|
flowSteps.delete(id);
|
|
77
87
|
notify();
|
|
78
88
|
}
|
|
79
89
|
|
|
80
90
|
// ── Step registration ────────────────────────────────────────────────────
|
|
81
91
|
|
|
82
|
-
/**
|
|
83
|
-
* Register a flow step.
|
|
84
|
-
*
|
|
85
|
-
* @param {string} featureId - Parent feature id
|
|
86
|
-
* @param {number} index - Position in the flat flow (0, 1, 2…)
|
|
87
|
-
* @param {number|null} parentStep - If set, this is a sub-step of parentStep
|
|
88
|
-
* @param {object} stepData - { selector, waitFor, advanceOn, ... }
|
|
89
|
-
*/
|
|
90
92
|
function registerStep(featureId, index, parentStep, stepData) {
|
|
91
93
|
if (!flowSteps.has(featureId)) {
|
|
92
94
|
flowSteps.set(featureId, new Map());
|
|
@@ -111,35 +113,14 @@ function createFeatureRegistry() {
|
|
|
111
113
|
|
|
112
114
|
// ── Snapshot ─────────────────────────────────────────────────────────────
|
|
113
115
|
|
|
114
|
-
/**
|
|
115
|
-
* Build the flat flow array the SDK core expects.
|
|
116
|
-
*
|
|
117
|
-
* For nested steps we inline sub-steps after their parent step,
|
|
118
|
-
* in index order. This means a flow like:
|
|
119
|
-
*
|
|
120
|
-
* Step 0 (flat)
|
|
121
|
-
* Step 1 (flat)
|
|
122
|
-
* Step 1.0 (sub-step of 1)
|
|
123
|
-
* Step 1.1 (sub-step of 1)
|
|
124
|
-
* Step 2 (flat)
|
|
125
|
-
*
|
|
126
|
-
* becomes the SDK flow: [step0, step1, step1.0, step1.1, step2]
|
|
127
|
-
*
|
|
128
|
-
* The AI writes titles/text for the parent feature.
|
|
129
|
-
* Sub-steps inherit the parent step's text with a "(N/M)" suffix added
|
|
130
|
-
* by the SDK's expandFlowSteps() function.
|
|
131
|
-
*/
|
|
132
116
|
function buildFlow(featureId) {
|
|
133
117
|
const map = flowSteps.get(featureId);
|
|
134
118
|
if (!map || map.size === 0) return null;
|
|
135
119
|
const allSteps = Array.from(map.values());
|
|
136
|
-
|
|
137
|
-
// Separate top-level and nested steps
|
|
138
120
|
const topLevel = allSteps.filter(s => s.parentStep == null).sort((a, b) => a.index - b.index);
|
|
139
121
|
const result = [];
|
|
140
122
|
topLevel.forEach(step => {
|
|
141
123
|
result.push(step);
|
|
142
|
-
// Inline any sub-steps after the parent
|
|
143
124
|
const children = allSteps.filter(s => s.parentStep === step.index).sort((a, b) => a.index - b.index);
|
|
144
125
|
result.push(...children);
|
|
145
126
|
});
|
|
@@ -148,7 +129,9 @@ function createFeatureRegistry() {
|
|
|
148
129
|
|
|
149
130
|
/**
|
|
150
131
|
* Returns the live feature array in the format the SDK core expects.
|
|
151
|
-
*
|
|
132
|
+
*
|
|
133
|
+
* `route` is now included in every feature entry so the core can detect
|
|
134
|
+
* when navigation is needed before showing a step.
|
|
152
135
|
*/
|
|
153
136
|
function snapshot() {
|
|
154
137
|
return Array.from(features.values()).map(feature => {
|
|
@@ -158,6 +141,7 @@ function createFeatureRegistry() {
|
|
|
158
141
|
name: feature.name,
|
|
159
142
|
description: feature.description,
|
|
160
143
|
selector: feature.selector,
|
|
144
|
+
route: feature.route || null,
|
|
161
145
|
advanceOn: feature.advanceOn || null,
|
|
162
146
|
waitFor: feature.waitFor || null,
|
|
163
147
|
...(flow ? {
|
|
@@ -193,7 +177,8 @@ function EventopProvider({
|
|
|
193
177
|
assistantName,
|
|
194
178
|
suggestions,
|
|
195
179
|
theme,
|
|
196
|
-
position
|
|
180
|
+
position,
|
|
181
|
+
router
|
|
197
182
|
}) {
|
|
198
183
|
if (!provider) throw new Error('[Eventop] <EventopProvider> requires a provider prop.');
|
|
199
184
|
if (!appName) throw new Error('[Eventop] <EventopProvider> requires an appName prop.');
|
|
@@ -207,10 +192,9 @@ function EventopProvider({
|
|
|
207
192
|
});
|
|
208
193
|
}, [registry]);
|
|
209
194
|
useEffect(() => {
|
|
210
|
-
// Dynamically import core.js only in the browser
|
|
211
195
|
async function boot() {
|
|
212
|
-
//
|
|
213
|
-
|
|
196
|
+
await import('./core.js'); // Ensure the UMD bundle is loaded (for Shepherd and global Eventop)
|
|
197
|
+
|
|
214
198
|
window.Eventop.init({
|
|
215
199
|
provider,
|
|
216
200
|
config: {
|
|
@@ -219,6 +203,7 @@ function EventopProvider({
|
|
|
219
203
|
suggestions,
|
|
220
204
|
theme,
|
|
221
205
|
position,
|
|
206
|
+
router,
|
|
222
207
|
features: registry.snapshot(),
|
|
223
208
|
_providerName: 'custom'
|
|
224
209
|
}
|
|
@@ -236,6 +221,22 @@ function EventopProvider({
|
|
|
236
221
|
}
|
|
237
222
|
};
|
|
238
223
|
}, [provider, appName, assistantName, suggestions, theme, position, registry, syncToSDK]);
|
|
224
|
+
// Note: `router` is intentionally omitted from the deps array above.
|
|
225
|
+
// Router instances from useNavigate / useRouter are stable references —
|
|
226
|
+
// including them would re-boot the SDK on every render.
|
|
227
|
+
// Instead, we sync router updates via a separate effect below.
|
|
228
|
+
|
|
229
|
+
// ── Keep the router reference fresh without re-booting the SDK ─────────────
|
|
230
|
+
// When the router instance changes (rare, but can happen in Next.js during
|
|
231
|
+
// hydration), we push the new reference into the already-running SDK core.
|
|
232
|
+
useEffect(() => {
|
|
233
|
+
if (sdkReady.current && window.Eventop) {
|
|
234
|
+
var _window$Eventop$_upda2, _window$Eventop3;
|
|
235
|
+
(_window$Eventop$_upda2 = (_window$Eventop3 = window.Eventop)._updateConfig) === null || _window$Eventop$_upda2 === void 0 || _window$Eventop$_upda2.call(_window$Eventop3, {
|
|
236
|
+
router
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}, [router]);
|
|
239
240
|
const ctx = {
|
|
240
241
|
registerFeature: registry.registerFeature,
|
|
241
242
|
unregisterFeature: registry.unregisterFeature,
|
|
@@ -254,6 +255,7 @@ function EventopTarget({
|
|
|
254
255
|
id,
|
|
255
256
|
name,
|
|
256
257
|
description,
|
|
258
|
+
route,
|
|
257
259
|
navigate,
|
|
258
260
|
navigateWaitFor,
|
|
259
261
|
advanceOn,
|
|
@@ -273,6 +275,7 @@ function EventopTarget({
|
|
|
273
275
|
id,
|
|
274
276
|
name,
|
|
275
277
|
description,
|
|
278
|
+
route,
|
|
276
279
|
selector,
|
|
277
280
|
navigate,
|
|
278
281
|
navigateWaitFor,
|
|
@@ -283,7 +286,7 @@ function EventopTarget({
|
|
|
283
286
|
} : null
|
|
284
287
|
});
|
|
285
288
|
return () => registry.unregisterFeature(id);
|
|
286
|
-
}, [id, name, description]);
|
|
289
|
+
}, [id, name, description, route]);
|
|
287
290
|
const child = Children.only(children);
|
|
288
291
|
let wrapped;
|
|
289
292
|
try {
|