@syntrologie/runtime-sdk 2.4.0-canary.2 → 2.4.0-canary.21

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 (62) hide show
  1. package/CAPABILITIES.md +116 -1
  2. package/dist/SmartCanvasApp.d.ts +5 -3
  3. package/dist/actions/executors/index.d.ts +1 -2
  4. package/dist/actions/index.d.ts +2 -2
  5. package/dist/actions/schema.d.ts +58243 -201
  6. package/dist/actions/schema.js +5 -2
  7. package/dist/actions/types.d.ts +45 -48
  8. package/dist/anchor/AnchorResolver.d.ts +18 -0
  9. package/dist/anchor/index.d.ts +2 -0
  10. package/dist/api.d.ts +3 -8
  11. package/dist/apps/examples/gamification-app.example.d.ts +8 -8
  12. package/dist/chunk-2UYZ5DWI.js +126 -0
  13. package/dist/chunk-2UYZ5DWI.js.map +7 -0
  14. package/dist/{chunk-DOJR7R46.js → chunk-HF3D7YFQ.js} +49 -31
  15. package/dist/chunk-HF3D7YFQ.js.map +7 -0
  16. package/dist/{chunk-ZDZ3IYFN.js → chunk-IPU3WVPY.js} +3449 -2110
  17. package/dist/chunk-IPU3WVPY.js.map +7 -0
  18. package/dist/{chunk-BIYMC56J.js → chunk-P5G4KT2U.js} +54 -6
  19. package/dist/chunk-P5G4KT2U.js.map +7 -0
  20. package/dist/components/ShadowCanvasOverlay.d.ts +1 -20
  21. package/dist/config/schema.d.ts +1797 -267
  22. package/dist/config/schema.js +19 -62
  23. package/dist/config/schema.js.map +3 -3
  24. package/dist/context/schema.d.ts +8 -8
  25. package/dist/decisions/schema.d.ts +506 -1490
  26. package/dist/decisions/schema.js +5 -2
  27. package/dist/decisions/types.d.ts +22 -0
  28. package/dist/events/registerConfigPredicates.d.ts +7 -10
  29. package/dist/events/schema.d.ts +12 -12
  30. package/dist/experiments/adapters/growthbook.d.ts +2 -0
  31. package/dist/experiments/types.d.ts +7 -0
  32. package/dist/hooks/useShadowCanvasConfig.d.ts +4 -2
  33. package/dist/index.d.ts +1 -0
  34. package/dist/index.js +72 -98
  35. package/dist/index.js.map +3 -3
  36. package/dist/overlays/schema.d.ts +48 -48
  37. package/dist/react.js +4 -3
  38. package/dist/react.js.map +1 -1
  39. package/dist/runtime.d.ts +3 -0
  40. package/dist/smart-canvas.esm.js +62 -66
  41. package/dist/smart-canvas.esm.js.map +4 -4
  42. package/dist/smart-canvas.js +2591 -1167
  43. package/dist/smart-canvas.js.map +4 -4
  44. package/dist/smart-canvas.min.js +62 -66
  45. package/dist/smart-canvas.min.js.map +4 -4
  46. package/dist/surfaces/types.d.ts +2 -1
  47. package/dist/theme/ThemeProvider.d.ts +11 -16
  48. package/dist/theme/defaultTheme.d.ts +6 -1
  49. package/dist/theme/index.d.ts +3 -4
  50. package/dist/theme/types.d.ts +10 -0
  51. package/dist/version.d.ts +1 -1
  52. package/package.json +7 -7
  53. package/schema/canvas-config.schema.json +9418 -790
  54. package/scripts/validate-config.mjs +78 -0
  55. package/dist/actions/executors/tour.d.ts +0 -18
  56. package/dist/chunk-BIYMC56J.js.map +0 -7
  57. package/dist/chunk-DOJR7R46.js.map +0 -7
  58. package/dist/chunk-JMHRHAEL.js +0 -18
  59. package/dist/chunk-JMHRHAEL.js.map +0 -7
  60. package/dist/chunk-ZDZ3IYFN.js.map +0 -7
  61. package/dist/hooks/useHostPatches.d.ts +0 -9
  62. package/dist/theme/extractHostTheme.d.ts +0 -14
@@ -3,12 +3,14 @@ import {
3
3
  AnchorVisibleConditionZ,
4
4
  ConditionZ,
5
5
  CooldownActiveConditionZ,
6
+ CounterDefZ,
6
7
  DecisionStrategyZ,
7
8
  DismissedConditionZ,
8
9
  EventCountConditionZ,
9
10
  EventOccurredConditionZ,
10
11
  ExternalStrategyZ,
11
12
  FrequencyLimitConditionZ,
13
+ MatchOpZ,
12
14
  ModelStrategyZ,
13
15
  PageUrlConditionZ,
14
16
  RouteConditionZ,
@@ -23,19 +25,20 @@ import {
23
25
  validateActivationConfig,
24
26
  validateCondition,
25
27
  validateStrategy
26
- } from "../chunk-BIYMC56J.js";
27
- import "../chunk-JMHRHAEL.js";
28
+ } from "../chunk-P5G4KT2U.js";
28
29
  export {
29
30
  ActivationConfigZ,
30
31
  AnchorVisibleConditionZ,
31
32
  ConditionZ,
32
33
  CooldownActiveConditionZ,
34
+ CounterDefZ,
33
35
  DecisionStrategyZ,
34
36
  DismissedConditionZ,
35
37
  EventCountConditionZ,
36
38
  EventOccurredConditionZ,
37
39
  ExternalStrategyZ,
38
40
  FrequencyLimitConditionZ,
41
+ MatchOpZ,
39
42
  ModelStrategyZ,
40
43
  PageUrlConditionZ,
41
44
  RouteConditionZ,
@@ -110,6 +110,25 @@ export interface FrequencyLimitCondition {
110
110
  /** Invert the condition (true if limit NOT reached) */
111
111
  inverted?: boolean;
112
112
  }
113
+ /**
114
+ * Match operator for counter filters.
115
+ * Exactly one of `equals` or `contains` must be specified.
116
+ */
117
+ export interface MatchOp {
118
+ equals?: string | number | boolean;
119
+ contains?: string;
120
+ }
121
+ /**
122
+ * Defines what events to count for an event_count condition.
123
+ * Registered as an accumulator predicate at config-load time.
124
+ */
125
+ export interface CounterDef {
126
+ /** Event names to listen for (e.g., ["ui.click"]). ALL other filters AND with this. */
127
+ events: string[];
128
+ /** Prop-based filters. Keys are event prop names OR element-chain fields
129
+ * (tag_name, $el_text, attr__*). All entries AND together. */
130
+ match?: Record<string, MatchOp>;
131
+ }
113
132
  /**
114
133
  * Condition that checks accumulated event counts.
115
134
  * Used for behavior triggers like "visited /pricing 3+ times".
@@ -125,6 +144,9 @@ export interface EventCountCondition {
125
144
  count: number;
126
145
  /** Only count events within this time window (ms). Omit = session lifetime. */
127
146
  withinMs?: number;
147
+ /** Inline counter definition. Defines what events to count.
148
+ * If omitted, predicate is pass-through (counts all events). */
149
+ counter?: CounterDef;
128
150
  }
129
151
  /**
130
152
  * Union of all condition types.
@@ -1,19 +1,16 @@
1
1
  /**
2
2
  * Register accumulator predicates from tile configs at config-load time.
3
3
  *
4
- * Previously, predicate registration lived inside FAQWidget's useEffect
5
- * meaning predicates were only active when the widget was mounted (canvas open).
6
- * On multi-page apps with `defaultOpen: false`, the canvas stays closed after
7
- * navigation, the widget never mounts, and clicks go uncounted.
4
+ * Scans all triggerWhen conditions (in tile actions and top-level actions)
5
+ * for event_count conditions with a `counter` definition. For each, builds
6
+ * a predicate and registers it with the accumulator.
8
7
  *
9
- * This module extracts that logic so predicates are registered as soon as the
10
- * config is loaded, regardless of canvas state.
8
+ * Safe to call multiple times accumulator.register() is idempotent.
11
9
  */
12
10
  import type { TileConfig } from '../types';
13
11
  import type { EventAccumulator } from './EventAccumulator';
14
12
  /**
15
- * Scan tile configs for scope + showWhen event_count conditions and register
16
- * accumulator predicates. Safe to call multiple times — accumulator.register()
17
- * is idempotent (skips if key already registered).
13
+ * Scan tile configs and top-level actions for event_count conditions
14
+ * and register accumulator predicates from their counter definitions.
18
15
  */
19
- export declare function registerConfigPredicates(tiles: TileConfig[], accumulator: EventAccumulator): void;
16
+ export declare function registerConfigPredicates(tiles: TileConfig[], accumulator: EventAccumulator, actions?: unknown[]): void;
@@ -10,15 +10,15 @@ export declare const NormalizedEventZ: z.ZodObject<{
10
10
  props: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
11
11
  schemaVersion: z.ZodString;
12
12
  }, "strip", z.ZodTypeAny, {
13
- source: "posthog" | "canvas" | "derived";
14
- name: string;
15
13
  schemaVersion: string;
14
+ source: "canvas" | "posthog" | "derived";
15
+ name: string;
16
16
  ts: number;
17
17
  props?: Record<string, unknown> | undefined;
18
18
  }, {
19
- source: "posthog" | "canvas" | "derived";
20
- name: string;
21
19
  schemaVersion: string;
20
+ source: "canvas" | "posthog" | "derived";
21
+ name: string;
22
22
  ts: number;
23
23
  props?: Record<string, unknown> | undefined;
24
24
  }>;
@@ -29,25 +29,25 @@ export declare const EventFilterZ: z.ZodObject<{
29
29
  }, "strip", z.ZodTypeAny, {
30
30
  names?: string[] | undefined;
31
31
  patterns?: string[] | undefined;
32
- sources?: ("posthog" | "canvas" | "derived")[] | undefined;
32
+ sources?: ("canvas" | "posthog" | "derived")[] | undefined;
33
33
  }, {
34
34
  names?: string[] | undefined;
35
35
  patterns?: string[] | undefined;
36
- sources?: ("posthog" | "canvas" | "derived")[] | undefined;
36
+ sources?: ("canvas" | "posthog" | "derived")[] | undefined;
37
37
  }>;
38
38
  /**
39
39
  * Validate a NormalizedEvent object.
40
40
  */
41
41
  export declare function validateNormalizedEvent(data: unknown): z.SafeParseReturnType<{
42
- source: "posthog" | "canvas" | "derived";
43
- name: string;
44
42
  schemaVersion: string;
43
+ source: "canvas" | "posthog" | "derived";
44
+ name: string;
45
45
  ts: number;
46
46
  props?: Record<string, unknown> | undefined;
47
47
  }, {
48
- source: "posthog" | "canvas" | "derived";
49
- name: string;
50
48
  schemaVersion: string;
49
+ source: "canvas" | "posthog" | "derived";
50
+ name: string;
51
51
  ts: number;
52
52
  props?: Record<string, unknown> | undefined;
53
53
  }>;
@@ -57,11 +57,11 @@ export declare function validateNormalizedEvent(data: unknown): z.SafeParseRetur
57
57
  export declare function validateEventFilter(data: unknown): z.SafeParseReturnType<{
58
58
  names?: string[] | undefined;
59
59
  patterns?: string[] | undefined;
60
- sources?: ("posthog" | "canvas" | "derived")[] | undefined;
60
+ sources?: ("canvas" | "posthog" | "derived")[] | undefined;
61
61
  }, {
62
62
  names?: string[] | undefined;
63
63
  patterns?: string[] | undefined;
64
- sources?: ("posthog" | "canvas" | "derived")[] | undefined;
64
+ sources?: ("canvas" | "posthog" | "derived")[] | undefined;
65
65
  }>;
66
66
  /**
67
67
  * Type inference from Zod schema.
@@ -43,6 +43,7 @@ export interface GrowthBookAdapterOptions extends GrowthBookInitOptions {
43
43
  */
44
44
  export declare class GrowthBookAdapter implements ExperimentClient {
45
45
  private readonly gb;
46
+ private readonly featureListeners;
46
47
  constructor(options?: GrowthBookAdapterOptions);
47
48
  /**
48
49
  * Access to the underlying GrowthBook instance.
@@ -55,6 +56,7 @@ export declare class GrowthBookAdapter implements ExperimentClient {
55
56
  getFeatureValue<T>(key: string, fallback: T): T;
56
57
  getAllFeatures(): Record<string, unknown>;
57
58
  shouldRenderRectangle(_tile: TileConfig): boolean;
59
+ onFeaturesChanged(callback: () => void): () => void;
58
60
  }
59
61
  /**
60
62
  * Create an ExperimentClient backed by GrowthBook.
@@ -32,6 +32,13 @@ export interface ExperimentClient {
32
32
  * Returns a map of feature key -> feature value.
33
33
  */
34
34
  getAllFeatures?(): Record<string, unknown>;
35
+ /**
36
+ * Subscribe to feature flag value changes.
37
+ * Called when the underlying provider receives updated feature values
38
+ * (e.g., via streaming, webhook, or manual refresh).
39
+ * Returns an unsubscribe function.
40
+ */
41
+ onFeaturesChanged?(callback: () => void): () => void;
35
42
  }
36
43
  /**
37
44
  * @deprecated Use ExperimentClient instead
@@ -3,11 +3,13 @@ import type { SmartCanvasRuntime } from '../runtime';
3
3
  import type { ActionStep, CanvasConfigFetcher, CanvasThemeConfig, LauncherConfig, TileConfig } from '../types';
4
4
  export interface UseShadowCanvasConfigOptions {
5
5
  fetcher: CanvasConfigFetcher;
6
- pollIntervalMs?: number;
7
6
  /** @deprecated Use runtime instead */
8
7
  experiments?: ExperimentClient;
9
8
  /** v2 Runtime for activation-based filtering */
10
9
  runtime?: SmartCanvasRuntime;
10
+ /** Current page URL — triggers re-filter when URL changes (route-based activation).
11
+ * Full URL (not just pathname) so hash-based routing also triggers re-filter. */
12
+ pageUrl?: string;
11
13
  }
12
14
  export interface ShadowCanvasConfigState {
13
15
  tiles: TileConfig[];
@@ -24,4 +26,4 @@ export interface ShadowCanvasConfigState {
24
26
  /** Launcher button configuration */
25
27
  launcher?: LauncherConfig;
26
28
  }
27
- export declare function useShadowCanvasConfig({ fetcher, pollIntervalMs, experiments, runtime, }: UseShadowCanvasConfigOptions): ShadowCanvasConfigState;
29
+ export declare function useShadowCanvasConfig({ fetcher, experiments, runtime, pageUrl, }: UseShadowCanvasConfigOptions): ShadowCanvasConfigState;
package/dist/index.d.ts CHANGED
@@ -20,6 +20,7 @@ export * from './telemetry';
20
20
  export * from './types';
21
21
  export * from './version';
22
22
  export * from './actions';
23
+ export * from './anchor';
23
24
  export * from './apps';
24
25
  export * from './context';
25
26
  export * from './decisions';
package/dist/index.js CHANGED
@@ -30,10 +30,9 @@ import {
30
30
  appRegistry,
31
31
  applyStaticSlotStyles,
32
32
  base,
33
- border,
34
- brand,
35
33
  cleanupAppContext,
36
34
  createActionEngine,
35
+ createAnchorResolver,
37
36
  createAppContext,
38
37
  createAppLoader,
39
38
  createCanvasConfigFetcher,
@@ -101,9 +100,10 @@ import {
101
100
  validateAction,
102
101
  validateActions,
103
102
  widgetRegistry
104
- } from "./chunk-ZDZ3IYFN.js";
103
+ } from "./chunk-IPU3WVPY.js";
105
104
  import {
106
105
  AddClassZ,
106
+ AnchorIdZ,
107
107
  BadgePositionZ,
108
108
  BadgeZ,
109
109
  CtaButtonZ,
@@ -134,18 +134,21 @@ import {
134
134
  WaitZ,
135
135
  WidgetConfigZ,
136
136
  coreActionStepSchemas
137
- } from "./chunk-DOJR7R46.js";
137
+ } from "./chunk-HF3D7YFQ.js";
138
+ import "./chunk-2UYZ5DWI.js";
138
139
  import {
139
140
  ActivationConfigZ,
140
141
  AnchorVisibleConditionZ,
141
142
  ConditionZ,
142
143
  CooldownActiveConditionZ,
144
+ CounterDefZ,
143
145
  DecisionStrategyZ,
144
146
  DismissedConditionZ,
145
147
  EventCountConditionZ,
146
148
  EventOccurredConditionZ,
147
149
  ExternalStrategyZ,
148
150
  FrequencyLimitConditionZ,
151
+ MatchOpZ,
149
152
  ModelStrategyZ,
150
153
  PageUrlConditionZ,
151
154
  RouteConditionZ,
@@ -160,8 +163,7 @@ import {
160
163
  validateActivationConfig,
161
164
  validateCondition,
162
165
  validateStrategy
163
- } from "./chunk-BIYMC56J.js";
164
- import "./chunk-JMHRHAEL.js";
166
+ } from "./chunk-P5G4KT2U.js";
165
167
 
166
168
  // src/index.ts
167
169
  import React4 from "react";
@@ -841,14 +843,18 @@ var themeStyles = {
841
843
  }
842
844
  }
843
845
  };
844
- function FAQItem({ item, isExpanded, onToggle, theme, feedbackConfig, feedbackValue, onFeedback }) {
846
+ function FAQItem({ item, isExpanded, isHighlighted, onToggle, theme, feedbackConfig, feedbackValue, onFeedback }) {
845
847
  const [isHovered, setIsHovered] = useState2(false);
846
848
  const colors = themeStyles[theme];
847
849
  const { question, answer } = item.config;
848
850
  const itemStyle = {
849
851
  ...baseStyles.item,
850
852
  ...colors.item,
851
- ...isExpanded ? colors.itemExpanded : {}
853
+ ...isExpanded ? colors.itemExpanded : {},
854
+ ...isHighlighted ? {
855
+ boxShadow: "0 0 0 2px #6366f1, 0 0 12px rgba(99, 102, 241, 0.4)",
856
+ transition: "box-shadow 0.3s ease"
857
+ } : {}
852
858
  };
853
859
  const questionStyle = {
854
860
  ...baseStyles.question,
@@ -880,6 +886,7 @@ function FAQItem({ item, isExpanded, onToggle, theme, feedbackConfig, feedbackVa
880
886
  function FAQWidget({ config, runtime: runtime7, instanceId }) {
881
887
  const [renderTick, forceUpdate] = useReducer((x) => x + 1, 0);
882
888
  const [expandedIds, setExpandedIds] = useState2(/* @__PURE__ */ new Set());
889
+ const [highlightId, setHighlightId] = useState2(null);
883
890
  const [searchQuery, setSearchQuery] = useState2("");
884
891
  const [feedbackState, setFeedbackState] = useState2(/* @__PURE__ */ new Map());
885
892
  const feedbackConfig = useMemo(() => resolveFeedbackConfig(config.feedback), [config.feedback]);
@@ -897,43 +904,6 @@ function FAQWidget({ config, runtime: runtime7, instanceId }) {
897
904
  forceUpdate();
898
905
  });
899
906
  }, [runtime7.accumulator]);
900
- useEffect2(() => {
901
- var _a, _b;
902
- if (!config.scope || !((_a = runtime7.accumulator) == null ? void 0 : _a.register))
903
- return;
904
- const { events: eventNames, urlContains, props: propFilters } = config.scope;
905
- const keys = /* @__PURE__ */ new Set();
906
- for (const action of config.actions) {
907
- if (((_b = action.showWhen) == null ? void 0 : _b.type) === "rules") {
908
- for (const rule of action.showWhen.rules) {
909
- for (const cond of rule.conditions) {
910
- if (cond.type === "event_count" && cond.key) {
911
- keys.add(cond.key);
912
- }
913
- }
914
- }
915
- }
916
- }
917
- for (const key of keys) {
918
- runtime7.accumulator.register(key, (event) => {
919
- var _a2, _b2, _c;
920
- if (!eventNames.includes(event.name))
921
- return false;
922
- if (urlContains) {
923
- const pathname = String((_b2 = (_a2 = event.props) == null ? void 0 : _a2.pathname) != null ? _b2 : "");
924
- if (!pathname.includes(urlContains))
925
- return false;
926
- }
927
- if (propFilters) {
928
- for (const [k, v] of Object.entries(propFilters)) {
929
- if (((_c = event.props) == null ? void 0 : _c[k]) !== v)
930
- return false;
931
- }
932
- }
933
- return true;
934
- });
935
- }
936
- }, [config.scope, config.actions, runtime7.accumulator]);
937
907
  useEffect2(() => {
938
908
  if (!runtime7.events.subscribe)
939
909
  return;
@@ -970,10 +940,43 @@ function FAQWidget({ config, runtime: runtime7, instanceId }) {
970
940
  });
971
941
  return unsubscribe;
972
942
  }, [runtime7]);
943
+ useEffect2(() => {
944
+ if (!runtime7.events.subscribe)
945
+ return;
946
+ const handleDeepLink = (event) => {
947
+ var _a, _b;
948
+ const tileId = (_a = event.props) == null ? void 0 : _a.tileId;
949
+ const itemId = (_b = event.props) == null ? void 0 : _b.itemId;
950
+ if (tileId !== instanceId)
951
+ return;
952
+ if (!itemId)
953
+ return;
954
+ setExpandedIds(/* @__PURE__ */ new Set([itemId]));
955
+ setHighlightId(itemId);
956
+ setTimeout(() => setHighlightId(null), 1500);
957
+ requestAnimationFrame(() => {
958
+ const el = document.querySelector(`[data-faq-item-id="${itemId}"]`);
959
+ if (el)
960
+ el.scrollIntoView({ behavior: "smooth", block: "center" });
961
+ });
962
+ };
963
+ if (runtime7.events.getRecent) {
964
+ const recent = runtime7.events.getRecent({ names: ["notification.deep_link"] }, 5);
965
+ const pending = recent.filter((e) => {
966
+ var _a, _b;
967
+ return ((_a = e.props) == null ? void 0 : _a.tileId) === instanceId && ((_b = e.props) == null ? void 0 : _b.itemId);
968
+ }).pop();
969
+ if (pending && Date.now() - pending.ts < 1e4) {
970
+ handleDeepLink(pending);
971
+ }
972
+ }
973
+ const unsubscribe = runtime7.events.subscribe({ names: ["notification.deep_link"] }, handleDeepLink);
974
+ return unsubscribe;
975
+ }, [runtime7, instanceId]);
973
976
  const visibleQuestions = useMemo(() => config.actions.filter((q) => {
974
- if (!q.showWhen)
977
+ if (!q.triggerWhen)
975
978
  return true;
976
- const result = runtime7.evaluateSync(q.showWhen);
979
+ const result = runtime7.evaluateSync(q.triggerWhen);
977
980
  return result.value;
978
981
  }), [config.actions, runtime7, renderTick]);
979
982
  const orderedQuestions = useMemo(() => {
@@ -1067,7 +1070,7 @@ function FAQWidget({ config, runtime: runtime7, instanceId }) {
1067
1070
  ...baseStyles.categoryHeader,
1068
1071
  ...themeStyles[resolvedTheme].categoryHeader
1069
1072
  };
1070
- const renderItems = (items) => items.map((q) => _jsx2(FAQItem, { item: q, isExpanded: expandedIds.has(q.config.id), onToggle: () => handleToggle(q.config.id), theme: resolvedTheme, feedbackConfig, feedbackValue: feedbackState.get(q.config.id), onFeedback: handleFeedback }, q.config.id));
1073
+ const renderItems = (items) => items.map((q) => _jsx2(FAQItem, { item: q, isExpanded: expandedIds.has(q.config.id), isHighlighted: highlightId === q.config.id, onToggle: () => handleToggle(q.config.id), theme: resolvedTheme, feedbackConfig, feedbackValue: feedbackState.get(q.config.id), onFeedback: handleFeedback }, q.config.id));
1071
1074
  if (visibleQuestions.length === 0) {
1072
1075
  return _jsx2("div", { style: containerStyle, "data-adaptive-id": instanceId, "data-adaptive-type": "adaptive-faq", children: _jsx2("div", { style: emptyStateStyle, children: "No FAQ questions available." }) });
1073
1076
  }
@@ -1136,14 +1139,14 @@ var runtime4 = {
1136
1139
  /**
1137
1140
  * Extract notify watcher entries from tile config props.
1138
1141
  * The runtime evaluates these continuously (even with drawer closed)
1139
- * and publishes faq:question_revealed when showWhen transitions false → true.
1142
+ * and publishes faq:question_revealed when triggerWhen transitions false → true.
1140
1143
  */
1141
1144
  notifyWatchers(props) {
1142
1145
  var _a;
1143
1146
  const actions = (_a = props.actions) != null ? _a : [];
1144
- return actions.filter((a) => a.notify && a.showWhen).map((a) => ({
1147
+ return actions.filter((a) => a.notify && a.triggerWhen).map((a) => ({
1145
1148
  id: `faq:${a.config.id}`,
1146
- strategy: a.showWhen,
1149
+ strategy: a.triggerWhen,
1147
1150
  eventName: "faq:question_revealed",
1148
1151
  eventProps: {
1149
1152
  questionId: a.config.id,
@@ -1403,48 +1406,11 @@ function NavWidget({ config, runtime: runtime7, instanceId }) {
1403
1406
  forceUpdate();
1404
1407
  });
1405
1408
  }, [runtime7.accumulator]);
1406
- useEffect3(() => {
1407
- var _a, _b;
1408
- if (!config.scope || !((_a = runtime7.accumulator) == null ? void 0 : _a.register))
1409
- return;
1410
- const { events: eventNames, urlContains, props: propFilters } = config.scope;
1411
- const keys = /* @__PURE__ */ new Set();
1412
- for (const action of config.actions) {
1413
- if (((_b = action.showWhen) == null ? void 0 : _b.type) === "rules") {
1414
- for (const rule of action.showWhen.rules) {
1415
- for (const cond of rule.conditions) {
1416
- if (cond.type === "event_count" && cond.key) {
1417
- keys.add(cond.key);
1418
- }
1419
- }
1420
- }
1421
- }
1422
- }
1423
- for (const key of keys) {
1424
- runtime7.accumulator.register(key, (event) => {
1425
- var _a2, _b2, _c;
1426
- if (!eventNames.includes(event.name))
1427
- return false;
1428
- if (urlContains) {
1429
- const pathname = String((_b2 = (_a2 = event.props) == null ? void 0 : _a2.pathname) != null ? _b2 : "");
1430
- if (!pathname.includes(urlContains))
1431
- return false;
1432
- }
1433
- if (propFilters) {
1434
- for (const [k, v] of Object.entries(propFilters)) {
1435
- if (((_c = event.props) == null ? void 0 : _c[k]) !== v)
1436
- return false;
1437
- }
1438
- }
1439
- return true;
1440
- });
1441
- }
1442
- }, [config.scope, config.actions, runtime7.accumulator]);
1443
1409
  const visibleTips = useMemo2(() => config.actions.filter((tip) => {
1444
- if (!tip.showWhen)
1410
+ if (!tip.triggerWhen)
1445
1411
  return true;
1446
1412
  try {
1447
- const result = runtime7.evaluateSync(tip.showWhen);
1413
+ const result = runtime7.evaluateSync(tip.triggerWhen);
1448
1414
  return result.value;
1449
1415
  } catch {
1450
1416
  return false;
@@ -1518,7 +1484,9 @@ function NavWidget({ config, runtime: runtime7, instanceId }) {
1518
1484
  if (external) {
1519
1485
  window.open(href, "_blank", "noopener,noreferrer");
1520
1486
  } else {
1521
- window.location.href = href;
1487
+ const url = new URL(href, window.location.origin);
1488
+ url.search = window.location.search;
1489
+ window.location.href = url.toString();
1522
1490
  }
1523
1491
  }, [runtime7.events, instanceId]);
1524
1492
  const containerStyle = {
@@ -1580,7 +1548,9 @@ var executeScrollTo = async (action, context) => {
1580
1548
  var _a, _b, _c, _d;
1581
1549
  const anchorEl = context.resolveAnchor(action.anchorId);
1582
1550
  if (!anchorEl) {
1583
- throw new Error(`Anchor not found: ${action.anchorId}`);
1551
+ console.error(`[adaptive-nav] Anchor not found for scrollTo, skipping: ${action.anchorId.selector}`);
1552
+ return { cleanup: () => {
1553
+ } };
1584
1554
  }
1585
1555
  anchorEl.scrollIntoView({
1586
1556
  behavior: (_a = action.behavior) != null ? _a : "smooth",
@@ -1662,14 +1632,14 @@ var runtime6 = {
1662
1632
  /**
1663
1633
  * Extract notify watcher entries from tile config props.
1664
1634
  * The runtime evaluates these continuously (even with drawer closed)
1665
- * and publishes nav:tip_revealed when showWhen transitions false → true.
1635
+ * and publishes nav:tip_revealed when triggerWhen transitions false → true.
1666
1636
  */
1667
1637
  notifyWatchers(props) {
1668
1638
  var _a;
1669
1639
  const actions = (_a = props.actions) != null ? _a : [];
1670
- return actions.filter((a) => a.notify && a.showWhen).map((a) => ({
1640
+ return actions.filter((a) => a.notify && a.triggerWhen).map((a) => ({
1671
1641
  id: `nav:${a.config.id}`,
1672
- strategy: a.showWhen,
1642
+ strategy: a.triggerWhen,
1673
1643
  eventName: "nav:tip_revealed",
1674
1644
  eventProps: {
1675
1645
  tipId: a.config.id,
@@ -1744,8 +1714,8 @@ function TileWheel({ tiles, intervalMs = 7e3, telemetry }) {
1744
1714
  position: "relative",
1745
1715
  overflow: "hidden",
1746
1716
  borderRadius: "1.5rem",
1747
- border: `1px solid ${border.primary}`,
1748
- background: slateGrey[1],
1717
+ border: "var(--sc-tile-border)",
1718
+ background: "var(--sc-tile-background)",
1749
1719
  padding: "1.5rem",
1750
1720
  boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)"
1751
1721
  },
@@ -1771,7 +1741,7 @@ function TileWheel({ tiles, intervalMs = 7e3, telemetry }) {
1771
1741
  height: "0.5rem",
1772
1742
  width: "1.5rem",
1773
1743
  borderRadius: "9999px",
1774
- background: idx === index ? brand[3] : slateGrey[6],
1744
+ background: idx === index ? "var(--sc-color-primary)" : "var(--sc-tile-text-color)",
1775
1745
  border: "none",
1776
1746
  cursor: "pointer",
1777
1747
  padding: 0
@@ -2086,6 +2056,7 @@ export {
2086
2056
  ANIMATION_KEYFRAMES,
2087
2057
  ActivationConfigZ,
2088
2058
  AddClassZ,
2059
+ AnchorIdZ,
2089
2060
  AnchorStateZ,
2090
2061
  AnchorVisibleConditionZ,
2091
2062
  AppRegistry,
@@ -2098,6 +2069,7 @@ export {
2098
2069
  ConditionZ,
2099
2070
  ContextManager,
2100
2071
  CooldownActiveConditionZ,
2072
+ CounterDefZ,
2101
2073
  CtaButtonZ,
2102
2074
  DEFAULT_COOLDOWN,
2103
2075
  DEFAULT_TTL,
@@ -2119,6 +2091,7 @@ export {
2119
2091
  InsertHtmlZ,
2120
2092
  InsertPositionZ,
2121
2093
  MAX_VISIBLE_TOASTS,
2094
+ MatchOpZ,
2122
2095
  ModalContentZ,
2123
2096
  ModalZ,
2124
2097
  ModelStrategyZ,
@@ -2187,6 +2160,7 @@ export {
2187
2160
  runtime as contentRuntime,
2188
2161
  coreActionStepSchemas,
2189
2162
  createActionEngine,
2163
+ createAnchorResolver,
2190
2164
  createAppContext,
2191
2165
  createAppLoader,
2192
2166
  createCanvasConfigFetcher,