@syntrologie/runtime-sdk 2.8.0-canary.4 → 2.8.0-canary.41

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 (45) hide show
  1. package/CAPABILITIES.md +44 -0
  2. package/dist/actions/schema.d.ts +1 -1
  3. package/dist/actions/schema.js +1 -1
  4. package/dist/actions/validation-core.d.ts +24 -0
  5. package/dist/actions/validation-rules.d.ts +74 -0
  6. package/dist/actions/validation.d.ts +5 -11
  7. package/dist/bootstrap-init.d.ts +33 -0
  8. package/dist/bootstrap-runtime.d.ts +7 -0
  9. package/dist/bootstrap-types.d.ts +90 -0
  10. package/dist/bootstrap.d.ts +17 -83
  11. package/dist/{chunk-R5DNAIRI.js → chunk-TN5BLBPU.js} +1 -1
  12. package/dist/{chunk-R5DNAIRI.js.map → chunk-TN5BLBPU.js.map} +1 -1
  13. package/dist/{chunk-5GTCL2IH.js → chunk-X2XEU6KD.js} +1506 -599
  14. package/dist/chunk-X2XEU6KD.js.map +7 -0
  15. package/dist/components/TileIcon.d.ts +2 -2
  16. package/dist/components/emojiToIcon.d.ts +24 -0
  17. package/dist/events/EventBus.d.ts +27 -1
  18. package/dist/events/history.d.ts +9 -0
  19. package/dist/events/index.d.ts +3 -0
  20. package/dist/events/normalizers/posthog.d.ts +4 -50
  21. package/dist/events/types.d.ts +30 -23
  22. package/dist/events/validation.d.ts +7 -0
  23. package/dist/index.d.ts +0 -2
  24. package/dist/index.js +1523 -182
  25. package/dist/index.js.map +4 -4
  26. package/dist/overlays/runtime/overlay/overlay-runner.d.ts +4 -0
  27. package/dist/overlays/runtime/overlay/overlay-state.d.ts +21 -0
  28. package/dist/overlays/types.d.ts +3 -1
  29. package/dist/react.js +4 -2
  30. package/dist/react.js.map +2 -2
  31. package/dist/smart-canvas.esm.js +123 -54
  32. package/dist/smart-canvas.esm.js.map +4 -4
  33. package/dist/smart-canvas.js +5650 -2964
  34. package/dist/smart-canvas.js.map +4 -4
  35. package/dist/smart-canvas.min.js +123 -54
  36. package/dist/smart-canvas.min.js.map +4 -4
  37. package/dist/telemetry/adapters/posthog.d.ts +30 -4
  38. package/dist/test/setup.d.ts +1 -0
  39. package/dist/token.d.ts +2 -0
  40. package/dist/version.d.ts +1 -1
  41. package/package.json +23 -28
  42. package/schema/canvas-config.schema.json +100 -2
  43. package/scripts/syntroReactPlugin.mjs +3 -0
  44. package/scripts/validate-config.mjs +42 -0
  45. package/dist/chunk-5GTCL2IH.js.map +0 -7
@@ -32,10 +32,12 @@ export interface PostHogAdapterOptions {
32
32
  */
33
33
  sessionRecording?: boolean;
34
34
  /**
35
- * Enable pageview capture.
36
- * @default true
35
+ * Pageview capture mode.
36
+ * - true: capture only on initial page load
37
+ * - 'history_change': auto-capture on SPA navigation (pushState/replaceState)
38
+ * @default "history_change"
37
39
  */
38
- capturePageview?: boolean;
40
+ capturePageview?: boolean | 'history_change';
39
41
  /**
40
42
  * Enable page leave capture.
41
43
  * @default true
@@ -71,6 +73,18 @@ export interface PostHogAdapterOptions {
71
73
  * @default false
72
74
  */
73
75
  requireExplicitConsent?: boolean;
76
+ /**
77
+ * Enable behavioral signal detection (hesitation, rage click, etc.)
78
+ * Pass `true` for defaults, or a partial DetectorConfig to customize thresholds.
79
+ * @default false
80
+ */
81
+ behavioralSignals?: boolean | Record<string, number>;
82
+ /**
83
+ * Callback for raw rrweb events from session recording.
84
+ * Called with each rrweb eventWithTime before PostHog processes it.
85
+ * Used by the event processor for behavioral signal detection.
86
+ */
87
+ onRRWebEvent?: (event: Record<string, unknown>) => void;
74
88
  }
75
89
  interface CanvasAnalyticsPayload extends Properties {
76
90
  rectangleId?: string;
@@ -84,13 +98,25 @@ export declare class PostHogAdapter implements TelemetryClient {
84
98
  private client?;
85
99
  private featureFlagsCallback?;
86
100
  private captureCallback?;
87
- private consentUnsub?;
101
+ private rrwebCallback?;
88
102
  constructor(options?: PostHogAdapterOptions);
89
103
  /**
90
104
  * Initialize the PostHog client. Called immediately (no consent gate)
91
105
  * or deferred (when consent gate grants).
92
106
  */
93
107
  private initPostHog;
108
+ /**
109
+ * Set up rrweb event interception on PostHog's session recording.
110
+ *
111
+ * PostHog lazy-loads the rrweb recorder. The SessionRecording wrapper has
112
+ * an `onRRwebEmit` method, but rrweb delivers events directly to the
113
+ * lazy-loaded recorder instance's `onRRwebEmit`, bypassing the wrapper.
114
+ * We must find and patch the recorder instance, not the wrapper.
115
+ *
116
+ * The recorder instance is stored on a minified property of SessionRecording.
117
+ * We detect it by looking for an object with both `onRRwebEmit` and `start` methods.
118
+ */
119
+ private setupRRWebIntercept;
94
120
  /**
95
121
  * Get all feature flags from PostHog.
96
122
  * Used to extract segment membership flags (in_segment_*).
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom/vitest';
package/dist/token.d.ts CHANGED
@@ -20,6 +20,8 @@ export interface SyntroTokenPayload {
20
20
  f?: string;
21
21
  /** Fetcher-specific options (e.g., configId for cdn fetcher) */
22
22
  o?: Record<string, string>;
23
+ /** Geo worker URL (e.g., "https://dev-geo.syntrologie.com" for dev) */
24
+ g?: string;
23
25
  /** Debug mode - enables console logging (default: false) */
24
26
  d?: boolean;
25
27
  }
package/dist/version.d.ts CHANGED
@@ -10,4 +10,4 @@
10
10
  *
11
11
  * @since 2.0.0
12
12
  */
13
- export declare const SDK_VERSION = "2.8.0-canary.4";
13
+ export declare const SDK_VERSION = "2.8.0-canary.41";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syntrologie/runtime-sdk",
3
- "version": "2.8.0-canary.4",
3
+ "version": "2.8.0-canary.41",
4
4
  "description": "Syntrologie Runtime SDK for web experimentation and analytics",
5
5
  "license": "Proprietary",
6
6
  "private": false,
@@ -61,21 +61,16 @@
61
61
  "validate-config": "node ./scripts/validate-config.mjs",
62
62
  "typecheck": "tsc --noEmit -p tsconfig.build.json",
63
63
  "test": "vitest run",
64
- "prepublishOnly": "npm run clean && npm run build"
64
+ "strip-internal-deps": "node ./scripts/strip-internal-deps.mjs",
65
+ "prepublishOnly": "npm run clean && npm run build && npm run strip-internal-deps"
65
66
  },
66
67
  "dependencies": {
67
- "@floating-ui/dom": "^1.7.5",
68
+ "@floating-ui/dom": "1.7.5",
68
69
  "@growthbook/growthbook": "~1.6.2",
69
- "@growthbook/growthbook-react": "^1.6.4",
70
- "@syntrologie/adapt-chatbot": "2.8.0-canary.4",
71
- "@syntrologie/adapt-content": "2.8.0-canary.4",
72
- "@syntrologie/adapt-faq": "2.8.0-canary.4",
73
- "@syntrologie/adapt-gamification": "2.8.0-canary.4",
74
- "@syntrologie/adapt-nav": "2.8.0-canary.4",
75
- "@syntrologie/adapt-overlays": "2.8.0-canary.4",
76
- "lucide-react": "^0.576.0",
77
- "posthog-js": "~1.302.2",
78
- "zod": "^3.25.76"
70
+ "@growthbook/growthbook-react": "1.6.4",
71
+ "lucide-react": "0.576.0",
72
+ "posthog-js": "1.341.0",
73
+ "zod": "3.25.76"
79
74
  },
80
75
  "peerDependencies": {
81
76
  "react": ">=18.0.0",
@@ -86,21 +81,21 @@
86
81
  "@semantic-release/github": "~12.0.3",
87
82
  "@semantic-release/npm": "~13.1.3",
88
83
  "@syntro/design-system": "*",
89
- "@testing-library/dom": "^10.4.1",
90
- "@testing-library/jest-dom": "^6.9.1",
91
- "@testing-library/react": "^16.3.2",
92
- "@types/node": "^22.19.7",
93
- "@types/react": "^19.2.0",
94
- "@types/react-dom": "^19.2.0",
95
- "ajv": "^8.18.0",
96
- "ajv-formats": "^3.0.1",
97
- "esbuild": "^0.27.2",
98
- "jsdom": "^26.1.0",
99
- "react": "^19.2.0",
100
- "react-dom": "^19.2.0",
84
+ "@testing-library/dom": "10.4.1",
85
+ "@testing-library/jest-dom": "6.9.1",
86
+ "@testing-library/react": "16.3.2",
87
+ "@types/node": "22.19.7",
88
+ "@types/react": "19.2.14",
89
+ "@types/react-dom": "19.2.3",
90
+ "ajv": "8.18.0",
91
+ "ajv-formats": "3.0.1",
92
+ "esbuild": "0.27.2",
93
+ "jsdom": "26.1.0",
94
+ "react": "19.2.1",
95
+ "react-dom": "19.2.1",
101
96
  "semantic-release": "~25.0.3",
102
- "typescript": "^5.9.3",
103
- "vitest": "^4.0.18",
104
- "zod-to-json-schema": "^3.25.1"
97
+ "typescript": "5.9.3",
98
+ "vitest": "4.0.18",
99
+ "zod-to-json-schema": "3.25.1"
105
100
  }
106
101
  }
@@ -11071,7 +11071,30 @@
11071
11071
  ]
11072
11072
  },
11073
11073
  "anchorId": {
11074
- "type": "string"
11074
+ "type": "object",
11075
+ "properties": {
11076
+ "selector": {
11077
+ "type": "string"
11078
+ },
11079
+ "route": {
11080
+ "anyOf": [
11081
+ {
11082
+ "type": "string"
11083
+ },
11084
+ {
11085
+ "type": "array",
11086
+ "items": {
11087
+ "type": "string"
11088
+ }
11089
+ }
11090
+ ]
11091
+ }
11092
+ },
11093
+ "required": [
11094
+ "selector",
11095
+ "route"
11096
+ ],
11097
+ "additionalProperties": false
11075
11098
  }
11076
11099
  },
11077
11100
  "required": [
@@ -11091,7 +11114,30 @@
11091
11114
  "type": "string"
11092
11115
  },
11093
11116
  "anchorId": {
11094
- "type": "string"
11117
+ "type": "object",
11118
+ "properties": {
11119
+ "selector": {
11120
+ "type": "string"
11121
+ },
11122
+ "route": {
11123
+ "anyOf": [
11124
+ {
11125
+ "type": "string"
11126
+ },
11127
+ {
11128
+ "type": "array",
11129
+ "items": {
11130
+ "type": "string"
11131
+ }
11132
+ }
11133
+ ]
11134
+ }
11135
+ },
11136
+ "required": [
11137
+ "selector",
11138
+ "route"
11139
+ ],
11140
+ "additionalProperties": false
11095
11141
  },
11096
11142
  "label": {
11097
11143
  "type": "string"
@@ -11984,6 +12030,32 @@
11984
12030
  "type": "string",
11985
12031
  "minLength": 1
11986
12032
  },
12033
+ "anchor": {
12034
+ "type": "object",
12035
+ "properties": {
12036
+ "selector": {
12037
+ "type": "string"
12038
+ },
12039
+ "route": {
12040
+ "anyOf": [
12041
+ {
12042
+ "type": "string"
12043
+ },
12044
+ {
12045
+ "type": "array",
12046
+ "items": {
12047
+ "type": "string"
12048
+ }
12049
+ }
12050
+ ]
12051
+ }
12052
+ },
12053
+ "required": [
12054
+ "selector",
12055
+ "route"
12056
+ ],
12057
+ "additionalProperties": false
12058
+ },
11987
12059
  "href": {
11988
12060
  "type": "string"
11989
12061
  },
@@ -14700,6 +14772,32 @@
14700
14772
  "type": "string",
14701
14773
  "minLength": 1
14702
14774
  },
14775
+ "anchor": {
14776
+ "type": "object",
14777
+ "properties": {
14778
+ "selector": {
14779
+ "type": "string"
14780
+ },
14781
+ "route": {
14782
+ "anyOf": [
14783
+ {
14784
+ "type": "string"
14785
+ },
14786
+ {
14787
+ "type": "array",
14788
+ "items": {
14789
+ "type": "string"
14790
+ }
14791
+ }
14792
+ ]
14793
+ }
14794
+ },
14795
+ "required": [
14796
+ "selector",
14797
+ "route"
14798
+ ],
14799
+ "additionalProperties": false
14800
+ },
14703
14801
  "href": {
14704
14802
  "type": "string"
14705
14803
  },
@@ -71,6 +71,9 @@ export const syntroReactPlugin = {
71
71
  export function useReducer() { return _R().useReducer.apply(null, arguments); }
72
72
  export function useLayoutEffect() { return _R().useLayoutEffect.apply(null, arguments); }
73
73
  export function useId() { return _R().useId.apply(null, arguments); }
74
+ export function useSyncExternalStore() { return _R().useSyncExternalStore.apply(null, arguments); }
75
+ export function useDebugValue() { return _R().useDebugValue.apply(null, arguments); }
76
+ export function useInsertionEffect() { return _R().useInsertionEffect.apply(null, arguments); }
74
77
 
75
78
  // Creation APIs — lazy function wrappers
76
79
  export function createElement() { return _R().createElement.apply(null, arguments); }
@@ -119,6 +119,29 @@ if (semanticErrors.length > 0) {
119
119
  process.exit(1);
120
120
  }
121
121
 
122
+ // --- Semantic check: tiles with notifications must have actions ---
123
+ // Notifications reference content (FAQ items, nav tips) that lives in
124
+ // tile.props.actions. Without actions, notifications have nothing to show.
125
+ for (const tile of config.tiles ?? []) {
126
+ const notifications = tile.notifications ?? [];
127
+ if (notifications.length === 0) continue;
128
+
129
+ const actions = tile.props?.actions ?? [];
130
+ if (actions.length === 0) {
131
+ semanticErrors.push(
132
+ `Tile "${tile.id}": has ${notifications.length} notification(s) but no actions.\n` +
133
+ ` Notifications reference tile content (FAQ items, nav tips) defined in tile.props.actions.\n` +
134
+ ` Add actions to the tile, or remove the notifications.`
135
+ );
136
+ }
137
+ }
138
+
139
+ if (semanticErrors.length > 0) {
140
+ console.error(`\n\u274C ${semanticErrors.length} semantic error(s):`);
141
+ for (const e of semanticErrors) console.error(` - ${e}`);
142
+ process.exit(1);
143
+ }
144
+
122
145
  // --- Semantic check: anchorId.route must include at least one concrete route ---
123
146
  // Wildcards allowed by canvas-config.schema.json anchorId.route;
124
147
  // update here if the schema adds new glob patterns.
@@ -241,6 +264,25 @@ for (const { path, url } of pageUrlHits) {
241
264
  }
242
265
  }
243
266
 
267
+ // Hidden insertHtml without a triggerWhen is dead HTML — the SDK has no way to show it.
268
+ // The LLM sometimes generates `display:none` elements expecting a trigger type (e.g.,
269
+ // exit-intent) that doesn't exist in the SDK. Without triggerWhen, the element is
270
+ // injected hidden and stays hidden forever.
271
+ for (const [i, action] of (config.actions ?? []).entries()) {
272
+ if (action.kind !== 'content:insertHtml') continue;
273
+ if (action.triggerWhen) continue;
274
+ const html = action.html ?? '';
275
+ if (!/display\s*:\s*none/i.test(html)) continue;
276
+
277
+ const label = action.label ? ` (label: "${action.label}")` : '';
278
+ warnings.push(
279
+ `actions[${i}]${label}: content:insertHtml injects hidden HTML (display:none) with no triggerWhen.\n` +
280
+ ` This element will be inserted into the DOM but never shown — the SDK has no mechanism to reveal it.\n` +
281
+ ` Either add a triggerWhen with a valid condition (e.g., event_count, session_metric) to control visibility,\n` +
282
+ ` or remove display:none to show it immediately.`
283
+ );
284
+ }
285
+
244
286
  if (warnings.length > 0) {
245
287
  console.warn(`\n\u26A0\uFE0F ${warnings.length} design warning(s):`);
246
288
  for (const w of warnings) console.warn(` - ${w}`);