@syntrologie/runtime-sdk 1.0.1 → 2.0.0-canary.1

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 (122) hide show
  1. package/CAPABILITIES.md +630 -463
  2. package/README.md +285 -62
  3. package/dist/RuntimeProvider.d.ts +51 -0
  4. package/dist/RuntimeProvider.js +114 -0
  5. package/dist/RuntimeProvider.js.map +1 -0
  6. package/dist/SmartCanvasApp.d.ts +9 -3
  7. package/dist/SmartCanvasApp.js +36 -38
  8. package/dist/SmartCanvasApp.js.map +1 -1
  9. package/dist/actions/ActionEngine.d.ts +11 -0
  10. package/dist/actions/ActionEngine.js +274 -0
  11. package/dist/actions/ActionEngine.js.map +1 -0
  12. package/dist/actions/executors/index.d.ts +118 -0
  13. package/dist/actions/executors/index.js +242 -0
  14. package/dist/actions/executors/index.js.map +1 -0
  15. package/dist/actions/executors/tour.d.ts +18 -0
  16. package/dist/actions/executors/tour.js +332 -0
  17. package/dist/actions/executors/tour.js.map +1 -0
  18. package/dist/actions/index.d.ts +10 -0
  19. package/dist/actions/index.js +12 -0
  20. package/dist/actions/index.js.map +1 -0
  21. package/dist/actions/types.d.ts +399 -0
  22. package/dist/actions/types.js +8 -0
  23. package/dist/actions/types.js.map +1 -0
  24. package/dist/actions/validation.d.ts +14 -0
  25. package/dist/actions/validation.js +603 -0
  26. package/dist/actions/validation.js.map +1 -0
  27. package/dist/api.d.ts +32 -18
  28. package/dist/api.js +56 -39
  29. package/dist/api.js.map +1 -1
  30. package/dist/apps/AppContext.d.ts +31 -0
  31. package/dist/apps/AppContext.js +93 -0
  32. package/dist/apps/AppContext.js.map +1 -0
  33. package/dist/apps/AppLoader.d.ts +84 -0
  34. package/dist/apps/AppLoader.js +250 -0
  35. package/dist/apps/AppLoader.js.map +1 -0
  36. package/dist/apps/AppRegistry.d.ts +102 -0
  37. package/dist/apps/AppRegistry.js +317 -0
  38. package/dist/apps/AppRegistry.js.map +1 -0
  39. package/dist/apps/examples/gamification-app.example.d.ts +305 -0
  40. package/dist/apps/examples/gamification-app.example.js +329 -0
  41. package/dist/apps/examples/gamification-app.example.js.map +1 -0
  42. package/dist/apps/index.d.ts +18 -0
  43. package/dist/apps/index.js +26 -0
  44. package/dist/apps/index.js.map +1 -0
  45. package/dist/apps/types.d.ts +231 -0
  46. package/dist/apps/types.js +8 -0
  47. package/dist/apps/types.js.map +1 -0
  48. package/dist/bootstrap.d.ts +24 -0
  49. package/dist/bootstrap.js +133 -33
  50. package/dist/bootstrap.js.map +1 -1
  51. package/dist/components/ShadowCanvasOverlay.js +36 -9
  52. package/dist/components/ShadowCanvasOverlay.js.map +1 -1
  53. package/dist/components/TileCard.js +37 -18
  54. package/dist/components/TileCard.js.map +1 -1
  55. package/dist/context/schema.d.ts +16 -16
  56. package/dist/decisions/schema.d.ts +96 -96
  57. package/dist/earlyPatcher.d.ts +8 -20
  58. package/dist/earlyPatcher.js +13 -62
  59. package/dist/earlyPatcher.js.map +1 -1
  60. package/dist/editorLoader.d.ts +2 -0
  61. package/dist/editorLoader.js +46 -7
  62. package/dist/editorLoader.js.map +1 -1
  63. package/dist/events/normalizers/posthog.d.ts +24 -0
  64. package/dist/events/normalizers/posthog.js.map +1 -1
  65. package/dist/events/schema.d.ts +8 -8
  66. package/dist/events/types.d.ts +6 -0
  67. package/dist/events/types.js +8 -0
  68. package/dist/events/types.js.map +1 -1
  69. package/dist/hooks/useCanvasOverlays.d.ts +4 -1
  70. package/dist/hooks/useCanvasOverlays.js +53 -6
  71. package/dist/hooks/useCanvasOverlays.js.map +1 -1
  72. package/dist/hooks/useShadowCanvasConfig.d.ts +3 -7
  73. package/dist/hooks/useShadowCanvasConfig.js +2 -3
  74. package/dist/hooks/useShadowCanvasConfig.js.map +1 -1
  75. package/dist/index.d.ts +5 -0
  76. package/dist/index.js +10 -0
  77. package/dist/index.js.map +1 -1
  78. package/dist/overlays/schema.d.ts +153 -153
  79. package/dist/runtime.d.ts +24 -0
  80. package/dist/runtime.js +75 -1
  81. package/dist/runtime.js.map +1 -1
  82. package/dist/smart-canvas.esm.js +162 -55
  83. package/dist/smart-canvas.esm.js.map +4 -4
  84. package/dist/smart-canvas.js +21133 -17957
  85. package/dist/smart-canvas.js.map +4 -4
  86. package/dist/smart-canvas.min.js +162 -55
  87. package/dist/smart-canvas.min.js.map +4 -4
  88. package/dist/store/example.d.ts +1 -0
  89. package/dist/store/example.js +43 -0
  90. package/dist/store/example.js.map +1 -0
  91. package/dist/store/mini-effector.d.ts +46 -0
  92. package/dist/store/mini-effector.js +90 -0
  93. package/dist/store/mini-effector.js.map +1 -0
  94. package/dist/surfaces/Surfaces.d.ts +11 -0
  95. package/dist/surfaces/Surfaces.js +361 -0
  96. package/dist/surfaces/Surfaces.js.map +1 -0
  97. package/dist/surfaces/index.d.ts +9 -0
  98. package/dist/surfaces/index.js +12 -0
  99. package/dist/surfaces/index.js.map +1 -0
  100. package/dist/surfaces/positioning.d.ts +50 -0
  101. package/dist/surfaces/positioning.js +231 -0
  102. package/dist/surfaces/positioning.js.map +1 -0
  103. package/dist/surfaces/types.d.ts +167 -0
  104. package/dist/surfaces/types.js +23 -0
  105. package/dist/surfaces/types.js.map +1 -0
  106. package/dist/telemetry/adapters/posthog.d.ts +6 -0
  107. package/dist/telemetry/adapters/posthog.js +9 -0
  108. package/dist/telemetry/adapters/posthog.js.map +1 -1
  109. package/dist/types-only.d.ts +32 -0
  110. package/dist/types-only.js +11 -0
  111. package/dist/types-only.js.map +1 -0
  112. package/dist/types.d.ts +26 -14
  113. package/dist/types.js +1 -1
  114. package/dist/types.js.map +1 -1
  115. package/dist/widgets/WidgetRegistry.d.ts +139 -0
  116. package/dist/widgets/WidgetRegistry.js +182 -0
  117. package/dist/widgets/WidgetRegistry.js.map +1 -0
  118. package/dist/widgets/index.d.ts +7 -0
  119. package/dist/widgets/index.js +7 -0
  120. package/dist/widgets/index.js.map +1 -0
  121. package/package.json +13 -3
  122. package/schema/canvas-config.schema.json +444 -254
package/README.md CHANGED
@@ -2,19 +2,50 @@
2
2
 
3
3
  ## Smart Canvas SDK (React + Shadow DOM)
4
4
 
5
- The SDK now ships a framework-agnostic `<smart-canvas>` custom element with an **open shadow root**. We still render everything with React, but the canvas is encapsulated so host Tailwind configs, resets, or stacking contexts cant break the UI.
5
+ 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.
6
6
 
7
- ### Whats Included
7
+ ### What's Included
8
8
 
9
9
  - `SmartCanvasElement` – the custom element that owns the shadow DOM, overlay root, and controller.
10
10
  - `SmartCanvasApp` – the React tree (overlay, rectangles, toggle) you portal into the shadow.
11
11
  - `SmartCanvasPortal` – helper for React hosts to portal their tree (and context) into the element mount.
12
12
  - `createSmartCanvas` – imperative API (`window.SmartCanvas.create`) for non-React hosts.
13
+ - **ActionEngine** – unified execution layer for interventions (highlight, tooltip, badge, DOM modifications)
14
+ - **Surfaces** – managed surface system for rendering UI into named slots
13
15
  - GrowthBook/PostHog wrappers, hooks, rectangle components, and wheel remain available.
14
16
 
15
- ### Installation
17
+ ---
16
18
 
17
- #### NPM/Yarn
19
+ ## Quick Start
20
+
21
+ ```typescript
22
+ import { Syntro } from "@syntrologie/runtime-sdk";
23
+
24
+ const { runtime } = await Syntro.init({ token: "syn_..." });
25
+
26
+ // Change a headline
27
+ const handle = await runtime.actions.apply({
28
+ kind: "set_text",
29
+ anchorId: "h1.hero-title",
30
+ text: "Welcome to Our New Experience"
31
+ });
32
+
33
+ // Show a toast notification
34
+ const toast = runtime.surfaces.mount("toast_top", {
35
+ type: "html",
36
+ content: '<div class="toast">Changes applied!</div>'
37
+ });
38
+
39
+ // Later: revert and cleanup
40
+ await handle.revert();
41
+ toast.unmount();
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Installation
47
+
48
+ ### NPM/Yarn
18
49
 
19
50
  ```bash
20
51
  npm install @syntrologie/smart-canvas-sdk
@@ -22,7 +53,7 @@ npm install @syntrologie/smart-canvas-sdk
22
53
  yarn add @syntrologie/smart-canvas-sdk
23
54
  ```
24
55
 
25
- #### CDN
56
+ ### CDN
26
57
 
27
58
  For quick setup without a build process:
28
59
 
@@ -39,18 +70,96 @@ For quick setup without a build process:
39
70
  </script>
40
71
  ```
41
72
 
42
- #### Local Development
73
+ ### Local Development
43
74
 
44
75
  ```bash
45
- cd tech-core/sdks/shadow-canvas
76
+ cd tech-core/sdks/runtime-sdk
46
77
  npm run build
47
- cd ../../tax_landing_page
48
- npm install @syntrologie/smart-canvas-sdk@file:../tech-core/sdks/shadow-canvas
49
78
  ```
50
79
 
51
- Rebuild and reinstall whenever the SDK changes.
80
+ ---
81
+
82
+ ## Core Modules
83
+
84
+ ### ActionEngine
85
+
86
+ The ActionEngine provides a unified API for applying reversible interventions:
87
+
88
+ ```typescript
89
+ // Visual actions
90
+ await runtime.actions.apply({ kind: "highlight", anchorId: "#cta", style: { color: "#4f46e5" } });
91
+ await runtime.actions.apply({ kind: "tooltip", anchorId: "#help", content: { body: "Click for help" } });
92
+ await runtime.actions.apply({ kind: "badge", anchorId: "#inbox", content: "3" });
93
+ await runtime.actions.apply({ kind: "pulse", anchorId: "#notification" });
94
+
95
+ // DOM actions
96
+ await runtime.actions.apply({ kind: "set_text", anchorId: "h1", text: "New headline" });
97
+ await runtime.actions.apply({ kind: "insert_html", anchorId: ".cta", html: "<span>NEW</span>", position: "append" });
98
+ await runtime.actions.apply({ kind: "add_class", anchorId: ".card", className: "highlighted" });
99
+ await runtime.actions.apply({ kind: "set_style", anchorId: ".hero", styles: { "background": "#1e40af" } });
100
+
101
+ // Navigation actions
102
+ await runtime.actions.apply({ kind: "scroll_to", anchorId: "#pricing" });
103
+ await runtime.actions.apply({ kind: "navigate", url: "/signup" });
104
+
105
+ // Batch with atomic rollback
106
+ const batch = await runtime.actions.applyBatch([
107
+ { kind: "set_text", anchorId: "h1", text: "New" },
108
+ { kind: "highlight", anchorId: "h1" }
109
+ ]);
110
+ await batch.revertAll();
111
+ ```
112
+
113
+ ### Surfaces
52
114
 
53
- ### Using the Custom Element (React Host)
115
+ The Surfaces system manages UI rendering into named slots:
116
+
117
+ ```typescript
118
+ // Static slots
119
+ runtime.surfaces.mount("toast_top", { type: "html", content: "<div>Saved!</div>" });
120
+ runtime.surfaces.mount("drawer_right", { type: "html", content: "<div>Settings</div>" });
121
+ runtime.surfaces.mount("overlay_center", { type: "html", content: "<div>Modal</div>" });
122
+
123
+ // Dynamic slots (positioned relative to anchors)
124
+ runtime.surfaces.mount("inline:product-card", { type: "html", content: "<span>SALE</span>" });
125
+ runtime.surfaces.mount("adjacent:help-icon", { type: "html", content: "<div>Help text</div>" }, {
126
+ position: { placement: "bottom" }
127
+ });
128
+
129
+ // Priority-based arbitration
130
+ runtime.surfaces.mount("toast_top", content, { priority: 10 }); // Higher priority wins
131
+ ```
132
+
133
+ **Available Static Slots:**
134
+ | Slot | Position |
135
+ |------|----------|
136
+ | `drawer_right` | Right edge, full height |
137
+ | `drawer_left` | Left edge, full height |
138
+ | `drawer_bottom` | Bottom edge, full width |
139
+ | `overlay_center` | Centered modal |
140
+ | `overlay_corner_br` | Bottom-right corner |
141
+ | `overlay_corner_bl` | Bottom-left corner |
142
+ | `toast_top` | Top center |
143
+ | `toast_bottom` | Bottom center |
144
+
145
+ ### Runtime
146
+
147
+ The runtime provides access to all core providers:
148
+
149
+ ```typescript
150
+ const { runtime } = await Syntro.init({ token: "syn_..." });
151
+
152
+ runtime.telemetry // Event tracking (PostHog)
153
+ runtime.context // Page/session/viewport state
154
+ runtime.events // Normalized event stream
155
+ runtime.state // Persistent storage
156
+ runtime.actions // ActionEngine
157
+ runtime.surfaces // Surfaces
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Using the Custom Element (React Host)
54
163
 
55
164
  ```tsx
56
165
  import {
@@ -90,7 +199,9 @@ function SmartCanvasBridge() {
90
199
  }
91
200
  ```
92
201
 
93
- ### Using the Imperative API (Plain JS Host)
202
+ ---
203
+
204
+ ## Using the Imperative API (Plain JS Host)
94
205
 
95
206
  When using via CDN, the SDK is available as `window.SyntrologieSDK`:
96
207
 
@@ -109,77 +220,189 @@ await window.SmartCanvas?.create({
109
220
  });
110
221
  ```
111
222
 
112
- ### Styling & Overlays
223
+ ---
113
224
 
114
- - Fonts, colors, and CSS variables (`--sc-surface`, `--sc-fg`, etc.) are inherited from the host. Tokens can be overridden via `setTokens` or standard CSS:
115
- - `--syntro-tooltip-bg`, `--syntro-tooltip-fg`, `--syntro-tooltip-radius`, `--syntro-tooltip-shadow`
116
- - `--syntro-ring`, `--syntro-spotlight-backdrop` for highlights
117
- - A scoped reset is injected via `adoptedStyleSheets` (fallbacks to `<style>`).
118
- - Tooltips/popovers should use the Popover API or Floating UI with the exposed overlay root (`element.getOverlayRoot()`).
225
+ ## Event System
119
226
 
120
- ### Analytics Events
227
+ The EventBus provides a unified stream of normalized events:
121
228
 
122
- The `createSyntroTelemetry` client emits:
229
+ ```typescript
230
+ // Subscribe to events
231
+ runtime.events.subscribe({ names: ["ui.click", "action.applied"] }, (event) => {
232
+ console.log(event.name, event.props);
233
+ });
123
234
 
124
- | Event | Description |
125
- | --- | --- |
126
- | `shadow_canvas_opened` / `shadow_canvas_closed` | Toggle button interactions. |
127
- | `shadow_canvas_rectangle_viewed` | A rectangle becomes visible (overlay grid & wheel). |
128
- | `shadow_canvas_action` | CTA click, chatbot send, overlay events (tooltips, dismiss, anchor missing). |
235
+ // Standard events
236
+ // UI: ui.click, ui.scroll, ui.input, ui.submit
237
+ // Navigation: nav.page_view, nav.page_leave
238
+ // Canvas: canvas.opened, canvas.closed, tile.viewed, tile.action
239
+ // Actions: action.applied, action.reverted, action.failed
240
+ // Surfaces: surface.mounted, surface.unmounted
241
+ ```
129
242
 
130
- ### Rectangle Config (unchanged)
243
+ ---
131
244
 
132
- The experimentation service still returns the same payload (`rectangles`, `style`, `content`, optional `experiment` metadata). Top-level fields now include optional `canvasTitle` so host teams can rename the overlay without code changes. See `src/types.ts` for the exact contract.
245
+ ## State Management
133
246
 
134
- ### Schema & Validation Tool
247
+ ```typescript
248
+ // Dismissals
249
+ runtime.state.dismissals.mark("promo-banner");
250
+ if (runtime.state.dismissals.isDismissed("promo-banner")) { ... }
135
251
 
136
- - JSON schema lives at `schema/canvas-config.schema.json` (published with the package).
137
- - Validate a config file locally:
252
+ // Cooldowns
253
+ runtime.state.cooldowns.set("upsell", 86400000); // 24h
254
+ if (runtime.state.cooldowns.isActive("upsell")) { ... }
138
255
 
139
- ```bash
140
- cd tech-core/sdks/shadow-canvas
141
- npm run validate-config -- ../../tax_landing_page/public/smart-canvas-demo.json
256
+ // Frequency caps
257
+ runtime.state.frequency.increment("tooltip-shown");
258
+ if (runtime.state.frequency.count("tooltip-shown") >= 3) { ... }
142
259
  ```
143
260
 
144
- The script evaluates structure/required fields without third-party dependencies so CI and content authors can catch issues early.
261
+ ---
262
+
263
+ ## Decision Strategies
264
+
265
+ Control when adaptives activate:
266
+
267
+ ```typescript
268
+ const result = runtime.evaluateSync({
269
+ type: "rules",
270
+ rules: [
271
+ {
272
+ conditions: [
273
+ { type: "page_url", pattern: "/pricing*" },
274
+ { type: "viewport", minWidth: 768 },
275
+ { type: "dismissed", key: "promo", inverted: true }
276
+ ],
277
+ value: true
278
+ }
279
+ ],
280
+ default: false
281
+ });
282
+
283
+ if (result.value) {
284
+ // Apply adaptive
285
+ }
286
+ ```
287
+
288
+ ---
289
+
290
+ ## Styling & Overlays
145
291
 
146
- ### Overlays (Tooltips & Highlights)
292
+ - Fonts, colors, and CSS variables are inherited from the host
293
+ - Tokens can be overridden via `setTokens` or standard CSS:
294
+ - `--syntro-tooltip-bg`, `--syntro-tooltip-fg`, `--syntro-tooltip-radius`
295
+ - `--syntro-ring`, `--syntro-spotlight-backdrop` for highlights
296
+ - A scoped reset is injected via `adoptedStyleSheets`
297
+
298
+ ---
299
+
300
+ ## Schema & Validation
301
+
302
+ - JSON schema lives at `schema/canvas-config.schema.json`
303
+ - Validate a config file locally:
304
+
305
+ ```bash
306
+ cd tech-core/sdks/runtime-sdk
307
+ npm run validate-config -- path/to/config.json
308
+ ```
147
309
 
148
- - Recipes use the schema in `src/overlays/schema.ts` (roughly `{ id, version, steps[] }`).
149
- - Provide a recipe URI via `overlayConfigUri` or let GrowthBook supply `smart-canvas-overlay-uri`.
150
- - Overlays render in `#syntro-overlays` (fixed, pointer-events: none) and use Floating UI for tethering.
151
- - The Canvas runtime dynamically imports the overlay chunk only when a recipe resolves.
152
- - Exposed helpers:
153
- - `createOverlayRecipeFetcher`, `resolveConfigUri`
154
- - `runOverlays`, `showTooltip`, `showHighlight`
155
- - `createAnchorResolver` (works for main DOM + shadow DOM)
310
+ ---
156
311
 
157
- Telemetry for overlays uses `telemetry.trackAction("syntro_overlay_*", stepId, "overlay")`.
312
+ ## Documentation
158
313
 
159
- ### Testing
314
+ - **[APPS.md](./APPS.md)** - App architecture: how to build runtime extensions with actions, schemas, and editor modules
315
+ - **[CAPABILITIES.md](./CAPABILITIES.md)** - Complete reference for all actions, surfaces, and config options
316
+ - **[RUNTIME_V2_REFERENCE.md](./RUNTIME_V2_REFERENCE.md)** - Context, Events, State, Decisions modules
160
317
 
161
- - Shadow root is **open**, so Playwright/Cypress can traverse via `.shadow()`.
162
- - Data hooks: `[data-shadow-canvas-id="overlay-launcher"]`, `[data-shadow-canvas-id="rectangle-${id}"]`, etc.
163
- - `SmartCanvasController` exposes `open/close` for deterministic tests.
318
+ ---
164
319
 
165
- ### Directory Overview
320
+ ## Directory Overview
166
321
 
167
322
  ```
168
- tech-core/sdks/shadow-canvas
323
+ tech-core/sdks/runtime-sdk
169
324
  ├─ src
170
- │ ├─ SmartCanvasElement.tsx // custom element + controller glue
171
- │ ├─ SmartCanvasApp.tsx // React UI
172
- │ ├─ SmartCanvasPortal.tsx // portal helper
173
- │ ├─ api.tsx // window.SmartCanvas + imperative API
174
- ├─ analytics/, experiments/, hooks/, components/
175
- └─ controller.ts
325
+ │ ├─ actions/ # ActionEngine (interventions)
326
+ ├─ types.ts
327
+ ├─ ActionEngine.ts
328
+ ├─ validation.ts
329
+ │ └─ executors/ # visual, dom, navigation executors
330
+ ├─ apps/ # App system (see APPS.md)
331
+ │ │ ├─ AppRegistry.ts # App registration and lifecycle
332
+ │ │ ├─ AppLoader.ts # Dynamic app loading
333
+ │ │ ├─ types.ts # AppManifest, AppContext types
334
+ │ │ └─ built-in/ # Core apps (bundled with runtime)
335
+ │ ├─ surfaces/ # Surfaces (UI rendering)
336
+ │ │ ├─ types.ts
337
+ │ │ ├─ Surfaces.ts
338
+ │ │ └─ positioning.ts
339
+ │ ├─ context/ # Page/session/viewport state
340
+ │ ├─ events/ # EventBus
341
+ │ ├─ state/ # StateStore
342
+ │ ├─ decisions/ # DecisionStrategy evaluation
343
+ │ ├─ runtime.ts # SmartCanvasRuntime factory
344
+ │ ├─ bootstrap.ts # Syntro.init()
345
+ │ ├─ SmartCanvasElement.tsx
346
+ │ ├─ SmartCanvasApp.tsx
347
+ │ └─ SmartCanvasPortal.tsx
348
+ ├─ schema/
349
+ │ └─ canvas-config.schema.json
350
+ ├─ APPS.md
351
+ ├─ CAPABILITIES.md
352
+ ├─ RUNTIME_V2_REFERENCE.md
176
353
  └─ README.md
177
354
  ```
178
355
 
179
- ### Quick Checklist
356
+ ---
180
357
 
181
- 1. Call `registerSmartCanvasElement()` once per app.
182
- 2. Render `<smart-canvas>` (custom element).
183
- 3. Portal your React tree into the element’s shadow via `SmartCanvasPortal`.
184
- 4. Configure the SDK with your API credentials.
185
- 5. For non-React pages, call `window.SmartCanvas.create()` with configuration.
358
+ ## Development Commands
359
+
360
+ ```bash
361
+ # Build TypeScript library
362
+ npm run build:lib
363
+
364
+ # Build CDN bundle
365
+ npm run build:cdn
366
+
367
+ # Full build
368
+ npm run build
369
+
370
+ # Validate a config file
371
+ npm run validate-config -- path/to/config.json
372
+
373
+ # Type check
374
+ npx tsc --noEmit
375
+ ```
376
+
377
+ ---
378
+
379
+ ## Testing
380
+
381
+ - Shadow root is **open**, so Playwright/Cypress can traverse via `.shadow()`
382
+ - Data hooks: `[data-shadow-canvas-id="overlay-launcher"]`, `[data-shadow-canvas-id="rectangle-${id}"]`
383
+ - `SmartCanvasController` exposes `open/close` for deterministic tests
384
+
385
+ ---
386
+
387
+ ## Analytics Events
388
+
389
+ The telemetry client emits:
390
+
391
+ | Event | Description |
392
+ | --- | --- |
393
+ | `shadow_canvas_opened` / `shadow_canvas_closed` | Toggle button interactions |
394
+ | `shadow_canvas_rectangle_viewed` | A rectangle becomes visible |
395
+ | `shadow_canvas_action` | CTA click, chatbot send, overlay events |
396
+ | `action.applied` / `action.reverted` | ActionEngine events |
397
+ | `surface.mounted` / `surface.unmounted` | Surfaces events |
398
+
399
+ ---
400
+
401
+ ## Quick Checklist
402
+
403
+ 1. Call `registerSmartCanvasElement()` once per app
404
+ 2. Render `<smart-canvas>` (custom element)
405
+ 3. Portal your React tree into the element's shadow via `SmartCanvasPortal`
406
+ 4. Configure the SDK with your API credentials
407
+ 5. Use `runtime.actions` for interventions, `runtime.surfaces` for UI
408
+ 6. For non-React pages, call `window.SmartCanvas.create()` with configuration
@@ -0,0 +1,51 @@
1
+ /**
2
+ * RuntimeProvider - React context for accessing the v2 Runtime.
3
+ *
4
+ * Provides access to the SmartCanvasRuntime from any component in the tree.
5
+ */
6
+ import { ReactNode } from "react";
7
+ import type { SmartCanvasRuntime } from "./runtime";
8
+ import type { RuntimeContext } from "./context/types";
9
+ export interface RuntimeProviderProps {
10
+ /** The SmartCanvasRuntime instance */
11
+ runtime: SmartCanvasRuntime | null;
12
+ children: ReactNode;
13
+ }
14
+ /**
15
+ * Provider component for the SmartCanvasRuntime.
16
+ */
17
+ export declare function RuntimeProvider({ runtime, children }: RuntimeProviderProps): import("react/jsx-runtime").JSX.Element;
18
+ /**
19
+ * Hook to access the SmartCanvasRuntime.
20
+ */
21
+ export declare function useRuntime(): SmartCanvasRuntime | null;
22
+ /**
23
+ * Hook to access the current runtime context (reactive).
24
+ */
25
+ export declare function useRuntimeContext(): RuntimeContext | null;
26
+ /**
27
+ * Hook to access a specific part of the runtime context.
28
+ */
29
+ export declare function usePageContext(): import("./context").PageContext | null;
30
+ export declare function useSessionContext(): import("./context").SessionContext | null;
31
+ export declare function useViewportContext(): import("./context").ViewportContext | null;
32
+ /**
33
+ * Hook to subscribe to runtime events.
34
+ */
35
+ export declare function useRuntimeEvents(filter: {
36
+ names?: string[];
37
+ patterns?: string[];
38
+ sources?: Array<"posthog" | "canvas" | "derived">;
39
+ } | undefined, callback: (event: import("./events/types").NormalizedEvent) => void, deps?: React.DependencyList): void;
40
+ /**
41
+ * Hook to access state helpers.
42
+ */
43
+ export declare function useRuntimeState(): import("./state").StateStore | null;
44
+ /**
45
+ * Hook to evaluate a decision strategy.
46
+ */
47
+ export declare function useDecision<T>(strategy: import("./decisions/types").DecisionStrategy<T> | undefined | null, defaultValue: T): {
48
+ value: T;
49
+ isFallback: boolean;
50
+ isLoading: boolean;
51
+ };
@@ -0,0 +1,114 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * RuntimeProvider - React context for accessing the v2 Runtime.
4
+ *
5
+ * Provides access to the SmartCanvasRuntime from any component in the tree.
6
+ */
7
+ import { createContext, useContext, useMemo, useEffect, useState } from "react";
8
+ const RuntimeReactContext = createContext({
9
+ runtime: null,
10
+ context: null,
11
+ });
12
+ /**
13
+ * Provider component for the SmartCanvasRuntime.
14
+ */
15
+ export function RuntimeProvider({ runtime, children }) {
16
+ // Subscribe to context changes and re-render when they occur
17
+ const [context, setContext] = useState(runtime ? runtime.context.get() : null);
18
+ useEffect(() => {
19
+ if (!runtime)
20
+ return;
21
+ // Set initial context
22
+ setContext(runtime.context.get());
23
+ // Subscribe to changes
24
+ const unsubscribe = runtime.context.subscribe((ctx) => {
25
+ setContext(ctx);
26
+ });
27
+ return unsubscribe;
28
+ }, [runtime]);
29
+ const value = useMemo(() => ({ runtime, context }), [runtime, context]);
30
+ return (_jsx(RuntimeReactContext.Provider, { value: value, children: children }));
31
+ }
32
+ /**
33
+ * Hook to access the SmartCanvasRuntime.
34
+ */
35
+ export function useRuntime() {
36
+ const { runtime } = useContext(RuntimeReactContext);
37
+ return runtime;
38
+ }
39
+ /**
40
+ * Hook to access the current runtime context (reactive).
41
+ */
42
+ export function useRuntimeContext() {
43
+ const { context } = useContext(RuntimeReactContext);
44
+ return context;
45
+ }
46
+ /**
47
+ * Hook to access a specific part of the runtime context.
48
+ */
49
+ export function usePageContext() {
50
+ var _a;
51
+ const context = useRuntimeContext();
52
+ return (_a = context === null || context === void 0 ? void 0 : context.page) !== null && _a !== void 0 ? _a : null;
53
+ }
54
+ export function useSessionContext() {
55
+ var _a;
56
+ const context = useRuntimeContext();
57
+ return (_a = context === null || context === void 0 ? void 0 : context.session) !== null && _a !== void 0 ? _a : null;
58
+ }
59
+ export function useViewportContext() {
60
+ var _a;
61
+ const context = useRuntimeContext();
62
+ return (_a = context === null || context === void 0 ? void 0 : context.viewport) !== null && _a !== void 0 ? _a : null;
63
+ }
64
+ /**
65
+ * Hook to subscribe to runtime events.
66
+ */
67
+ export function useRuntimeEvents(filter, callback, deps = []) {
68
+ const runtime = useRuntime();
69
+ useEffect(() => {
70
+ if (!runtime)
71
+ return;
72
+ const unsubscribe = filter
73
+ ? runtime.events.subscribe(filter, callback)
74
+ : runtime.events.subscribe(callback);
75
+ return unsubscribe;
76
+ // eslint-disable-next-line react-hooks/exhaustive-deps
77
+ }, [runtime, ...deps]);
78
+ }
79
+ /**
80
+ * Hook to access state helpers.
81
+ */
82
+ export function useRuntimeState() {
83
+ var _a;
84
+ const runtime = useRuntime();
85
+ return (_a = runtime === null || runtime === void 0 ? void 0 : runtime.state) !== null && _a !== void 0 ? _a : null;
86
+ }
87
+ /**
88
+ * Hook to evaluate a decision strategy.
89
+ */
90
+ export function useDecision(strategy, defaultValue) {
91
+ const runtime = useRuntime();
92
+ const [result, setResult] = useState({
93
+ value: defaultValue,
94
+ isFallback: true,
95
+ isLoading: true,
96
+ });
97
+ useEffect(() => {
98
+ if (!runtime || !strategy) {
99
+ setResult({ value: defaultValue, isFallback: true, isLoading: false });
100
+ return;
101
+ }
102
+ let cancelled = false;
103
+ runtime.evaluate(strategy).then((res) => {
104
+ if (!cancelled) {
105
+ setResult({ value: res.value, isFallback: res.isFallback, isLoading: false });
106
+ }
107
+ });
108
+ return () => {
109
+ cancelled = true;
110
+ };
111
+ }, [runtime, strategy, defaultValue]);
112
+ return result;
113
+ }
114
+ //# sourceMappingURL=RuntimeProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RuntimeProvider.js","sourceRoot":"","sources":["../src/RuntimeProvider.tsx"],"names":[],"mappings":"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"}
@@ -3,9 +3,9 @@ import { SmartCanvasController } from "./controller";
3
3
  import type { CanvasConfigFetcher } from "./types";
4
4
  import type { ExperimentClient } from "./experiments/types";
5
5
  import type { TelemetryClient } from "./telemetry/types";
6
- import type { OverlayRecipeFetcher } from "./overlays/fetcher";
7
6
  import { MountableComponent } from "./api";
8
7
  import { CanvasTheme } from "./components/ShadowCanvasOverlay";
8
+ import type { SmartCanvasRuntime } from "./runtime";
9
9
  export interface SmartCanvasAppProps {
10
10
  controller: SmartCanvasController;
11
11
  fetcher?: CanvasConfigFetcher;
@@ -16,9 +16,15 @@ export interface SmartCanvasAppProps {
16
16
  pollIntervalMs?: number;
17
17
  experiments?: ExperimentClient;
18
18
  telemetry?: TelemetryClient;
19
- overlayFetcher?: OverlayRecipeFetcher;
19
+ /** v2 Runtime instance for context, events, state, and decisions */
20
+ runtime?: SmartCanvasRuntime;
21
+ /** @deprecated Actions replace overlay recipes. Use config.actions instead. */
22
+ overlayFetcher?: () => Promise<unknown>;
23
+ /** @deprecated Actions replace overlay recipes. Use config.actions instead. */
20
24
  overlayConfigUri?: string;
25
+ /** @deprecated Actions replace overlay recipes. Use config.actions instead. */
21
26
  overlayConfigFeatureKey?: string;
27
+ /** @deprecated Actions replace overlay recipes. Use config.actions instead. */
22
28
  overlayFetchCredentials?: RequestCredentials;
23
29
  footerSlot?: ReactNode;
24
30
  launcherLabel?: string;
@@ -26,4 +32,4 @@ export interface SmartCanvasAppProps {
26
32
  customRenderers?: Record<string, MountableComponent>;
27
33
  theme?: Partial<CanvasTheme>;
28
34
  }
29
- export declare function SmartCanvasApp({ controller, fetcher, configUri, configUriFeatureKey, configFeatureKey, fetchCredentials, pollIntervalMs, experiments, telemetry, overlayFetcher, overlayConfigUri, overlayConfigFeatureKey, overlayFetchCredentials, footerSlot, launcherLabel, canvasHost, customRenderers, theme, }: SmartCanvasAppProps): import("react/jsx-runtime").JSX.Element | null;
35
+ export declare function SmartCanvasApp({ controller, fetcher, configUri, configUriFeatureKey, configFeatureKey, fetchCredentials, pollIntervalMs, experiments, telemetry, runtime, overlayFetcher, overlayConfigUri, overlayConfigFeatureKey, overlayFetchCredentials, footerSlot, launcherLabel, canvasHost, customRenderers, theme, }: SmartCanvasAppProps): import("react/jsx-runtime").JSX.Element;