@syntrologie/runtime-sdk 2.2.0-canary.9 → 2.2.0

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.
@@ -0,0 +1,36 @@
1
+ /**
2
+ * GTM DataLayer Bridge
3
+ *
4
+ * Subscribes to the EventBus and pushes events to window.dataLayer
5
+ * so customers' existing GTM setups can surface Syntro events.
6
+ */
7
+ export interface GtmBridgeConfig {
8
+ /** EventBus to subscribe to */
9
+ eventBus: {
10
+ subscribe: (filter: {
11
+ names?: string[];
12
+ patterns?: string[];
13
+ }, callback: (event: {
14
+ name: string;
15
+ props?: Record<string, unknown>;
16
+ source?: string;
17
+ ts: number;
18
+ }) => void) => () => void;
19
+ };
20
+ /** Prefix for event names in dataLayer. @default "syntro" */
21
+ prefix?: string;
22
+ /** Optional filter -- return true to include event, false to skip */
23
+ eventFilter?: (eventName: string) => boolean;
24
+ }
25
+ export interface GtmBridge {
26
+ destroy: () => void;
27
+ }
28
+ declare global {
29
+ interface Window {
30
+ dataLayer?: Array<Record<string, unknown>>;
31
+ }
32
+ }
33
+ /**
34
+ * Create a GTM DataLayer bridge that forwards EventBus events to window.dataLayer.
35
+ */
36
+ export declare function createGtmBridge(config: GtmBridgeConfig): GtmBridge;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * NavigationMonitor - Centralized History API patching.
3
+ *
4
+ * This is the SINGLE point in the SDK that wraps history.pushState and
5
+ * history.replaceState. All other modules that need to react to navigation
6
+ * (ContextManager, overlay runner, tour executor, SmartCanvasApp) must
7
+ * subscribe to this monitor instead of patching the History API directly.
8
+ *
9
+ * This prevents the "quadruple-patching" problem where multiple SDK modules
10
+ * each wrap pushState/replaceState independently, creating a fragile chain
11
+ * that can break when combined with React Router, GA4, and GTM — all of
12
+ * which also wrap the History API.
13
+ */
14
+ export type NavigationMethod = 'pushState' | 'replaceState' | 'popstate';
15
+ export type NavigationListener = (url: string, method: NavigationMethod) => void;
16
+ export interface NavigationDiagnostics {
17
+ /** Whether pushState was native (not already wrapped) when we captured it */
18
+ isNative: boolean;
19
+ /** Number of active subscribers */
20
+ subscriberCount: number;
21
+ }
22
+ export declare class NavigationMonitor {
23
+ private listeners;
24
+ private capturedPushState;
25
+ private capturedReplaceState;
26
+ private wasNative;
27
+ private destroyed;
28
+ constructor();
29
+ /**
30
+ * Subscribe to navigation events.
31
+ * Returns an unsubscribe function.
32
+ */
33
+ subscribe(listener: NavigationListener): () => void;
34
+ /**
35
+ * Get diagnostics about the History API chain.
36
+ */
37
+ diagnose(): NavigationDiagnostics;
38
+ /**
39
+ * Restore the History API to the state we captured and remove all listeners.
40
+ */
41
+ destroy(): void;
42
+ private onPopState;
43
+ private notify;
44
+ private isNativeFunction;
45
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * AnchorWatcher — Detects when an anchor element is removed from the DOM.
3
+ *
4
+ * Uses MutationObserver on document.body to watch for subtree changes
5
+ * that disconnect the watched element. Calls onDetach exactly once
6
+ * when the anchor's isConnected becomes false.
7
+ */
8
+ export interface AnchorWatcherOptions {
9
+ /** Called once when the anchor element is removed from the DOM. */
10
+ onDetach: () => void;
11
+ }
12
+ export declare class AnchorWatcher {
13
+ private opts;
14
+ private anchor;
15
+ private observer;
16
+ private detached;
17
+ constructor(anchor: HTMLElement, opts: AnchorWatcherOptions);
18
+ /** Returns the current connection status of the anchor. */
19
+ isConnected(): boolean;
20
+ /** Stop watching. Safe to call multiple times. */
21
+ destroy(): void;
22
+ }
@@ -119,4 +119,6 @@ export type OverlayContext = {
119
119
  telemetry?: {
120
120
  setPersonPropertiesOnce?: (props: Record<string, unknown>) => void;
121
121
  };
122
+ /** Subscribe to navigation changes (from NavigationMonitor) */
123
+ subscribeNavigation?: (callback: (url: string, method: string) => void) => () => void;
122
124
  };
package/dist/react.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Syntro
3
- } from "./chunk-UEAP7WOK.js";
3
+ } from "./chunk-V4MDQX67.js";
4
4
  import "./chunk-AYTRRBR5.js";
5
5
 
6
6
  // src/react.tsx
package/dist/runtime.d.ts CHANGED
@@ -20,6 +20,7 @@ import type { DecisionResult, DecisionStrategy } from './decisions/types';
20
20
  import { type EventAccumulator } from './events/EventAccumulator';
21
21
  import { type EventBus } from './events/EventBus';
22
22
  import type { SessionMetricTracker } from './metrics/sessionMetrics';
23
+ import { NavigationMonitor } from './navigation/NavigationMonitor';
23
24
  import { type StateStore } from './state/StateStore';
24
25
  import { type Surfaces } from './surfaces';
25
26
  import type { TelemetryClient } from './telemetry/types';
@@ -59,6 +60,8 @@ export interface SmartCanvasRuntime {
59
60
  apps: AppRegistry;
60
61
  /** Event accumulator for event_count conditions */
61
62
  accumulator: EventAccumulator;
63
+ /** Centralized navigation monitor for History API interception */
64
+ navigation: NavigationMonitor;
62
65
  /** Runtime version */
63
66
  version: string;
64
67
  /** Runtime mode */