@eventop/sdk 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +355 -193
  2. package/package.json +25 -13
package/README.md CHANGED
@@ -1,8 +1,6 @@
1
- # eventop/sdk
1
+ # @eventop/sdk
2
2
 
3
- React integration for eventopAI. Features register at the **call site**, not
4
- inside component definitions — so any generic component works with any feature,
5
- and you never touch the component itself.
3
+ AI-powered guided tours for any React or Next.js app. Drop-in, themeable, works with any component library.
6
4
 
7
5
  ---
8
6
 
@@ -10,55 +8,75 @@ and you never touch the component itself.
10
8
 
11
9
  ```bash
12
10
  npm install @eventop/sdk
11
+ # or
12
+ yarn add @eventop/sdk
13
+ # or
14
+ pnpm add @eventop/sdk
13
15
  ```
14
16
 
15
17
  ---
16
18
 
17
- ## The mental model
19
+ ## How it works
18
20
 
19
- ```jsx
20
- // ❌ Old way — registration inside the component, breaks reusability
21
- function ExportButton() {
22
- useeventopFeature({ id: 'export', name: 'Export' }); // hardcoded
23
- return <button>Export</button>;
24
- }
21
+ You wrap any element with `<EventopTarget>` at the call site. The SDK registers it as a feature the AI can guide users to. When a user types what they need in the chat bubble, the AI picks the right features and walks them through step by step.
25
22
 
26
- // New wayregistration at the call site, component stays generic
27
- function Button({ children, onClick }) {
28
- return <button onClick={onClick}>{children}</button>;
29
- }
23
+ The wrapped component stays completely generic `<Button>`, `<div>`, anything from shadcn, MUI, Radix, whatever. You never modify the component itself.
30
24
 
31
- // Different features, same component, different places in the app
32
- <eventopTarget id="export" name="Export Design" description="Download as PNG or SVG">
25
+ ```jsx
26
+ // Same Button, two different features, two different places in the app
27
+ <EventopTarget id="export" name="Export Design" description="Download as PNG or SVG">
33
28
  <Button onClick={handleExport}>Export</Button>
34
- </eventopTarget>
29
+ </EventopTarget>
35
30
 
36
- <eventopTarget id="download-report" name="Download Report" description="Save as PDF">
37
- <Button onClick={handleDownload}>Download</Button>
38
- </eventopTarget>
31
+ <EventopTarget id="share" name="Share Design" description="Share a link with teammates">
32
+ <Button onClick={handleShare}>Share</Button>
33
+ </EventopTarget>
39
34
  ```
40
35
 
41
36
  ---
42
37
 
43
- ## Quick start
38
+ ## React app
39
+
40
+ ### 1. Set up the server endpoint
41
+
42
+ Never put API keys in the browser. Create a server route that proxies the AI call.
43
+
44
+ ```js
45
+ // server.js (Express)
46
+ import Anthropic from '@anthropic-ai/sdk';
47
+
48
+ const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
49
+
50
+ app.post('/api/guide', async (req, res) => {
51
+ const { systemPrompt, messages } = req.body;
52
+ const response = await client.messages.create({
53
+ model: 'claude-sonnet-4-20250514',
54
+ max_tokens: 1000,
55
+ system: systemPrompt,
56
+ messages,
57
+ });
58
+ res.json(JSON.parse(response.content[0].text));
59
+ });
60
+ ```
61
+
62
+ ### 2. Add the provider at the root
44
63
 
45
64
  ```jsx
46
- // main.jsx — provider at the root, nothing else needed here
47
- import { EventopAIProvider } from '@eventop/sdk';
48
- import eventopAI from 'eventop-ai-sdk';
65
+ // main.jsx
66
+ import { EventopAIProvider } from '@eventop/sdk/react';
49
67
 
50
- const provider = eventopAI.providers.custom(async ({ systemPrompt, messages }) => {
68
+ const provider = async ({ systemPrompt, messages }) => {
51
69
  const res = await fetch('/api/guide', {
52
70
  method: 'POST',
53
71
  headers: { 'Content-Type': 'application/json' },
54
72
  body: JSON.stringify({ systemPrompt, messages }),
55
73
  });
56
74
  return res.json();
57
- });
75
+ };
58
76
 
59
77
  export default function App() {
60
78
  return (
61
- <eventopAIProvider
79
+ <EventopAIProvider
62
80
  provider={provider}
63
81
  appName="My App"
64
82
  assistantName="AI Guide"
@@ -67,207 +85,289 @@ export default function App() {
67
85
  position={{ corner: 'bottom-right' }}
68
86
  >
69
87
  <YourApp />
70
- </eventopAIProvider>
88
+ </EventopAIProvider>
71
89
  );
72
90
  }
73
91
  ```
74
92
 
75
- ---
93
+ ### 3. Wrap features anywhere in the tree
76
94
 
77
- ## Components
95
+ ```jsx
96
+ // ExportPanel.jsx
97
+ import { EventopTarget } from '@eventop/sdk/react';
78
98
 
79
- ### `<eventopTarget>`
99
+ export function ExportPanel() {
100
+ return (
101
+ <EventopTarget
102
+ id="export"
103
+ name="Export Design"
104
+ description="Download the design as PNG, SVG or PDF"
105
+ >
106
+ <div id="export-panel">
107
+ <button>PNG</button>
108
+ <button>SVG</button>
109
+ <button>PDF</button>
110
+ </div>
111
+ </EventopTarget>
112
+ );
113
+ }
114
+ ```
80
115
 
81
- Wraps any component and registers it as a feature. Works with your own components,
82
- shadcn, MUI, Radix — anything. The wrapped component does not need to accept refs
83
- or know about eventopAI.
116
+ That's it. The chat bubble appears automatically. Users type what they need and get a guided tour.
84
117
 
85
- ```jsx
86
- import { EventopTarget } from '@eventop/sdk';
118
+ ---
87
119
 
88
- // Simple feature
89
- <EventopTarget id="export" name="Export Design" description="Download as PNG or SVG">
90
- <Button>Export</Button>
91
- </EventopTarget>
120
+ ## Next.js app
92
121
 
93
- // With navigation for features behind a route change
94
- <EventopTarget
95
- id="effects"
96
- name="Effects Panel"
97
- description="Apply shadows, blur and glow"
98
- navigate={() => router.push('/canvas')}
99
- navigateWaitFor="#canvas-stage"
100
- >
101
- <EffectsPanel />
102
- </EventopTarget>
122
+ ### 1. Create the API route
103
123
 
104
- // Auto-advance the tour when clicked
105
- <EventopTarget
106
- id="open-settings"
107
- name="Settings"
108
- description="Open the workspace settings"
109
- advanceOn={{ event: 'click', delay: 200 }}
110
- >
111
- <SettingsButton />
112
- </EventopTarget>
124
+ ```js
125
+ // app/api/guide/route.js (App Router)
126
+ import Anthropic from '@anthropic-ai/sdk';
127
+
128
+ const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
129
+
130
+ export async function POST(request) {
131
+ const { systemPrompt, messages } = await request.json();
132
+ const response = await client.messages.create({
133
+ model: 'claude-sonnet-4-20250514',
134
+ max_tokens: 1000,
135
+ system: systemPrompt,
136
+ messages,
137
+ });
138
+ return Response.json(JSON.parse(response.content[0].text));
139
+ }
113
140
  ```
114
141
 
115
- **Props:**
142
+ ```js
143
+ // pages/api/guide.js (Pages Router)
144
+ import Anthropic from '@anthropic-ai/sdk';
116
145
 
117
- | Prop | Type | Required | Description |
118
- |-------------------|----------|----------|-------------------------------------------------------|
119
- | `id` | string | ✓ | Unique feature id |
120
- | `name` | string | ✓ | Human-readable name (AI reads this) |
121
- | `description` | string | | What it does (AI uses this to match user intent) |
122
- | `navigate` | function | | Navigate here if component is not currently mounted |
123
- | `navigateWaitFor` | string | | CSS selector to wait for after navigating |
124
- | `advanceOn` | object | | `{ event, delay?, selector? }` — auto-advance the tour|
125
- | `waitFor` | string | | CSS selector to wait for before showing this step |
146
+ const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
126
147
 
127
- ---
148
+ export default async function handler(req, res) {
149
+ const { systemPrompt, messages } = req.body;
150
+ const response = await client.messages.create({
151
+ model: 'claude-sonnet-4-20250514',
152
+ max_tokens: 1000,
153
+ system: systemPrompt,
154
+ messages,
155
+ });
156
+ res.json(JSON.parse(response.content[0].text));
157
+ }
158
+ ```
128
159
 
129
- ### `<eventopStep>`
160
+ ### 2. Add the provider in a client component
130
161
 
131
- Registers one step in a multi-step flow. Can live **anywhere** in the component
132
- tree — it does not need to be inside a `eventopTarget`. Steps self-assemble
133
- into the correct sequence via the `index` prop.
162
+ The SDK touches the DOM so the provider must be a client component.
134
163
 
135
164
  ```jsx
136
- import { EventopStep } from '@eventop/sdk';
165
+ // components/EventopProvider.jsx
166
+ 'use client';
137
167
 
138
- // These three components are totally separate — different files, different parents
139
- // They form a flow by sharing the same feature id and sequential indexes
168
+ import { EventopAIProvider } from '@eventop/sdk/react';
140
169
 
141
- // In CanvasStage.jsx
142
- <EventopStep
143
- feature="drop-shadow"
144
- index={0}
145
- advanceOn={{ selector: '.canvas-el', event: 'click', delay: 300 }}
146
- >
147
- <div className="canvas-stage">...</div>
148
- </EventopStep>
149
-
150
- // In Toolbar.jsx
151
- <EventopStep
152
- feature="drop-shadow"
153
- index={1}
154
- waitFor=".canvas-el.selected"
155
- advanceOn={{ event: 'click', delay: 200 }}
156
- >
157
- <button id="btn-effects">Effects</button>
158
- </EventopStep>
159
-
160
- // In EffectsPanel.jsx
161
- <EventopStep
162
- feature="drop-shadow"
163
- index={2}
164
- waitFor="#effects-panel.open"
165
- advanceOn={{ event: 'click', delay: 300 }}
166
- >
167
- <button id="shadow-toggle">Shadow</button>
168
- </EventopStep>
170
+ const provider = async ({ systemPrompt, messages }) => {
171
+ const res = await fetch('/api/guide', {
172
+ method: 'POST',
173
+ headers: { 'Content-Type': 'application/json' },
174
+ body: JSON.stringify({ systemPrompt, messages }),
175
+ });
176
+ return res.json();
177
+ };
178
+
179
+ export function EventopProvider({ children }) {
180
+ return (
181
+ <EventopAIProvider
182
+ provider={provider}
183
+ appName="My App"
184
+ assistantName="AI Guide"
185
+ suggestions={['How do I export?', 'Invite a teammate']}
186
+ theme={{ mode: 'auto', tokens: { accent: '#6366f1' } }}
187
+ position={{ corner: 'bottom-right' }}
188
+ >
189
+ {children}
190
+ </EventopAIProvider>
191
+ );
192
+ }
193
+ ```
194
+
195
+ ```jsx
196
+ // app/layout.jsx
197
+ import { EventopProvider } from '@/components/EventopProvider';
169
198
 
170
- // Only renders when shadow is on — SDK waits for it via waitFor
171
- <EventopStep feature="drop-shadow" index={3} waitFor="#shadow-controls.visible">
172
- <div id="shadow-controls">...</div>
173
- </EventopStep>
199
+ export default function RootLayout({ children }) {
200
+ return (
201
+ <html lang="en">
202
+ <body>
203
+ <EventopProvider>
204
+ {children}
205
+ </EventopProvider>
206
+ </body>
207
+ </html>
208
+ );
209
+ }
174
210
  ```
175
211
 
176
- **Nested sub-steps:**
212
+ ### 3. Wrap features in client components
177
213
 
178
- Pass `parentStep` to model steps that belong inside another step.
179
- Useful for things like "open font picker → (select font family → select weight → set size)".
214
+ Any component that uses `EventopTarget`, `EventopStep`, or the hooks needs `'use client'`.
180
215
 
181
216
  ```jsx
182
- // Step 1: open font picker
183
- <EventopStep feature="style-text" index={1}>
184
- <FontPickerButton />
185
- </EventopStep>
186
-
187
- // Sub-steps of step 1 — run after step 1, in order
188
- <EventopStep feature="style-text" index={0} parentStep={1} waitFor=".font-picker.open">
189
- <FontFamilyList />
190
- </EventopStep>
191
- <EventopStep feature="style-text" index={1} parentStep={1} waitFor=".family-selected">
192
- <FontWeightList />
193
- </EventopStep>
217
+ // components/Toolbar.jsx
218
+ 'use client';
219
+
220
+ import { EventopTarget } from '@eventop/sdk/react';
221
+
222
+ export function Toolbar() {
223
+ return (
224
+ <div className="toolbar">
225
+ <EventopTarget
226
+ id="export"
227
+ name="Export Design"
228
+ description="Download as PNG, SVG or PDF"
229
+ >
230
+ <button>Export</button>
231
+ </EventopTarget>
232
+
233
+ <EventopTarget
234
+ id="share"
235
+ name="Share Design"
236
+ description="Share a link to this design"
237
+ >
238
+ <button>Share</button>
239
+ </EventopTarget>
240
+ </div>
241
+ );
242
+ }
194
243
  ```
195
244
 
196
- **Implicit feature id from `eventopTarget` ancestor:**
245
+ ---
246
+
247
+ ## Multi-step flows
197
248
 
198
- If `eventopStep` is inside a `eventopTarget`, it inherits the feature id:
249
+ For features that require multiple actions in sequence (open a panel, toggle a switch, adjust sliders), use `<EventopStep>`. Steps can live in completely different components — they self-assemble by index.
199
250
 
200
251
  ```jsx
201
- <EventopTarget id="drop-shadow" name="Drop Shadow" description="...">
202
- <div>
203
- <EventopStep index={0} advanceOn={{ selector: '.el', event: 'click' }}>
204
- <Canvas />
252
+ // CanvasStage.jsx step 0: click an element
253
+ 'use client';
254
+ import { EventopStep } from '@eventop/sdk/react';
255
+
256
+ export function CanvasStage() {
257
+ return (
258
+ <EventopStep
259
+ feature="drop-shadow"
260
+ index={0}
261
+ advanceOn={{ selector: '.canvas-el', event: 'click', delay: 300 }}
262
+ >
263
+ <div className="canvas-stage">...</div>
264
+ </EventopStep>
265
+ );
266
+ }
267
+
268
+ // Toolbar.jsx — step 1: click Effects (different component entirely)
269
+ export function EffectsButton() {
270
+ return (
271
+ <EventopStep
272
+ feature="drop-shadow"
273
+ index={1}
274
+ waitFor=".canvas-el.selected"
275
+ advanceOn={{ event: 'click', delay: 200 }}
276
+ >
277
+ <button id="btn-effects">✨ Effects</button>
205
278
  </EventopStep>
206
- <EventopStep index={1} waitFor=".el.selected">
207
- <EffectsButton />
279
+ );
280
+ }
281
+
282
+ // EffectsPanel.jsx — step 2: toggle shadow on
283
+ export function ShadowToggle({ onToggle }) {
284
+ return (
285
+ <EventopStep
286
+ feature="drop-shadow"
287
+ index={2}
288
+ waitFor="#effects-panel.open"
289
+ advanceOn={{ event: 'click', delay: 300 }}
290
+ >
291
+ <button id="shadow-toggle" onClick={onToggle}>Shadow</button>
208
292
  </EventopStep>
209
- </div>
210
- </EventopTarget>
293
+ );
294
+ }
295
+
296
+ // Step 3: sliders — only rendered when shadow is on
297
+ // SDK waits for them via waitFor before showing this step
298
+ export function ShadowSliders() {
299
+ return (
300
+ <EventopStep feature="drop-shadow" index={3} waitFor="#shadow-controls.visible">
301
+ <div id="shadow-controls" className="visible">...</div>
302
+ </EventopStep>
303
+ );
304
+ }
211
305
  ```
212
306
 
213
- **Props:**
307
+ The parent feature still needs a `<EventopTarget>` somewhere:
214
308
 
215
- | Prop | Type | Required | Description |
216
- |--------------|--------|----------|----------------------------------------------------------|
217
- | `feature` | string | * | Feature id this step belongs to (*not needed if inside `eventopTarget`) |
218
- | `index` | number | ✓ | Position in the flow (0-based) |
219
- | `parentStep` | number | | Parent step index — makes this a sub-step |
220
- | `waitFor` | string | | CSS selector to wait for before showing |
221
- | `advanceOn` | object | | `{ event, delay?, selector? }` — auto-advance |
309
+ ```jsx
310
+ // In whichever component owns the canvas screen
311
+ <EventopTarget
312
+ id="drop-shadow"
313
+ name="Drop Shadow Effect"
314
+ description="Apply a customisable drop shadow to a selected element"
315
+ navigate={() => router.push('/canvas')}
316
+ >
317
+ <div className="canvas-screen">
318
+ <CanvasStage />
319
+ <EffectsButton />
320
+ <ShadowToggle />
321
+ {shadowOn && <ShadowSliders />}
322
+ </div>
323
+ </EventopTarget>
324
+ ```
222
325
 
223
326
  ---
224
327
 
225
- ### `useeventopAI`
328
+ ## Async validation
226
329
 
227
- Call SDK methods from inside any component. Use for `stepComplete()` and
228
- `stepFail()` when you have async validation the tour should respect.
330
+ Use `useEventopAI` when a tour step depends on the user completing a form action correctly before advancing.
229
331
 
230
332
  ```jsx
231
- import { useeventopAI } from '@eventop/sdk';
333
+ 'use client';
334
+ import { useEventopAI } from '@eventop/sdk/react';
232
335
 
233
- function CheckoutStep() {
234
- const { stepComplete, stepFail } = useeventopAI();
336
+ export function CheckoutForm() {
337
+ const { stepComplete, stepFail } = useEventopAI();
338
+ const [email, setEmail] = useState('');
235
339
 
236
340
  async function handleContinue() {
237
- const ok = await validateCard(cardNumber);
238
- if (ok) stepComplete(); // tour advances to next step
239
- else stepFail('Invalid card number please try again.');
341
+ const ok = await validateEmail(email);
342
+ if (ok) stepComplete();
343
+ else stepFail('Please enter a valid email address.');
240
344
  }
241
345
 
242
- return <button onClick={handleContinue}>Continue</button>;
346
+ return (
347
+ <EventopTarget id="email-field" name="Email Address" description="Enter your email">
348
+ <div>
349
+ <input
350
+ type="email"
351
+ value={email}
352
+ onChange={e => setEmail(e.target.value)}
353
+ />
354
+ <button onClick={handleContinue}>Continue</button>
355
+ </div>
356
+ </EventopTarget>
357
+ );
243
358
  }
244
359
  ```
245
360
 
246
- **Returns:**
247
-
248
- | Method | Description |
249
- |------------------|-----------------------------------------------------|
250
- | `stepComplete()` | Advance the active tour step |
251
- | `stepFail(msg)` | Block advancement and show error in the tooltip |
252
- | `open()` | Open the chat panel |
253
- | `close()` | Close the chat panel |
254
- | `cancelTour()` | Hard cancel — no resume state saved |
255
- | `resumeTour()` | Resume a paused tour from where it left off |
256
- | `isActive()` | Returns true if a tour is running |
257
- | `isPaused()` | Returns true if a tour is paused |
258
- | `runTour(steps)` | Run a manual tour bypassing the AI |
259
-
260
361
  ---
261
362
 
262
- ### `useeventopTour`
263
-
264
- React to tour state in your own UI. Reactive — updates every 300ms.
363
+ ## Tour status in your own UI
265
364
 
266
365
  ```jsx
267
- import { useeventopTour } from '@eventop/sdk';
366
+ 'use client';
367
+ import { useEventopTour } from '@eventop/sdk/react';
268
368
 
269
- function TourStatusBar() {
270
- const { isActive, isPaused, resume, cancel } = useeventopTour();
369
+ export function TourStatusBar() {
370
+ const { isActive, isPaused, resume, cancel } = useEventopTour();
271
371
 
272
372
  if (!isActive && !isPaused) return null;
273
373
 
@@ -289,27 +389,89 @@ function TourStatusBar() {
289
389
 
290
390
  ---
291
391
 
292
- ## Screen navigation
392
+ ## API reference
393
+
394
+ ### `<EventopAIProvider>`
395
+
396
+ | Prop | Type | Required | Default | Description |
397
+ |-----------------|------------|----------|----------------|-------------------------------|
398
+ | `provider` | function | ✓ | — | Async function that calls your server route |
399
+ | `appName` | string | ✓ | — | Shown in the chat header |
400
+ | `assistantName` | string | | `'AI Guide'` | Name shown in the chat header |
401
+ | `suggestions` | string[] | | `[]` | Clickable chips on first open |
402
+ | `theme` | object | | dark, default | `{ mode, preset, tokens }` |
403
+ | `position` | object | | bottom-right | `{ corner, offsetX, offsetY }`|
404
+
405
+ ### `<EventopTarget>`
406
+
407
+ | Prop | Type | Required | Description |
408
+ |-------------------|----------|----------|---------------------------------------------------------|
409
+ | `id` | string | ✓ | Unique feature id |
410
+ | `name` | string | ✓ | Human-readable name the AI reads |
411
+ | `description` | string | | What it does — AI uses this to match user intent |
412
+ | `navigate` | function | | Navigate here if component is not currently mounted |
413
+ | `navigateWaitFor` | string | | CSS selector to wait for after navigating |
414
+ | `advanceOn` | object | | `{ event, delay?, selector? }` — auto-advance the tour |
415
+ | `waitFor` | string | | CSS selector to wait for before showing this step |
416
+
417
+ ### `<EventopStep>`
418
+
419
+ | Prop | Type | Required | Description |
420
+ |-------------|--------|----------|----------------------------------------------------------------|
421
+ | `feature` | string | * | Feature id (*not needed if inside `<EventopTarget>`) |
422
+ | `index` | number | ✓ | Position in the flow, 0-based |
423
+ | `parentStep`| number | | Makes this a sub-step of another step |
424
+ | `waitFor` | string | | CSS selector to wait for before showing |
425
+ | `advanceOn` | object | | `{ event, delay?, selector? }` — auto-advance |
426
+
427
+ ### `useEventopAI`
428
+
429
+ | Method | Description |
430
+ |--------------------|------------------------------------------------------|
431
+ | `stepComplete()` | Advance the active tour step |
432
+ | `stepFail(msg)` | Block advancement and show error in the tooltip |
433
+ | `open()` | Open the chat panel |
434
+ | `close()` | Close the chat panel |
435
+ | `cancelTour()` | Hard cancel — no resume state saved |
436
+ | `resumeTour()` | Resume a paused tour from where it left off |
437
+ | `isActive()` | Returns true if a tour is currently running |
438
+ | `isPaused()` | Returns true if a tour is paused |
439
+ | `runTour(steps)` | Run a tour manually, bypassing the AI |
440
+
441
+ ### `useEventopTour`
442
+
443
+ | Property / Method | Type | Description |
444
+ |-------------------|----------|------------------------------------------|
445
+ | `isActive` | boolean | True if a tour is running |
446
+ | `isPaused` | boolean | True if a tour is paused |
447
+ | `resume()` | function | Resume a paused tour |
448
+ | `cancel()` | function | Hard cancel |
449
+ | `open()` | function | Open the chat panel |
450
+ | `close()` | function | Close the chat panel |
293
451
 
294
- Because `eventopTarget` only registers a feature while its component is mounted,
295
- screen detection is automatic. If the Effects Panel is not rendered, the `effects`
296
- feature simply does not exist in the registry — no `screen.check()` needed.
452
+ ---
453
+
454
+ ## Theme tokens
297
455
 
298
- For features that live behind a route change, pass `navigate`:
456
+ | Token | Default (dark) | Default (light) |
457
+ |-------------------|------------------|-----------------|
458
+ | `accent` | `#e94560` | `#e94560` |
459
+ | `accentSecondary` | `#a855f7` | `#7c3aed` |
460
+ | `bg` | `#0f0f1a` | `#ffffff` |
461
+ | `surface` | `#1a1a2e` | `#f8f8fc` |
462
+ | `border` | `#2a2a4a` | `#e4e4f0` |
463
+ | `text` | `#e0e0f0` | `#1a1a2e` |
464
+ | `radius` | `16px` | `16px` |
465
+
466
+ Override any token:
299
467
 
300
468
  ```jsx
301
- // Only rendered on /canvas route
302
- function EffectsPanel() {
303
- return (
304
- <EventopTarget
305
- id="effects"
306
- name="Effects Panel"
307
- description="Apply shadows and blur"
308
- navigate={() => router.push('/canvas')}
309
- navigateWaitFor="#canvas-root"
310
- >
311
- <div id="effects-panel">...</div>
312
- </EventopTarget>
313
- );
314
- }
315
- ```
469
+ theme={{
470
+ mode: 'dark',
471
+ tokens: {
472
+ accent: '#6366f1',
473
+ radius: '12px',
474
+ fontFamily: "'Inter', sans-serif",
475
+ }
476
+ }}
477
+ ```
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@eventop/sdk",
3
- "version": "1.0.4",
4
- "description": "Official SDK for Eventop",
3
+ "version": "1.0.5",
4
+ "description": "AI-powered guided tours for any web app. Drop-in, themeable, provider-agnostic.",
5
5
  "keywords": [
6
- "Onboarding",
7
- "subscriptions",
8
- "crypto",
9
- "payments"
6
+ "onboarding",
7
+ "tour",
8
+ "guided-tour",
9
+ "ai",
10
+ "react"
10
11
  ],
11
12
  "homepage": "https://github.com/eventop-s/sdk#readme",
12
13
  "bugs": {
@@ -21,10 +22,17 @@
21
22
  "type": "module",
22
23
  "main": "./dist/index.js",
23
24
  "module": "./dist/index.js",
25
+ "types": "./dist/index.d.ts",
24
26
  "exports": {
25
27
  ".": {
26
28
  "import": "./dist/index.js",
27
- "require": "./dist/index.cjs"
29
+ "require": "./dist/index.cjs",
30
+ "types": "./dist/index.d.ts"
31
+ },
32
+ "./react": {
33
+ "import": "./dist/react/index.js",
34
+ "require": "./dist/react/index.cjs",
35
+ "types": "./dist/react/index.d.ts"
28
36
  }
29
37
  },
30
38
  "files": [
@@ -36,17 +44,21 @@
36
44
  "prepublishOnly": "yarn run build"
37
45
  },
38
46
  "dependencies": {
39
- "node-fetch": "^2.6.7"
47
+ "node-fetch": "^2.6.7",
48
+ "react": "^19.2.4"
40
49
  },
41
50
  "peerDependencies": {
42
51
  "react": "^18.0.0 || ^19.0.0"
43
52
  },
44
53
  "devDependencies": {
45
- "@rollup/plugin-node-resolve": "^15.2.3",
46
- "@rollup/plugin-commonjs": "^25.0.7",
47
- "@rollup/plugin-babel": "^6.0.4",
48
54
  "@babel/core": "^7.23.9",
49
55
  "@babel/preset-react": "^7.23.3",
50
- "rollup": "^4.9.6"
56
+ "@rollup/plugin-babel": "^6.0.4",
57
+ "@rollup/plugin-commonjs": "^25.0.7",
58
+ "@rollup/plugin-node-resolve": "^15.2.3",
59
+ "@types/react": "^19.2.14",
60
+ "@types/react-dom": "^19.2.3",
61
+ "rollup": "^4.9.6",
62
+ "typescript": "^5.9.3"
51
63
  }
52
- }
64
+ }