@syntrologie/runtime-sdk 2.8.0-canary.5 → 2.8.0-canary.50

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 (46) hide show
  1. package/CAPABILITIES.md +214 -111
  2. package/README.md +2 -0
  3. package/dist/actions/schema.d.ts +1 -1
  4. package/dist/actions/schema.js +1 -1
  5. package/dist/actions/validation-core.d.ts +24 -0
  6. package/dist/actions/validation-rules.d.ts +74 -0
  7. package/dist/actions/validation.d.ts +5 -11
  8. package/dist/bootstrap-init.d.ts +33 -0
  9. package/dist/bootstrap-runtime.d.ts +7 -0
  10. package/dist/bootstrap-types.d.ts +90 -0
  11. package/dist/bootstrap.d.ts +17 -83
  12. package/dist/{chunk-WOSJMR3G.js → chunk-MQ3RNLXB.js} +1519 -606
  13. package/dist/chunk-MQ3RNLXB.js.map +7 -0
  14. package/dist/{chunk-R5DNAIRI.js → chunk-TN5BLBPU.js} +1 -1
  15. package/dist/{chunk-R5DNAIRI.js.map → chunk-TN5BLBPU.js.map} +1 -1
  16. package/dist/components/TileIcon.d.ts +2 -2
  17. package/dist/components/emojiToIcon.d.ts +24 -0
  18. package/dist/events/EventBus.d.ts +27 -1
  19. package/dist/events/history.d.ts +9 -0
  20. package/dist/events/index.d.ts +3 -0
  21. package/dist/events/normalizers/posthog.d.ts +4 -50
  22. package/dist/events/types.d.ts +30 -23
  23. package/dist/events/validation.d.ts +7 -0
  24. package/dist/index.d.ts +0 -2
  25. package/dist/index.js +1525 -210
  26. package/dist/index.js.map +4 -4
  27. package/dist/overlays/runtime/overlay/overlay-runner.d.ts +4 -0
  28. package/dist/overlays/runtime/overlay/overlay-state.d.ts +21 -0
  29. package/dist/overlays/types.d.ts +3 -1
  30. package/dist/react.js +4 -2
  31. package/dist/react.js.map +2 -2
  32. package/dist/smart-canvas.esm.js +115 -65
  33. package/dist/smart-canvas.esm.js.map +4 -4
  34. package/dist/smart-canvas.js +5669 -3002
  35. package/dist/smart-canvas.js.map +4 -4
  36. package/dist/smart-canvas.min.js +115 -65
  37. package/dist/smart-canvas.min.js.map +4 -4
  38. package/dist/telemetry/adapters/posthog.d.ts +30 -4
  39. package/dist/test/setup.d.ts +1 -0
  40. package/dist/token.d.ts +2 -0
  41. package/dist/version.d.ts +1 -1
  42. package/package.json +23 -28
  43. package/schema/canvas-config.schema.json +100 -2
  44. package/scripts/syntroReactPlugin.mjs +3 -0
  45. package/scripts/validate-config.mjs +42 -0
  46. package/dist/chunk-WOSJMR3G.js.map +0 -7
package/CAPABILITIES.md CHANGED
@@ -54,8 +54,8 @@ Change a page header when the element is visible:
54
54
  },
55
55
  "actions": [
56
56
  {
57
- "kind": "set_text",
58
- "anchorId": "h1.hero-title",
57
+ "kind": "content:setText",
58
+ "anchorId": { "selector": "h1.hero-title", "route": "/" },
59
59
  "text": "Welcome to Our New Experience"
60
60
  }
61
61
  ]
@@ -160,62 +160,73 @@ The widget reads auth credentials from the browser:
160
160
 
161
161
  DOM content modification capabilities for text, attributes, styles, HTML, and classes.
162
162
 
163
+ ## When to use
164
+
165
+ | Goal | Action |
166
+ |------|--------|
167
+ | Replace an element's text | `content:setText` |
168
+ | Change an HTML attribute (href, src, data-*) | `content:setAttr` |
169
+ | Modify inline styles (color, size, spacing) | `content:setStyle` |
170
+ | Inject new HTML before/after/inside an element | `content:insertHtml` |
171
+ | Add a CSS class (show/hide, animate) | `content:addClass` |
172
+ | Remove a CSS class | `content:removeClass` |
173
+
163
174
  ## Actions
164
175
 
165
- ### set_text
176
+ ### content:setText
166
177
 
167
178
  Replaces the text content of an element.
168
179
 
169
- | Property | Type | Required | Description |
170
- | ---------- | ------------ | -------- | ---------------- |
171
- | `kind` | `"set_text"` | Yes | Action type |
172
- | `anchorId` | string | Yes | Element selector |
173
- | `text` | string | Yes | New text content |
180
+ | Property | Type | Required | Description |
181
+ | ---------- | ------------------- | -------- | ---------------- |
182
+ | `kind` | `"content:setText"` | Yes | Action type |
183
+ | `anchorId` | object | Yes | `{ selector, route }` |
184
+ | `text` | string | Yes | New text content |
174
185
 
175
186
  ```json
176
187
  {
177
- "kind": "set_text",
178
- "anchorId": "h1.hero-title",
188
+ "kind": "content:setText",
189
+ "anchorId": { "selector": "h1.hero-title", "route": "/" },
179
190
  "text": "Start Your Free Trial Today"
180
191
  }
181
192
  ```
182
193
 
183
- ### set_attr
194
+ ### content:setAttr
184
195
 
185
196
  Sets an HTML attribute on an element.
186
197
 
187
- | Property | Type | Required | Description |
188
- | ---------- | ------------ | -------- | ---------------- |
189
- | `kind` | `"set_attr"` | Yes | Action type |
190
- | `anchorId` | string | Yes | Element selector |
191
- | `attr` | string | Yes | Attribute name |
192
- | `value` | string | Yes | Attribute value |
198
+ | Property | Type | Required | Description |
199
+ | ---------- | ------------------- | -------- | ---------------- |
200
+ | `kind` | `"content:setAttr"` | Yes | Action type |
201
+ | `anchorId` | object | Yes | `{ selector, route }` |
202
+ | `attr` | string | Yes | Attribute name |
203
+ | `value` | string | Yes | Attribute value |
193
204
 
194
205
  **Blocked attributes:** Event handlers (`onclick`, `onerror`, etc.) are not allowed.
195
206
 
196
207
  ```json
197
208
  {
198
- "kind": "set_attr",
199
- "anchorId": "#signup-form",
209
+ "kind": "content:setAttr",
210
+ "anchorId": { "selector": "#signup-form", "route": "/" },
200
211
  "attr": "data-experiment",
201
212
  "value": "signup-v2"
202
213
  }
203
214
  ```
204
215
 
205
- ### set_style
216
+ ### content:setStyle
206
217
 
207
218
  Sets inline CSS styles on an element.
208
219
 
209
- | Property | Type | Required | Description |
210
- | ---------- | ------------- | -------- | ------------------------ |
211
- | `kind` | `"set_style"` | Yes | Action type |
212
- | `anchorId` | string | Yes | Element selector |
213
- | `styles` | object | Yes | CSS property/value pairs |
220
+ | Property | Type | Required | Description |
221
+ | ---------- | -------------------- | -------- | ------------------------ |
222
+ | `kind` | `"content:setStyle"` | Yes | Action type |
223
+ | `anchorId` | object | Yes | `{ selector, route }` |
224
+ | `styles` | object | Yes | CSS property/value pairs |
214
225
 
215
226
  ```json
216
227
  {
217
- "kind": "set_style",
218
- "anchorId": ".hero-section",
228
+ "kind": "content:setStyle",
229
+ "anchorId": { "selector": ".hero-section", "route": "/" },
219
230
  "styles": {
220
231
  "background-color": "#1e40af",
221
232
  "padding": "2rem"
@@ -223,16 +234,17 @@ Sets inline CSS styles on an element.
223
234
  }
224
235
  ```
225
236
 
226
- ### insert_html
237
+ ### content:insertHtml
227
238
 
228
239
  Inserts HTML content relative to an element.
229
240
 
230
- | Property | Type | Required | Description |
231
- | ---------- | --------------- | -------- | ----------------------------------------------------------- |
232
- | `kind` | `"insert_html"` | Yes | Action type |
233
- | `anchorId` | string | Yes | Element selector |
234
- | `html` | string | Yes | HTML content (sanitized) |
235
- | `position` | string | Yes | `"before"`, `"after"`, `"prepend"`, `"append"`, `"replace"` |
241
+ | Property | Type | Required | Description |
242
+ | ---------- | --------------------- | -------- | ----------------------------------------------------------- |
243
+ | `kind` | `"content:insertHtml"` | Yes | Action type |
244
+ | `anchorId` | object | Yes | `{ selector, route }` |
245
+ | `html` | string | Yes | HTML content (sanitized) |
246
+ | `position` | string | Yes | `"before"`, `"after"`, `"prepend"`, `"append"`, `"replace"` |
247
+ | `deepLink` | object | No | Makes the entire inserted element clickable to open the canvas panel and navigate to a specific tile |
236
248
 
237
249
  **Positions:**
238
250
 
@@ -244,45 +256,66 @@ Inserts HTML content relative to an element.
244
256
 
245
257
  ```json
246
258
  {
247
- "kind": "insert_html",
248
- "anchorId": ".cta-button",
259
+ "kind": "content:insertHtml",
260
+ "anchorId": { "selector": ".cta-button", "route": "/" },
249
261
  "html": "<span class=\"badge\">NEW</span>",
250
262
  "position": "append"
251
263
  }
252
264
  ```
253
265
 
254
- ### add_class
266
+ **Deep-linking to canvas tiles:**
267
+
268
+ Use `deepLink` to make inserted content open the canvas panel and navigate to a specific tile when clicked. This is the correct way to connect inserted buttons/links to canvas tiles — do NOT use `onclick` handlers with `window.SynOS`.
269
+
270
+ | Property | Type | Required | Description |
271
+ | ---------------- | ------ | -------- | ---------------------------------- |
272
+ | `deepLink.tileId` | string | Yes | ID of the tile to open |
273
+ | `deepLink.itemId` | string | No | Specific item within the tile |
274
+
275
+ ```json
276
+ {
277
+ "kind": "content:insertHtml",
278
+ "anchorId": { "selector": "[data-id='pricing-heading']", "route": "/" },
279
+ "html": "<button style='background: #4a90e2; color: white; border: none; padding: 8px 16px; border-radius: 20px; cursor: pointer;'>Help Me Choose</button>",
280
+ "position": "after",
281
+ "deepLink": { "tileId": "plan_selector_faq" }
282
+ }
283
+ ```
284
+
285
+ The SDK automatically handles opening the canvas, setting the cursor to pointer, and publishing a `notification.deep_link` event. The click handler is wired up and cleaned up by the SDK — no JavaScript in the HTML is needed.
286
+
287
+ ### content:addClass
255
288
 
256
289
  Adds a CSS class to an element.
257
290
 
258
- | Property | Type | Required | Description |
259
- | ----------- | ------------- | -------- | ----------------- |
260
- | `kind` | `"add_class"` | Yes | Action type |
261
- | `anchorId` | string | Yes | Element selector |
262
- | `className` | string | Yes | Class name to add |
291
+ | Property | Type | Required | Description |
292
+ | ----------- | -------------------- | -------- | ----------------- |
293
+ | `kind` | `"content:addClass"` | Yes | Action type |
294
+ | `anchorId` | object | Yes | `{ selector, route }` |
295
+ | `className` | string | Yes | Class name to add |
263
296
 
264
297
  ```json
265
298
  {
266
- "kind": "add_class",
267
- "anchorId": ".pricing-card",
299
+ "kind": "content:addClass",
300
+ "anchorId": { "selector": ".pricing-card", "route": "/pricing" },
268
301
  "className": "highlighted"
269
302
  }
270
303
  ```
271
304
 
272
- ### remove_class
305
+ ### content:removeClass
273
306
 
274
307
  Removes a CSS class from an element.
275
308
 
276
- | Property | Type | Required | Description |
277
- | ----------- | ---------------- | -------- | -------------------- |
278
- | `kind` | `"remove_class"` | Yes | Action type |
279
- | `anchorId` | string | Yes | Element selector |
280
- | `className` | string | Yes | Class name to remove |
309
+ | Property | Type | Required | Description |
310
+ | ----------- | ----------------------- | -------- | -------------------- |
311
+ | `kind` | `"content:removeClass"` | Yes | Action type |
312
+ | `anchorId` | object | Yes | `{ selector, route }` |
313
+ | `className` | string | Yes | Class name to remove |
281
314
 
282
315
  ```json
283
316
  {
284
- "kind": "remove_class",
285
- "anchorId": ".pricing-card",
317
+ "kind": "content:removeClass",
318
+ "anchorId": { "selector": ".pricing-card", "route": "/pricing" },
286
319
  "className": "hidden"
287
320
  }
288
321
  ```
@@ -294,15 +327,24 @@ Removes a CSS class from an element.
294
327
 
295
328
  Collapsible Q&A accordion with actions, rich content, feedback, and personalization.
296
329
 
330
+ ## When to use
331
+
332
+ | Goal | Action |
333
+ |------|--------|
334
+ | Mount an FAQ accordion widget | `core:mountWidget` with `widget: "adaptive-faq:accordion"` |
335
+ | Scroll to and expand a specific FAQ item | `faq:scroll_to` |
336
+ | Open, close, or toggle a FAQ item | `faq:toggle_item` |
337
+ | Add, remove, reorder, or replace FAQ items | `faq:update` |
338
+
297
339
  ## Actions
298
340
 
299
- ### mount_faq
341
+ ### core:mountWidget (FAQ)
300
342
 
301
343
  Mounts an FAQ accordion widget to a surface slot.
302
344
 
303
345
  | Property | Type | Required | Description |
304
346
  | ----------------------- | --------------------------------- | -------- | ------------------------------------------------------------------- |
305
- | `kind` | `"mount_faq"` | Yes | Action type |
347
+ | `kind` | `"core:mountWidget"` | Yes | Action type |
306
348
  | `slot` | string | Yes | Target slot (e.g., `"drawer_right"`, `"overlay_center"`) |
307
349
  | `config.title` | string | No | Widget title |
308
350
  | `config.expandBehavior` | `"single"` \| `"multiple"` | No | Whether one or many items can be open at once (default: `"single"`) |
@@ -326,11 +368,11 @@ Each item in the `items` array:
326
368
  | `config.category` | string | No | Category for grouping items |
327
369
  | `config.priority` | number | No | Priority weight for ordering |
328
370
  | `config.answerStrategy` | AnswerStrategy | No | AI-generated answer configuration |
329
- | `showWhen` | DecisionStrategy \| null | No | Conditional visibility strategy |
371
+ | `triggerWhen` | DecisionStrategy \| null | No | Conditional visibility strategy |
330
372
 
331
373
  ```json
332
374
  {
333
- "kind": "mount_faq",
375
+ "kind": "core:mountWidget",
334
376
  "slot": "drawer_right",
335
377
  "config": {
336
378
  "title": "Frequently Asked Questions",
@@ -362,7 +404,7 @@ Each item in the `items` array:
362
404
  "category": "Billing",
363
405
  "priority": 5
364
406
  },
365
- "showWhen": {
407
+ "triggerWhen": {
366
408
  "type": "rules",
367
409
  "rules": [
368
410
  {
@@ -378,13 +420,13 @@ Each item in the `items` array:
378
420
  }
379
421
  ```
380
422
 
381
- ### scroll_to_faq
423
+ ### faq:scroll_to
382
424
 
383
425
  Scrolls the viewport to a specific FAQ item and optionally expands it.
384
426
 
385
427
  | Property | Type | Required | Default | Description |
386
428
  | -------------- | ----------------- | -------- | ---------- | ------------------------------------------ |
387
- | `kind` | `"scroll_to_faq"` | Yes | | Action type |
429
+ | `kind` | `"faq:scroll_to"` | Yes | | Action type |
388
430
  | `itemId` | string | No\* | | Target item ID |
389
431
  | `itemQuestion` | string | No\* | | Target item question text (fuzzy match) |
390
432
  | `expand` | boolean | No | `true` | Whether to expand the item after scrolling |
@@ -394,20 +436,20 @@ Scrolls the viewport to a specific FAQ item and optionally expands it.
394
436
 
395
437
  ```json
396
438
  {
397
- "kind": "scroll_to_faq",
439
+ "kind": "faq:scroll_to",
398
440
  "itemId": "payment-methods",
399
441
  "expand": true,
400
442
  "behavior": "smooth"
401
443
  }
402
444
  ```
403
445
 
404
- ### toggle_faq_item
446
+ ### faq:toggle_item
405
447
 
406
448
  Opens, closes, or toggles a FAQ item's expanded state.
407
449
 
408
450
  | Property | Type | Required | Default | Description |
409
451
  | -------------- | ------------------- | -------- | ---------- | --------------------------------------- |
410
- | `kind` | `"toggle_faq_item"` | Yes | | Action type |
452
+ | `kind` | `"faq:toggle_item"` | Yes | | Action type |
411
453
  | `itemId` | string | No\* | | Target item ID |
412
454
  | `itemQuestion` | string | No\* | | Target item question text (fuzzy match) |
413
455
  | `state` | string | No | `"toggle"` | `"open"`, `"closed"`, `"toggle"` |
@@ -416,19 +458,19 @@ Opens, closes, or toggles a FAQ item's expanded state.
416
458
 
417
459
  ```json
418
460
  {
419
- "kind": "toggle_faq_item",
461
+ "kind": "faq:toggle_item",
420
462
  "itemId": "getting-started",
421
463
  "state": "open"
422
464
  }
423
465
  ```
424
466
 
425
- ### update_faq
467
+ ### faq:update
426
468
 
427
469
  Dynamically adds, removes, reorders, or replaces FAQ items at runtime.
428
470
 
429
471
  | Property | Type | Required | Description |
430
472
  | ----------- | ------------------- | -------- | ------------------------------------------------------- |
431
- | `kind` | `"update_faq"` | Yes | Action type |
473
+ | `kind` | `"faq:update"` | Yes | Action type |
432
474
  | `operation` | string | Yes | `"add"`, `"remove"`, `"reorder"`, `"replace"` |
433
475
  | `items` | FAQQuestionAction[] | No | Items to add or replace with (required for add/replace) |
434
476
  | `itemId` | string | No | Item to remove (required for remove) |
@@ -440,7 +482,7 @@ Dynamically adds, removes, reorders, or replaces FAQ items at runtime.
440
482
 
441
483
  ```json
442
484
  {
443
- "kind": "update_faq",
485
+ "kind": "faq:update",
444
486
  "operation": "add",
445
487
  "position": "append",
446
488
  "items": [
@@ -460,7 +502,7 @@ Dynamically adds, removes, reorders, or replaces FAQ items at runtime.
460
502
 
461
503
  ```json
462
504
  {
463
- "kind": "update_faq",
505
+ "kind": "faq:update",
464
506
  "operation": "remove",
465
507
  "itemId": "outdated-question"
466
508
  }
@@ -470,7 +512,7 @@ Dynamically adds, removes, reorders, or replaces FAQ items at runtime.
470
512
 
471
513
  ```json
472
514
  {
473
- "kind": "update_faq",
515
+ "kind": "faq:update",
474
516
  "operation": "reorder",
475
517
  "order": ["getting-started", "new-feature", "payment-methods"]
476
518
  }
@@ -480,7 +522,7 @@ Dynamically adds, removes, reorders, or replaces FAQ items at runtime.
480
522
 
481
523
  ```json
482
524
  {
483
- "kind": "update_faq",
525
+ "kind": "faq:update",
484
526
  "operation": "replace",
485
527
  "items": [
486
528
  {
@@ -499,12 +541,12 @@ Dynamically adds, removes, reorders, or replaces FAQ items at runtime.
499
541
 
500
542
  The FAQ widget uses a **compositional action pattern** where `faq:question` actions serve as configuration data rendered by the widget, rather than being executed by the runtime. This allows:
501
543
 
502
- - **Per-item conditional visibility** via `showWhen` strategies -- items can appear or hide based on page URL, user segment, viewport, or any DecisionStrategy condition
544
+ - **Per-item conditional visibility** via `triggerWhen` strategies -- items can appear or hide based on page URL, user segment, viewport, or any DecisionStrategy condition
503
545
  - **Category grouping** -- items with a `category` field are grouped under collapsible section headers
504
546
  - **Dynamic injection** -- `injections` rules can add items when trigger conditions are met, supporting contextual FAQ content
505
547
  - **Ordering control** -- the `ordering` strategy determines how items are sorted within categories
506
548
 
507
- Items without `showWhen` are always visible. Items without `category` appear in an ungrouped section.
549
+ Items without `triggerWhen` are always visible. Items without `category` appear in an ungrouped section.
508
550
 
509
551
  ## Rich Answer Content
510
552
 
@@ -650,15 +692,55 @@ Injection rules add contextual FAQ items when conditions are met:
650
692
 
651
693
  Gamification capabilities including badges, points, and leaderboards.
652
694
 
695
+ ## When to use
696
+
697
+ | Goal | Action |
698
+ |------|--------|
699
+ | Award a badge to a user | `gamification:awardBadge` |
700
+ | Add points to a user's score | `gamification:addPoints` |
701
+ | Mount a gamification widget (leaderboard, progress) | `core:mountWidget` |
702
+
653
703
  ## Actions
654
704
 
655
- ### mount_gamification
705
+ ### gamification:awardBadge
656
706
 
657
- Mounts gamification UI elements.
707
+ Awards a badge to the current user.
708
+
709
+ | Property | Type | Required | Description |
710
+ | -------- | -------------------------- | -------- | ---------------- |
711
+ | `kind` | `"gamification:awardBadge"` | Yes | Action type |
712
+ | `badgeId` | string | Yes | Badge identifier |
713
+
714
+ ```json
715
+ {
716
+ "kind": "gamification:awardBadge",
717
+ "badgeId": "first-purchase"
718
+ }
719
+ ```
720
+
721
+ ### gamification:addPoints
722
+
723
+ Adds points to the current user's score.
724
+
725
+ | Property | Type | Required | Description |
726
+ | -------- | -------------------------- | -------- | ---------------- |
727
+ | `kind` | `"gamification:addPoints"` | Yes | Action type |
728
+ | `points` | number | Yes | Points to add |
729
+
730
+ ```json
731
+ {
732
+ "kind": "gamification:addPoints",
733
+ "points": 50
734
+ }
735
+ ```
736
+
737
+ ### core:mountWidget (Gamification)
738
+
739
+ Mounts gamification UI elements (leaderboard, badge display, progress tracker).
658
740
 
659
741
  | Property | Type | Required | Description |
660
742
  | -------- | ---------------------- | -------- | -------------------------- |
661
- | `kind` | `"mount_gamification"` | Yes | Action type |
743
+ | `kind` | `"core:mountWidget"` | Yes | Action type |
662
744
  | `slot` | string | Yes | Target slot |
663
745
  | `config` | object | Yes | Gamification configuration |
664
746
 
@@ -685,7 +767,7 @@ Mounts gamification UI elements.
685
767
 
686
768
  ```json
687
769
  {
688
- "kind": "mount_gamification",
770
+ "kind": "core:mountWidget",
689
771
  "slot": "overlay_corner_br",
690
772
  "config": {
691
773
  "badges": [
@@ -697,18 +779,6 @@ Mounts gamification UI elements.
697
779
  "trigger": {
698
780
  "event": "purchase_completed"
699
781
  }
700
- },
701
- {
702
- "id": "explorer",
703
- "name": "Explorer",
704
- "icon": "compass",
705
- "description": "Visited 10 different pages",
706
- "trigger": {
707
- "event": "page_view",
708
- "conditions": [
709
- { "type": "session_metric", "key": "unique_pages", "operator": ">=", "threshold": 10 }
710
- ]
711
- }
712
782
  }
713
783
  ],
714
784
  "points": {
@@ -737,6 +807,14 @@ Mounts gamification UI elements.
737
807
 
738
808
  Navigation tips accordion widget with conditional item visibility and toast notifications.
739
809
 
810
+ ## When to use
811
+
812
+ | Goal | Action |
813
+ |------|--------|
814
+ | Scroll to an element on the page | `navigation:scrollTo` |
815
+ | Navigate to a different URL | `navigation:navigate` |
816
+ | Show contextual navigation tips widget | `core:mountWidget` with `widget: "adaptive-nav:tips"` |
817
+
740
818
  ## Widget: `adaptive-nav:tips`
741
819
 
742
820
  Accordion of contextual navigation tips. Each tip has a collapsible header and expanded body with optional CTA link.
@@ -857,15 +935,26 @@ Navigates to a URL.
857
935
 
858
936
  Visual overlay capabilities including highlights, tooltips, badges, pulse animations, and celebrations.
859
937
 
938
+ ## When to use
939
+
940
+ | Goal | Action |
941
+ |------|--------|
942
+ | Draw attention to an element (spotlight) | `overlays:highlight` |
943
+ | Show contextual help or guidance near an element | `overlays:tooltip` |
944
+ | Add a notification indicator (count, "NEW") | `overlays:badge` |
945
+ | Subtle attention-grab animation | `overlays:pulse` |
946
+ | Show a blocking or non-blocking dialog | `overlays:modal` |
947
+ | Celebrate a user achievement | `overlays:celebrate` |
948
+
860
949
  ## Actions
861
950
 
862
- ### highlight
951
+ ### overlays:highlight
863
952
 
864
953
  Creates a spotlight effect around an element with a scrim overlay.
865
954
 
866
955
  | Property | Type | Required | Default | Description |
867
956
  | -------------------- | ------------- | -------- | ----------- | --------------------------------------- |
868
- | `kind` | `"highlight"` | Yes | | Action type |
957
+ | `kind` | `"overlays:highlight"` | Yes | | Action type |
869
958
  | `anchorId` | string | Yes | | Element selector |
870
959
  | `style.color` | string | No | `"#5b8cff"` | Ring color |
871
960
  | `style.scrimOpacity` | number | No | `0.55` | Backdrop opacity 0-1 (set to 0 to hide) |
@@ -874,7 +963,7 @@ Creates a spotlight effect around an element with a scrim overlay.
874
963
 
875
964
  ```json
876
965
  {
877
- "kind": "highlight",
966
+ "kind": "overlays:highlight",
878
967
  "anchorId": "#signup-button",
879
968
  "style": {
880
969
  "color": "#22c55e",
@@ -883,13 +972,13 @@ Creates a spotlight effect around an element with a scrim overlay.
883
972
  }
884
973
  ```
885
974
 
886
- ### tooltip
975
+ ### overlays:tooltip
887
976
 
888
977
  Shows a tooltip near an element with optional title, body, and CTA.
889
978
 
890
979
  | Property | Type | Required | Default | Description |
891
980
  | -------------------- | ----------- | -------- | ------------- | -------------------------------------- |
892
- | `kind` | `"tooltip"` | Yes | | Action type |
981
+ | `kind` | `"overlays:tooltip"` | Yes | | Action type |
893
982
  | `anchorId` | string | Yes | | Element selector |
894
983
  | `content.title` | string | No | | Tooltip heading |
895
984
  | `content.body` | string | Yes | | Tooltip text |
@@ -905,14 +994,14 @@ Shows a tooltip near an element with optional title, body, and CTA.
905
994
 
906
995
  ```json
907
996
  {
908
- "kind": "tooltip",
997
+ "kind": "overlays:tooltip",
909
998
  "anchorId": "#pricing-toggle",
910
999
  "content": {
911
1000
  "title": "Save 20%",
912
1001
  "body": "Switch to annual billing to save on your subscription.",
913
1002
  "cta": {
914
1003
  "label": "Switch Now",
915
- "action": { "kind": "navigate", "url": "/billing?annual=true" }
1004
+ "action": { "kind": "navigation:navigate", "url": "/billing?annual=true" }
916
1005
  }
917
1006
  },
918
1007
  "placement": "bottom",
@@ -951,45 +1040,45 @@ Use `ctaButtons` for tooltips with multiple actions. Each button has:
951
1040
  - `"faq:open:<questionId>"` — Convention for companion FAQ tooltips (see adaptive-faq CAPABILITIES for details). Publishes `action.tooltip_cta_clicked` which the FAQ widget listens for.
952
1041
  - Any other value — Publishes `action.tooltip_cta_clicked` with the `actionId` in event props for custom handling
953
1042
 
954
- ### badge
1043
+ ### overlays:badge
955
1044
 
956
1045
  Adds a small badge indicator near an element.
957
1046
 
958
1047
  | Property | Type | Required | Default | Description |
959
1048
  | ---------- | --------- | -------- | ------------- | -------------------------------------------------------------- |
960
- | `kind` | `"badge"` | Yes | | Action type |
1049
+ | `kind` | `"overlays:badge"` | Yes | | Action type |
961
1050
  | `anchorId` | string | Yes | | Element selector |
962
1051
  | `text` | string | Yes | | Badge text (e.g., "NEW", "3") |
963
1052
  | `position` | string | No | `"top-right"` | `"top-left"`, `"top-right"`, `"bottom-left"`, `"bottom-right"` |
964
1053
 
965
1054
  ```json
966
1055
  {
967
- "kind": "badge",
1056
+ "kind": "overlays:badge",
968
1057
  "anchorId": "#inbox-icon",
969
1058
  "text": "5",
970
1059
  "position": "top-right"
971
1060
  }
972
1061
  ```
973
1062
 
974
- ### pulse
1063
+ ### overlays:pulse
975
1064
 
976
1065
  Adds a pulsing animation to draw attention.
977
1066
 
978
1067
  | Property | Type | Required | Default | Description |
979
1068
  | ---------- | --------- | -------- | ------- | ------------------------ |
980
- | `kind` | `"pulse"` | Yes | | Action type |
1069
+ | `kind` | `"overlays:pulse"` | Yes | | Action type |
981
1070
  | `anchorId` | string | Yes | | Element selector |
982
1071
  | `duration` | number | No | `2000` | Animation duration in ms |
983
1072
 
984
1073
  ```json
985
1074
  {
986
- "kind": "pulse",
1075
+ "kind": "overlays:pulse",
987
1076
  "anchorId": ".notification-bell",
988
1077
  "duration": 3000
989
1078
  }
990
1079
  ```
991
1080
 
992
- ### modal
1081
+ ### overlays:modal
993
1082
 
994
1083
  Shows a centered modal dialog with optional CTA buttons.
995
1084
 
@@ -1029,7 +1118,7 @@ Shows a centered modal dialog with optional CTA buttons.
1029
1118
  }
1030
1119
  ```
1031
1120
 
1032
- ### celebrate
1121
+ ### overlays:celebrate
1033
1122
 
1034
1123
  Renders a fullscreen Canvas 2D celebration effect. One action kind with a pluggable `effect` parameter supporting multiple visual presets.
1035
1124
 
@@ -1251,15 +1340,7 @@ Control when adaptives activate using `DecisionStrategy`:
1251
1340
 
1252
1341
  ### 1. Choose the Right Action Type
1253
1342
 
1254
- | Goal | Action |
1255
- |------|--------|
1256
- | Change text | `set_text` |
1257
- | Add visual indicator | `badge`, `pulse` |
1258
- | Show help text | `tooltip` |
1259
- | Draw attention | `highlight` |
1260
- | Add content | `insert_html` |
1261
- | Navigate user | `scroll_to`, `navigate` |
1262
- | Show UI panel | `mount_widget` + Surfaces |
1343
+ Each adaptive package has a "When to use" guide at the top of its capabilities section above. Refer to those for action selection guidance.
1263
1344
 
1264
1345
  ### 2. Anchor Selection
1265
1346
 
@@ -1284,3 +1365,25 @@ Control when adaptives activate using `DecisionStrategy`:
1284
1365
  - Listen for `action.failed` to handle errors
1285
1366
  - Track `action.applied` for analytics
1286
1367
  - Use EventBus for cross-adaptive coordination
1368
+
1369
+ ### 6. Opening the Canvas from Inserted Content
1370
+
1371
+ When `content:insertHtml` needs to open the canvas panel (e.g., a "Help Me Choose" button that opens an FAQ tile), use the `deepLink` property — **never write `onclick` handlers or reference `window.SynOS` in HTML**.
1372
+
1373
+ ```json
1374
+ {
1375
+ "kind": "content:insertHtml",
1376
+ "anchorId": { "selector": "[data-id='pricing-heading']", "route": "/" },
1377
+ "html": "<button style='background: #4a90e2; color: white; border: none; padding: 8px 16px; border-radius: 20px; cursor: pointer;'>Help Me Choose</button>",
1378
+ "position": "after",
1379
+ "deepLink": { "tileId": "plan_selector_faq" }
1380
+ }
1381
+ ```
1382
+
1383
+ The `deepLink` object:
1384
+ - `tileId` (required) — ID of the canvas tile to navigate to
1385
+ - `itemId` (optional) — specific item within the tile (e.g., a FAQ question ID)
1386
+
1387
+ The SDK automatically opens the canvas, navigates to the tile, sets cursor to pointer, and wires up click/cleanup handlers.
1388
+
1389
+ **NEVER use `onclick`, `window.SynOS`, or any JavaScript in `content:insertHtml` HTML strings.** The HTML is sanitized and event handlers are stripped. Use `deepLink` instead.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Smart Canvas Runtime SDK
2
2
 
3
+ > Config is delivered via GrowthBook feature flags — discovered automatically, no hardcoded keys.
4
+
3
5
  ## Runtime SDK (React + Shadow DOM)
4
6
 
5
7
  The SDK ships a framework-agnostic `<smart-canvas>` custom element with an **open shadow root**. We render everything with React, but the canvas is encapsulated so host Tailwind configs, resets, or stacking contexts can't break the UI.
@@ -26592,4 +26592,4 @@ export declare const coreActionStepSchemas: ({
26592
26592
  }>]>>>;
26593
26593
  }, z.ZodTypeAny, "passthrough">>;
26594
26594
  })[];
26595
- export { AnchorIdZ, HighlightStyleZ, BadgePositionZ, PlacementZ, CtaButtonZ, TooltipContentZ, ModalContentZ, InsertPositionZ, TooltipTriggerZ, WidgetConfigZ, TourStepForSchemaZ, ScrollBehaviorZ, ScrollLogicalPositionZ, SetTextZ, SetAttrZ, AddClassZ, RemoveClassZ, SetStyleZ, InsertHtmlZ, HighlightZ, PulseZ, BadgeZ, TooltipZ, ModalZ, ScrollToZ, NavigateZ, MountWidgetZ, WaitZ, SequenceZ, ParallelZ, TourZ, };
26595
+ export { AddClassZ, AnchorIdZ, BadgePositionZ, BadgeZ, CtaButtonZ, HighlightStyleZ, HighlightZ, InsertHtmlZ, InsertPositionZ, ModalContentZ, ModalZ, MountWidgetZ, NavigateZ, ParallelZ, PlacementZ, PulseZ, RemoveClassZ, ScrollBehaviorZ, ScrollLogicalPositionZ, ScrollToZ, SequenceZ, SetAttrZ, SetStyleZ, SetTextZ, TooltipContentZ, TooltipTriggerZ, TooltipZ, TourStepForSchemaZ, TourZ, WaitZ, WidgetConfigZ, };