@syntrologie/runtime-sdk 0.2.1 → 0.2.3
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.
- package/CAPABILITIES.md +400 -0
- package/dist/SmartCanvasApp.js +28 -10
- package/dist/SmartCanvasApp.js.map +1 -1
- package/dist/api.d.ts +23 -0
- package/dist/api.js +23 -5
- package/dist/api.js.map +1 -1
- package/dist/blocks/data/ComparisonBlock.d.ts +10 -0
- package/dist/blocks/data/ComparisonBlock.js +92 -0
- package/dist/blocks/data/ComparisonBlock.js.map +1 -0
- package/dist/blocks/data/StatsBlock.d.ts +10 -0
- package/dist/blocks/data/StatsBlock.js +103 -0
- package/dist/blocks/data/StatsBlock.js.map +1 -0
- package/dist/blocks/data/index.d.ts +2 -0
- package/dist/blocks/data/index.js +3 -0
- package/dist/blocks/data/index.js.map +1 -0
- package/dist/blocks/index.d.ts +26 -0
- package/dist/blocks/index.js +94 -0
- package/dist/blocks/index.js.map +1 -0
- package/dist/blocks/interactive/ChecklistBlock.d.ts +11 -0
- package/dist/blocks/interactive/ChecklistBlock.js +110 -0
- package/dist/blocks/interactive/ChecklistBlock.js.map +1 -0
- package/dist/blocks/interactive/RatingBlock.d.ts +11 -0
- package/dist/blocks/interactive/RatingBlock.js +131 -0
- package/dist/blocks/interactive/RatingBlock.js.map +1 -0
- package/dist/blocks/interactive/index.d.ts +2 -0
- package/dist/blocks/interactive/index.js +3 -0
- package/dist/blocks/interactive/index.js.map +1 -0
- package/dist/blocks/notification/NotificationBlock.d.ts +26 -0
- package/dist/blocks/notification/NotificationBlock.js +166 -0
- package/dist/blocks/notification/NotificationBlock.js.map +1 -0
- package/dist/blocks/notification/index.d.ts +1 -0
- package/dist/blocks/notification/index.js +2 -0
- package/dist/blocks/notification/index.js.map +1 -0
- package/dist/bootstrap.d.ts +19 -1
- package/dist/bootstrap.js +118 -17
- package/dist/bootstrap.js.map +1 -1
- package/dist/components/ShadowCanvasOverlay.d.ts +12 -3
- package/dist/components/ShadowCanvasOverlay.js +75 -24
- package/dist/components/ShadowCanvasOverlay.js.map +1 -1
- package/dist/components/{RectangleCard.d.ts → TileCard.d.ts} +4 -4
- package/dist/components/{RectangleCard.js → TileCard.js} +57 -6
- package/dist/components/TileCard.js.map +1 -0
- package/dist/components/TileWheel.d.ts +8 -0
- package/dist/components/{RectangleWheel.js → TileWheel.js} +7 -7
- package/dist/components/TileWheel.js.map +1 -0
- package/dist/configFetcher.js.map +1 -1
- package/dist/earlyPatcher.js +1 -2
- package/dist/earlyPatcher.js.map +1 -1
- package/dist/editorLoader.js +74 -17
- package/dist/editorLoader.js.map +1 -1
- package/dist/experiments/adapters/growthbook.d.ts +18 -2
- package/dist/experiments/adapters/growthbook.js +17 -3
- package/dist/experiments/adapters/growthbook.js.map +1 -1
- package/dist/experiments/registry.d.ts +18 -4
- package/dist/experiments/registry.js +1 -1
- package/dist/experiments/registry.js.map +1 -1
- package/dist/experiments/types.d.ts +8 -3
- package/dist/fetchers/cdnFetcher.js.map +1 -1
- package/dist/fetchers/experimentsFetcher.js +20 -0
- package/dist/fetchers/experimentsFetcher.js.map +1 -1
- package/dist/fetchers/types.d.ts +2 -2
- package/dist/hooks/useCanvasOverlays.d.ts +5 -1
- package/dist/hooks/useCanvasOverlays.js +33 -13
- package/dist/hooks/useCanvasOverlays.js.map +1 -1
- package/dist/hooks/useShadowCanvasConfig.d.ts +9 -2
- package/dist/hooks/useShadowCanvasConfig.js +8 -8
- package/dist/hooks/useShadowCanvasConfig.js.map +1 -1
- package/dist/hostPatcher/core/patcher.js +14 -15
- package/dist/hostPatcher/core/patcher.js.map +1 -1
- package/dist/hostPatcher/core/sanitizer.js +1 -1
- package/dist/hostPatcher/core/sanitizer.js.map +1 -1
- package/dist/hostPatcher/core/types.d.ts +8 -9
- package/dist/hostPatcher/policy/defaultPolicy.d.ts +4 -0
- package/dist/hostPatcher/policy/defaultPolicy.js +9 -37
- package/dist/hostPatcher/policy/defaultPolicy.js.map +1 -1
- package/dist/hostPatcher/utils/anchors.js +3 -3
- package/dist/hostPatcher/utils/anchors.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/overlays/recipeRegistry.d.ts +14 -0
- package/dist/overlays/recipeRegistry.js +32 -0
- package/dist/overlays/recipeRegistry.js.map +1 -0
- package/dist/overlays/runtime/index.d.ts +1 -0
- package/dist/overlays/runtime/index.js +1 -0
- package/dist/overlays/runtime/index.js.map +1 -1
- package/dist/overlays/runtime/overlay/modal.d.ts +11 -0
- package/dist/overlays/runtime/overlay/modal.js +78 -0
- package/dist/overlays/runtime/overlay/modal.js.map +1 -0
- package/dist/overlays/runtime/overlay/root.js +132 -0
- package/dist/overlays/runtime/overlay/root.js.map +1 -1
- package/dist/overlays/runtime/overlay/runner.d.ts +2 -0
- package/dist/overlays/runtime/overlay/runner.js +441 -2
- package/dist/overlays/runtime/overlay/runner.js.map +1 -1
- package/dist/overlays/runtime/overlay/tooltip.d.ts +1 -0
- package/dist/overlays/runtime/overlay/tooltip.js +61 -1
- package/dist/overlays/runtime/overlay/tooltip.js.map +1 -1
- package/dist/overlays/schema.d.ts +6 -6
- package/dist/overlays/types.d.ts +55 -1
- package/dist/react.d.ts +6 -1
- package/dist/react.js +31 -9
- package/dist/react.js.map +1 -1
- package/dist/render/RenderContext.d.ts +39 -0
- package/dist/render/RenderContext.js +67 -0
- package/dist/render/RenderContext.js.map +1 -0
- package/dist/render/index.d.ts +3 -0
- package/dist/render/index.js +3 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/types.d.ts +81 -0
- package/dist/render/types.js +2 -0
- package/dist/render/types.js.map +1 -0
- package/dist/smart-canvas.esm.js +192 -25
- package/dist/smart-canvas.esm.js.map +4 -4
- package/dist/smart-canvas.js +25962 -26846
- package/dist/smart-canvas.js.map +4 -4
- package/dist/smart-canvas.min.js +192 -25
- package/dist/smart-canvas.min.js.map +4 -4
- package/dist/telemetry/adapters/posthog.d.ts +6 -0
- package/dist/telemetry/adapters/posthog.js +48 -0
- package/dist/telemetry/adapters/posthog.js.map +1 -1
- package/dist/telemetry/types.d.ts +30 -0
- package/dist/theme/ThemeProvider.d.ts +31 -0
- package/dist/theme/ThemeProvider.js +109 -0
- package/dist/theme/ThemeProvider.js.map +1 -0
- package/dist/theme/defaultTheme.d.ts +18 -0
- package/dist/theme/defaultTheme.js +163 -0
- package/dist/theme/defaultTheme.js.map +1 -0
- package/dist/theme/extractHostTheme.d.ts +14 -0
- package/dist/theme/extractHostTheme.js +261 -0
- package/dist/theme/extractHostTheme.js.map +1 -0
- package/dist/theme/index.d.ts +5 -0
- package/dist/theme/index.js +7 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/types.d.ts +91 -0
- package/dist/theme/types.js +6 -0
- package/dist/theme/types.js.map +1 -0
- package/dist/token.d.ts +4 -0
- package/dist/token.js.map +1 -1
- package/dist/types.d.ts +228 -47
- package/package.json +8 -4
- package/schema/canvas-config.schema.json +24 -15
- package/dist/components/RectangleCard.js.map +0 -1
- package/dist/components/RectangleWheel.d.ts +0 -8
- package/dist/components/RectangleWheel.js.map +0 -1
package/dist/editorLoader.js
CHANGED
|
@@ -5,32 +5,54 @@ export const DEFAULT_EDITOR_URL = "https://cdn.syntrologie.com/editor-sdk/latest
|
|
|
5
5
|
*/
|
|
6
6
|
const ALLOWED_EDITOR_HOSTS = [
|
|
7
7
|
'cdn.syntrologie.com',
|
|
8
|
+
'api.syntrologie.com',
|
|
9
|
+
'dev-api.syntrologie.com',
|
|
8
10
|
'localhost',
|
|
9
|
-
'127.0.0.1'
|
|
11
|
+
'127.0.0.1',
|
|
12
|
+
// Allow any .syntrologie.com subdomain for dev/staging
|
|
13
|
+
'.syntrologie.com',
|
|
10
14
|
];
|
|
11
15
|
/**
|
|
12
16
|
* Validates that an editor URL is from an allowed host.
|
|
13
17
|
* Requires HTTPS for non-localhost URLs.
|
|
14
18
|
*/
|
|
15
19
|
function validateEditorUrl(url) {
|
|
20
|
+
console.log('[Syntro Runtime] Validating editor URL:', url);
|
|
16
21
|
try {
|
|
17
22
|
const parsed = new URL(url);
|
|
18
23
|
const isLocalhost = /^(localhost|127\.0\.0\.1)$/.test(parsed.hostname);
|
|
24
|
+
console.log('[Syntro Runtime] Parsed URL:', {
|
|
25
|
+
hostname: parsed.hostname,
|
|
26
|
+
protocol: parsed.protocol,
|
|
27
|
+
isLocalhost,
|
|
28
|
+
});
|
|
19
29
|
// Require HTTPS for non-localhost
|
|
20
30
|
if (parsed.protocol !== 'https:' && !isLocalhost) {
|
|
21
|
-
console.warn('[Syntro Runtime] Editor URL must use HTTPS:', url);
|
|
31
|
+
console.warn('[Syntro Runtime] ❌ Editor URL must use HTTPS:', url);
|
|
22
32
|
return false;
|
|
23
33
|
}
|
|
24
|
-
// Check against allowlist
|
|
25
|
-
const isAllowed = ALLOWED_EDITOR_HOSTS.some(host =>
|
|
34
|
+
// Check against allowlist - handle both exact match and suffix match
|
|
35
|
+
const isAllowed = ALLOWED_EDITOR_HOSTS.some(host => {
|
|
36
|
+
if (host.startsWith('.')) {
|
|
37
|
+
// Suffix match for wildcards like '.syntrologie.com'
|
|
38
|
+
return parsed.hostname.endsWith(host) || parsed.hostname === host.slice(1);
|
|
39
|
+
}
|
|
40
|
+
return parsed.hostname === host;
|
|
41
|
+
});
|
|
42
|
+
console.log('[Syntro Runtime] Host allowlist check:', {
|
|
43
|
+
hostname: parsed.hostname,
|
|
44
|
+
allowedHosts: ALLOWED_EDITOR_HOSTS,
|
|
45
|
+
isAllowed,
|
|
46
|
+
});
|
|
26
47
|
if (!isAllowed) {
|
|
27
|
-
console.warn('[Syntro Runtime] Editor URL host not in allowlist:', parsed.hostname);
|
|
48
|
+
console.warn('[Syntro Runtime] ❌ Editor URL host not in allowlist:', parsed.hostname);
|
|
28
49
|
return false;
|
|
29
50
|
}
|
|
51
|
+
console.log('[Syntro Runtime] ✓ Editor URL validated');
|
|
30
52
|
return true;
|
|
31
53
|
}
|
|
32
|
-
catch {
|
|
33
|
-
console.warn('[Syntro Runtime] Invalid editor URL:', url);
|
|
54
|
+
catch (e) {
|
|
55
|
+
console.warn('[Syntro Runtime] ❌ Invalid editor URL:', url, e);
|
|
34
56
|
return false;
|
|
35
57
|
}
|
|
36
58
|
}
|
|
@@ -39,17 +61,34 @@ function validateEditorUrl(url) {
|
|
|
39
61
|
* Requires editor_token parameter for security (not just syntro_editor flag).
|
|
40
62
|
*/
|
|
41
63
|
export const shouldLoadEditor = () => {
|
|
42
|
-
|
|
64
|
+
var _a;
|
|
65
|
+
console.log('[Syntro Runtime] ====== EDITOR LOAD CHECK ======');
|
|
66
|
+
if (typeof window === "undefined") {
|
|
67
|
+
console.log('[Syntro Runtime] Not in browser - skipping editor');
|
|
43
68
|
return false;
|
|
69
|
+
}
|
|
44
70
|
const params = new URLSearchParams(window.location.search);
|
|
71
|
+
console.log('[Syntro Runtime] URL:', window.location.href);
|
|
72
|
+
console.log('[Syntro Runtime] Search params:', window.location.search);
|
|
45
73
|
// Require editor_token for security - prevents arbitrary editor activation
|
|
46
74
|
const hasEditorFlag = params.has("syntro_editor") || params.has("syntro-editor");
|
|
47
75
|
const hasEditorToken = params.has("editor_token");
|
|
76
|
+
console.log('[Syntro Runtime] Editor flags:', {
|
|
77
|
+
hasEditorFlag,
|
|
78
|
+
hasEditorToken,
|
|
79
|
+
syntro_editor: params.get("syntro_editor"),
|
|
80
|
+
"syntro-editor": params.get("syntro-editor"),
|
|
81
|
+
editor_token: hasEditorToken ? `${(_a = params.get("editor_token")) === null || _a === void 0 ? void 0 : _a.slice(0, 10)}...` : 'none',
|
|
82
|
+
});
|
|
48
83
|
if (hasEditorFlag && !hasEditorToken) {
|
|
49
|
-
console.warn('[Syntro Runtime] Editor activation requires editor_token parameter');
|
|
84
|
+
console.warn('[Syntro Runtime] ❌ Editor activation requires editor_token parameter');
|
|
85
|
+
console.log('[Syntro Runtime] ================================');
|
|
50
86
|
return false;
|
|
51
87
|
}
|
|
52
|
-
|
|
88
|
+
const shouldLoad = hasEditorFlag && hasEditorToken;
|
|
89
|
+
console.log('[Syntro Runtime] Should load editor:', shouldLoad);
|
|
90
|
+
console.log('[Syntro Runtime] ================================');
|
|
91
|
+
return shouldLoad;
|
|
53
92
|
};
|
|
54
93
|
/**
|
|
55
94
|
* Dynamically loads the Editor SDK script.
|
|
@@ -57,21 +96,32 @@ export const shouldLoadEditor = () => {
|
|
|
57
96
|
*/
|
|
58
97
|
export const loadEditorSdk = async (editorUrlOrOptions) => {
|
|
59
98
|
var _a;
|
|
60
|
-
|
|
99
|
+
console.log('[Syntro Runtime] ====== LOAD EDITOR SDK ======');
|
|
100
|
+
if (typeof window === "undefined") {
|
|
101
|
+
console.log('[Syntro Runtime] Not in browser - skipping editor SDK load');
|
|
61
102
|
return;
|
|
62
|
-
|
|
63
|
-
|
|
103
|
+
}
|
|
104
|
+
if (window.SyntroEditor) {
|
|
105
|
+
console.log('[Syntro Runtime] Editor SDK already loaded (window.SyntroEditor exists)');
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
64
108
|
// Handle both legacy string arg and new options object
|
|
65
109
|
const options = typeof editorUrlOrOptions === 'string'
|
|
66
110
|
? { editorUrl: editorUrlOrOptions }
|
|
67
111
|
: editorUrlOrOptions !== null && editorUrlOrOptions !== void 0 ? editorUrlOrOptions : {};
|
|
68
112
|
const editorUrl = (_a = options.editorUrl) !== null && _a !== void 0 ? _a : DEFAULT_EDITOR_URL;
|
|
113
|
+
console.log('[Syntro Runtime] Editor URL:', editorUrl);
|
|
114
|
+
console.log('[Syntro Runtime] Options:', {
|
|
115
|
+
hasIntegrity: !!options.integrity,
|
|
116
|
+
isDefault: editorUrl === DEFAULT_EDITOR_URL,
|
|
117
|
+
});
|
|
69
118
|
// Security: Validate URL against allowlist
|
|
70
119
|
if (!validateEditorUrl(editorUrl)) {
|
|
71
|
-
console.error('[Syntro Runtime]
|
|
120
|
+
console.error('[Syntro Runtime] ❌ BLOCKED: Editor from untrusted URL:', editorUrl);
|
|
121
|
+
console.log('[Syntro Runtime] ================================');
|
|
72
122
|
return;
|
|
73
123
|
}
|
|
74
|
-
console.log(
|
|
124
|
+
console.log('[Syntro Runtime] ✓ URL validated, injecting script tag...');
|
|
75
125
|
return new Promise((resolve, reject) => {
|
|
76
126
|
const script = document.createElement("script");
|
|
77
127
|
script.src = editorUrl;
|
|
@@ -80,16 +130,23 @@ export const loadEditorSdk = async (editorUrlOrOptions) => {
|
|
|
80
130
|
if (options.integrity) {
|
|
81
131
|
script.integrity = options.integrity;
|
|
82
132
|
script.crossOrigin = "anonymous";
|
|
133
|
+
console.log('[Syntro Runtime] SRI integrity check enabled');
|
|
83
134
|
}
|
|
84
135
|
script.onload = () => {
|
|
85
|
-
console.log(
|
|
136
|
+
console.log('[Syntro Runtime] ✓ Editor SDK script loaded successfully');
|
|
137
|
+
console.log('[Syntro Runtime] window.SyntroEditor:', !!window.SyntroEditor);
|
|
138
|
+
console.log('[Syntro Runtime] ================================');
|
|
86
139
|
resolve();
|
|
87
140
|
};
|
|
88
141
|
script.onerror = (err) => {
|
|
89
|
-
console.error(
|
|
142
|
+
console.error('[Syntro Runtime] ❌ Failed to load Editor SDK:', err);
|
|
143
|
+
console.error('[Syntro Runtime] URL attempted:', editorUrl);
|
|
144
|
+
console.error('[Syntro Runtime] Check: Is the URL accessible? CORS? Network?');
|
|
145
|
+
console.log('[Syntro Runtime] ================================');
|
|
90
146
|
reject(err);
|
|
91
147
|
};
|
|
92
148
|
document.head.appendChild(script);
|
|
149
|
+
console.log('[Syntro Runtime] Script tag appended to <head>');
|
|
93
150
|
});
|
|
94
151
|
};
|
|
95
152
|
//# sourceMappingURL=editorLoader.js.map
|
package/dist/editorLoader.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editorLoader.js","sourceRoot":"","sources":["../src/editorLoader.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,kBAAkB,GAAG,6DAA6D,CAAC;AAEhG;;;GAGG;AACH,MAAM,oBAAoB,GAAG;IAC3B,qBAAqB;IACrB,WAAW;IACX,WAAW;
|
|
1
|
+
{"version":3,"file":"editorLoader.js","sourceRoot":"","sources":["../src/editorLoader.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,11 @@
|
|
|
7
7
|
import { GrowthBook } from "@growthbook/growthbook-react";
|
|
8
8
|
import type { Context as GrowthBookInitOptions } from "@growthbook/growthbook";
|
|
9
9
|
import type { ExperimentClient } from "../types";
|
|
10
|
-
import type {
|
|
10
|
+
import type { TileConfig } from "../../types";
|
|
11
|
+
/**
|
|
12
|
+
* Callback fired when a user is assigned to an experiment.
|
|
13
|
+
*/
|
|
14
|
+
export type ExperimentTrackingCallback = (experimentKey: string, variationId: number, variationName: string) => void;
|
|
11
15
|
/**
|
|
12
16
|
* Default API host for GrowthBook experiments.
|
|
13
17
|
*/
|
|
@@ -22,6 +26,17 @@ export interface GrowthBookAdapterOptions extends GrowthBookInitOptions {
|
|
|
22
26
|
* Auto-initialize with streaming enabled.
|
|
23
27
|
*/
|
|
24
28
|
autoInit?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Enable dev mode for URL parameter overrides and forced variations.
|
|
31
|
+
* When true, allows ?syntro_exp=xxx&syntro_var=N to force specific variations.
|
|
32
|
+
* @default true
|
|
33
|
+
*/
|
|
34
|
+
enableDevMode?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Callback fired when a user is assigned to an experiment.
|
|
37
|
+
* Use this to send experiment data to your analytics provider.
|
|
38
|
+
*/
|
|
39
|
+
onExperimentViewed?: ExperimentTrackingCallback;
|
|
25
40
|
}
|
|
26
41
|
/**
|
|
27
42
|
* Internal adapter that implements ExperimentClient using GrowthBook.
|
|
@@ -36,8 +51,9 @@ export declare class GrowthBookAdapter implements ExperimentClient {
|
|
|
36
51
|
get _internal(): GrowthBook;
|
|
37
52
|
refreshFeatures(): Promise<void>;
|
|
38
53
|
setAttributes(attrs: Record<string, unknown>): void;
|
|
54
|
+
setForcedVariations(variations: Record<string, number>): void;
|
|
39
55
|
getFeatureValue<T>(key: string, fallback: T): T;
|
|
40
|
-
shouldRenderRectangle(
|
|
56
|
+
shouldRenderRectangle(tile: TileConfig): boolean;
|
|
41
57
|
}
|
|
42
58
|
/**
|
|
43
59
|
* Create an ExperimentClient backed by GrowthBook.
|
|
@@ -14,14 +14,25 @@ export const DEFAULT_EXPERIMENT_API_HOST = "https://experiment.syntrologie.com";
|
|
|
14
14
|
*/
|
|
15
15
|
export class GrowthBookAdapter {
|
|
16
16
|
constructor(options = {}) {
|
|
17
|
-
var _a;
|
|
17
|
+
var _a, _b;
|
|
18
18
|
if (options.client) {
|
|
19
19
|
this.gb = options.client;
|
|
20
20
|
}
|
|
21
21
|
else {
|
|
22
|
+
// Set up tracking callback to bridge to telemetry
|
|
23
|
+
const trackingCallback = options.onExperimentViewed
|
|
24
|
+
? (experiment, result) => {
|
|
25
|
+
options.onExperimentViewed(experiment.key, result.variationId, typeof result.value === "string" ? result.value : `variation_${result.variationId}`);
|
|
26
|
+
}
|
|
27
|
+
: undefined;
|
|
22
28
|
this.gb = new GrowthBook({
|
|
23
29
|
...options,
|
|
24
30
|
apiHost: (_a = options.apiHost) !== null && _a !== void 0 ? _a : DEFAULT_EXPERIMENT_API_HOST,
|
|
31
|
+
// Enable dev mode for URL param overrides (?syntro_exp=xxx&syntro_var=N)
|
|
32
|
+
// Set to false in production if you want to disable preview functionality
|
|
33
|
+
enableDevMode: (_b = options.enableDevMode) !== null && _b !== void 0 ? _b : true,
|
|
34
|
+
// Wire up experiment tracking callback
|
|
35
|
+
trackingCallback,
|
|
25
36
|
});
|
|
26
37
|
if (options.autoInit) {
|
|
27
38
|
this.gb.init({ streaming: true });
|
|
@@ -41,11 +52,14 @@ export class GrowthBookAdapter {
|
|
|
41
52
|
setAttributes(attrs) {
|
|
42
53
|
this.gb.setAttributes(attrs);
|
|
43
54
|
}
|
|
55
|
+
setForcedVariations(variations) {
|
|
56
|
+
this.gb.setForcedVariations(variations);
|
|
57
|
+
}
|
|
44
58
|
getFeatureValue(key, fallback) {
|
|
45
59
|
return this.gb.getFeatureValue(key, fallback);
|
|
46
60
|
}
|
|
47
|
-
shouldRenderRectangle(
|
|
48
|
-
const experiment =
|
|
61
|
+
shouldRenderRectangle(tile) {
|
|
62
|
+
const experiment = tile.experiment;
|
|
49
63
|
if (!experiment)
|
|
50
64
|
return true;
|
|
51
65
|
if (!experiment.featureKey)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"growthbook.js","sourceRoot":"","sources":["../../../src/experiments/adapters/growthbook.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"growthbook.js","sourceRoot":"","sources":["../../../src/experiments/adapters/growthbook.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Experiment provider registry.
|
|
3
|
+
*
|
|
4
|
+
* Maps provider names to their adapter factories.
|
|
5
|
+
* This allows the bootstrap module to dynamically create
|
|
6
|
+
* experiment clients based on token configuration.
|
|
7
|
+
*/
|
|
8
|
+
import { ExperimentTrackingCallback } from "./adapters/growthbook";
|
|
1
9
|
import type { ExperimentClient } from "./types";
|
|
10
|
+
export interface CreateExperimentClientConfig {
|
|
11
|
+
clientKey: string;
|
|
12
|
+
apiHost?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Callback fired when a user is assigned to an experiment.
|
|
15
|
+
* Use this to send experiment data to your analytics provider.
|
|
16
|
+
*/
|
|
17
|
+
onExperimentViewed?: ExperimentTrackingCallback;
|
|
18
|
+
}
|
|
2
19
|
/**
|
|
3
20
|
* Create an experiment client for the specified provider.
|
|
4
21
|
*
|
|
@@ -7,7 +24,4 @@ import type { ExperimentClient } from "./types";
|
|
|
7
24
|
* @returns An ExperimentClient instance
|
|
8
25
|
* @throws Error if the provider is not supported
|
|
9
26
|
*/
|
|
10
|
-
export declare function createExperimentClient(provider: string, config:
|
|
11
|
-
clientKey: string;
|
|
12
|
-
apiHost?: string;
|
|
13
|
-
}): ExperimentClient;
|
|
27
|
+
export declare function createExperimentClient(provider: string, config: CreateExperimentClientConfig): ExperimentClient;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* This allows the bootstrap module to dynamically create
|
|
6
6
|
* experiment clients based on token configuration.
|
|
7
7
|
*/
|
|
8
|
-
import { createGrowthBookClient } from "./adapters/growthbook";
|
|
8
|
+
import { createGrowthBookClient, } from "./adapters/growthbook";
|
|
9
9
|
const adapters = {
|
|
10
10
|
growthbook: (config) => createGrowthBookClient({
|
|
11
11
|
...config,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/experiments/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/experiments/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,sBAAsB,GAGvB,MAAM,uBAAuB,CAAC;AAK/B,MAAM,QAAQ,GAAmC;IAC/C,UAAU,EAAE,CAAC,MAAgC,EAAE,EAAE,CAC/C,sBAAsB,CAAC;QACrB,GAAG,MAAM;QACT,QAAQ,EAAE,IAAI;KACf,CAAC;CACL,CAAC;AAYF;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACpC,QAAgB,EAChB,MAAoC;IAEpC,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,gCAAgC,QAAQ,gBAAgB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC3F,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;AACzB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { TileConfig } from "../types";
|
|
2
2
|
/**
|
|
3
3
|
* Clean interface for experiment/feature flag clients.
|
|
4
4
|
*
|
|
@@ -7,9 +7,9 @@ import type { RectangleConfig } from "../types";
|
|
|
7
7
|
*/
|
|
8
8
|
export interface ExperimentClient {
|
|
9
9
|
/**
|
|
10
|
-
* Check if a
|
|
10
|
+
* Check if a tile should be rendered based on its experiment config.
|
|
11
11
|
*/
|
|
12
|
-
shouldRenderRectangle(
|
|
12
|
+
shouldRenderRectangle(tile: TileConfig): boolean;
|
|
13
13
|
/**
|
|
14
14
|
* Get a feature flag value.
|
|
15
15
|
*/
|
|
@@ -18,6 +18,11 @@ export interface ExperimentClient {
|
|
|
18
18
|
* Update user/device attributes for targeting.
|
|
19
19
|
*/
|
|
20
20
|
setAttributes?(attrs: Record<string, unknown>): void;
|
|
21
|
+
/**
|
|
22
|
+
* Force specific experiment variations for preview/testing.
|
|
23
|
+
* @param variations Map of experiment tracking key to variation index
|
|
24
|
+
*/
|
|
25
|
+
setForcedVariations?(variations: Record<string, number>): void;
|
|
21
26
|
}
|
|
22
27
|
/**
|
|
23
28
|
* @deprecated Use ExperimentClient instead
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cdnFetcher.js","sourceRoot":"","sources":["../../src/fetchers/cdnFetcher.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,iBAAiB,GAAG;IACxB,qBAAqB;IACrB,WAAW;IACX,WAAW;CACZ,CAAC;AAoBF;;GAEG;AACH,SAAS,cAAc,CAAC,GAAW;IACjC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,WAAW,GAAG,4BAA4B,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEvE,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,WAAW,EAAE,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,uCAAuC,EAAE,GAAG,CAAC,CAAC;YAC3D,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC;QAC3E,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,0CAA0C,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC1E,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,gCAAgC,EAAE,GAAG,CAAC,CAAC;QACpD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,UAAU;IAMrB,YAAY,OAA0B;QAL7B,SAAI,GAAG,KAAK,CAAC;QAMpB,IAAI,CAAC,GAAG,GAAG,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,QAAQ,OAAO,CAAC;QACzD,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QAEnC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,sCAAsC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;;QACT,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAEhC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;YACrC,WAAW,EAAE,MAAM,EAAE,4BAA4B;YACjD,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,kDAAkD,QAAQ,CAAC,MAAM,GAAG,CACrE,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEnC,+BAA+B;QAC/B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YACvD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CACb,yDAAyD,QAAQ,SAAS,IAAI,EAAE,CACjF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,
|
|
1
|
+
{"version":3,"file":"cdnFetcher.js","sourceRoot":"","sources":["../../src/fetchers/cdnFetcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL parameters for forcing experiment variations in preview mode.
|
|
3
|
+
* Usage: ?syntro_exp=experiment_tracking_key&syntro_var=1
|
|
4
|
+
*/
|
|
5
|
+
const PREVIEW_EXP_PARAM = "syntro_exp";
|
|
6
|
+
const PREVIEW_VAR_PARAM = "syntro_var";
|
|
1
7
|
/**
|
|
2
8
|
* Fetches config from an experiment/feature flag system.
|
|
3
9
|
*
|
|
@@ -17,6 +23,20 @@ export class ExperimentsFetcher {
|
|
|
17
23
|
async fetch() {
|
|
18
24
|
var _a, _b;
|
|
19
25
|
const start = performance.now();
|
|
26
|
+
// Check for preview URL params to force a specific variation
|
|
27
|
+
if (typeof window !== "undefined") {
|
|
28
|
+
const params = new URLSearchParams(window.location.search);
|
|
29
|
+
const expName = params.get(PREVIEW_EXP_PARAM);
|
|
30
|
+
const varIndex = params.get(PREVIEW_VAR_PARAM);
|
|
31
|
+
if (expName && varIndex !== null && this.client.setForcedVariations) {
|
|
32
|
+
const index = parseInt(varIndex, 10);
|
|
33
|
+
if (!isNaN(index)) {
|
|
34
|
+
console.log(`[SmartCanvas] Preview mode: forcing "${expName}" to variation ${index}`);
|
|
35
|
+
this.client.setForcedVariations({ [expName]: index });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Get config from experiment client (GrowthBook feature flag)
|
|
20
40
|
const config = (_b = (_a = this.client).getFeatureValue) === null || _b === void 0 ? void 0 : _b.call(_a, this.featureKey, null);
|
|
21
41
|
if (!config || typeof config !== "object") {
|
|
22
42
|
throw new Error(`[SmartCanvas] Feature "${this.featureKey}" not found or invalid. ` +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"experimentsFetcher.js","sourceRoot":"","sources":["../../src/fetchers/experimentsFetcher.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"experimentsFetcher.js","sourceRoot":"","sources":["../../src/fetchers/experimentsFetcher.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,iBAAiB,GAAG,YAAY,CAAC;AACvC,MAAM,iBAAiB,GAAG,YAAY,CAAC;AAevC;;;;;;;;GAQG;AACH,MAAM,OAAO,kBAAkB;IAM7B,YAAY,OAAkC;;QALrC,SAAI,GAAG,aAAa,CAAC;QAM5B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,MAAA,OAAO,CAAC,UAAU,mCAAI,qBAAqB,CAAC;IAChE,CAAC;IAED,KAAK,CAAC,KAAK;;QACT,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAEhC,6DAA6D;QAC7D,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;YAC9C,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;YAE/C,IAAI,OAAO,IAAI,QAAQ,KAAK,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;gBACpE,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBACrC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;oBAClB,OAAO,CAAC,GAAG,CAAC,wCAAwC,OAAO,kBAAkB,KAAK,EAAE,CAAC,CAAC;oBACtF,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;gBACxD,CAAC;YACH,CAAC;QACH,CAAC;QAED,8DAA8D;QAC9D,MAAM,MAAM,GAAG,MAAA,MAAA,IAAI,CAAC,MAAM,EAAC,eAAe,mDAAG,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAEpE,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CACb,0BAA0B,IAAI,CAAC,UAAU,0BAA0B;gBACnE,+DAA+D,CAChE,CAAC;QACJ,CAAC;QAED,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QAE9C,OAAO;YACL,MAAM,EAAE,MAA8B;YACtC,IAAI,EAAE;gBACJ,MAAM,EAAE,aAAa;gBACrB,WAAW;gBACX,MAAM,EAAE,IAAI;aACb;SACF,CAAC;IACJ,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CACtC,OAAkC;IAElC,OAAO,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;AACzC,CAAC"}
|
package/dist/fetchers/types.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CanvasConfigResponse } from "../types";
|
|
2
2
|
/**
|
|
3
3
|
* Result from a config fetch, including timing metadata.
|
|
4
4
|
*/
|
|
5
5
|
export interface FetchResult {
|
|
6
|
-
config:
|
|
6
|
+
config: CanvasConfigResponse;
|
|
7
7
|
meta: {
|
|
8
8
|
source: 'experiments' | 'cdn' | 'cache';
|
|
9
9
|
fetchTimeMs: number;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import type { ExperimentClient } from "../experiments/types";
|
|
2
2
|
import type { TelemetryClient } from "../telemetry/types";
|
|
3
3
|
import { type OverlayRecipeFetcher } from "../overlays/fetcher";
|
|
4
|
+
import type { CanvasRecipe } from "../overlays/types";
|
|
5
|
+
export type OverlayRecipesFetcher = () => Promise<CanvasRecipe[] | CanvasRecipe | undefined>;
|
|
4
6
|
export interface UseCanvasOverlaysOptions {
|
|
5
7
|
fetcher?: OverlayRecipeFetcher;
|
|
8
|
+
/** Fetcher that returns multiple recipes */
|
|
9
|
+
recipesFetcher?: OverlayRecipesFetcher;
|
|
6
10
|
configUri?: string;
|
|
7
11
|
featureKey?: string;
|
|
8
12
|
credentials?: RequestCredentials;
|
|
@@ -10,4 +14,4 @@ export interface UseCanvasOverlaysOptions {
|
|
|
10
14
|
telemetry?: TelemetryClient;
|
|
11
15
|
canvasHost?: HTMLElement | null;
|
|
12
16
|
}
|
|
13
|
-
export declare function useCanvasOverlays({ fetcher, configUri, featureKey, credentials, experiments, telemetry, canvasHost, }: UseCanvasOverlaysOptions): void;
|
|
17
|
+
export declare function useCanvasOverlays({ fetcher, recipesFetcher, configUri, featureKey, credentials, experiments, telemetry, canvasHost, }: UseCanvasOverlaysOptions): void;
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { useEffect, useMemo } from "react";
|
|
2
2
|
import { createOverlayRecipeFetcher } from "../overlays/fetcher";
|
|
3
3
|
import { CanvasRecipeZ } from "../overlays/schema";
|
|
4
|
-
|
|
4
|
+
import { registerRecipes, clearRecipes } from "../overlays/recipeRegistry";
|
|
5
|
+
export function useCanvasOverlays({ fetcher, recipesFetcher, configUri, featureKey, credentials, experiments, telemetry, canvasHost, }) {
|
|
5
6
|
const derivedFetcher = useMemo(() => {
|
|
6
|
-
// Priority 1: Use explicit fetcher if provided
|
|
7
|
+
// Priority 1: Use explicit recipes fetcher if provided (for multiple recipes)
|
|
8
|
+
if (recipesFetcher)
|
|
9
|
+
return recipesFetcher;
|
|
10
|
+
// Priority 2: Use explicit single fetcher if provided
|
|
7
11
|
if (fetcher)
|
|
8
12
|
return fetcher;
|
|
9
|
-
// Priority
|
|
10
|
-
// (inline recipes are passed via the fetcher prop, not configUri)
|
|
13
|
+
// Priority 3: Only create a fetcher if we have an explicit configUri
|
|
11
14
|
if (configUri) {
|
|
12
15
|
return createOverlayRecipeFetcher({
|
|
13
16
|
configUri,
|
|
@@ -17,34 +20,50 @@ export function useCanvasOverlays({ fetcher, configUri, featureKey, credentials,
|
|
|
17
20
|
validator: CanvasRecipeZ,
|
|
18
21
|
});
|
|
19
22
|
}
|
|
20
|
-
// No fetcher and no configUri = no overlays
|
|
23
|
+
// No fetcher and no configUri = no overlays
|
|
21
24
|
return undefined;
|
|
22
|
-
}, [fetcher, configUri, experiments, featureKey, credentials]);
|
|
25
|
+
}, [fetcher, recipesFetcher, configUri, experiments, featureKey, credentials]);
|
|
23
26
|
useEffect(() => {
|
|
24
27
|
if (!derivedFetcher)
|
|
25
28
|
return;
|
|
26
29
|
let cancelled = false;
|
|
27
|
-
let
|
|
30
|
+
let cleanups = [];
|
|
28
31
|
(async () => {
|
|
29
|
-
var _a;
|
|
32
|
+
var _a, _b;
|
|
30
33
|
try {
|
|
31
|
-
const
|
|
32
|
-
if (!
|
|
34
|
+
const result = await derivedFetcher();
|
|
35
|
+
if (!result || cancelled)
|
|
33
36
|
return;
|
|
37
|
+
// Normalize to array of recipes
|
|
38
|
+
const recipes = Array.isArray(result) ? result : [result];
|
|
39
|
+
if (!recipes.length)
|
|
40
|
+
return;
|
|
41
|
+
// Register recipes so TileCard can look them up for navigation
|
|
42
|
+
registerRecipes(recipes);
|
|
34
43
|
const mod = await import("../overlays/runtime");
|
|
35
44
|
const overlayRoot = mod.ensureOverlayRoot();
|
|
36
45
|
const resolve = mod.createAnchorResolver({ canvasHost });
|
|
37
|
-
|
|
46
|
+
const ctx = {
|
|
38
47
|
overlayRoot,
|
|
39
48
|
resolve,
|
|
40
49
|
canvasHost,
|
|
50
|
+
telemetry: telemetry ? {
|
|
51
|
+
setPersonPropertiesOnce: (_a = telemetry.setPersonPropertiesOnce) === null || _a === void 0 ? void 0 : _a.bind(telemetry),
|
|
52
|
+
} : undefined,
|
|
41
53
|
onEvent: (name, payload) => {
|
|
42
54
|
var _a, _b;
|
|
43
55
|
if (!telemetry)
|
|
44
56
|
return;
|
|
45
57
|
(_a = telemetry.trackAction) === null || _a === void 0 ? void 0 : _a.call(telemetry, name, (_b = payload === null || payload === void 0 ? void 0 : payload.stepId) !== null && _b !== void 0 ? _b : "", "overlay");
|
|
46
58
|
},
|
|
47
|
-
}
|
|
59
|
+
};
|
|
60
|
+
// Run all recipes
|
|
61
|
+
for (const recipe of recipes) {
|
|
62
|
+
if (!((_b = recipe === null || recipe === void 0 ? void 0 : recipe.steps) === null || _b === void 0 ? void 0 : _b.length) || cancelled)
|
|
63
|
+
continue;
|
|
64
|
+
const cleanup = await mod.runOverlays(recipe, ctx);
|
|
65
|
+
cleanups.push(cleanup);
|
|
66
|
+
}
|
|
48
67
|
}
|
|
49
68
|
catch (err) {
|
|
50
69
|
console.warn("[SmartCanvas] overlays failed", err);
|
|
@@ -52,7 +71,8 @@ export function useCanvasOverlays({ fetcher, configUri, featureKey, credentials,
|
|
|
52
71
|
})();
|
|
53
72
|
return () => {
|
|
54
73
|
cancelled = true;
|
|
55
|
-
|
|
74
|
+
cleanups.forEach(fn => fn === null || fn === void 0 ? void 0 : fn());
|
|
75
|
+
clearRecipes();
|
|
56
76
|
};
|
|
57
77
|
}, [derivedFetcher, telemetry, canvasHost]);
|
|
58
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCanvasOverlays.js","sourceRoot":"","sources":["../../src/hooks/useCanvasOverlays.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAG3C,OAAO,EAAE,0BAA0B,EAA6B,MAAM,qBAAqB,CAAC;AAE5F,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"useCanvasOverlays.js","sourceRoot":"","sources":["../../src/hooks/useCanvasOverlays.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAG3C,OAAO,EAAE,0BAA0B,EAA6B,MAAM,qBAAqB,CAAC;AAE5F,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAgB3E,MAAM,UAAU,iBAAiB,CAAC,EAChC,OAAO,EACP,cAAc,EACd,SAAS,EACT,UAAU,EACV,WAAW,EACX,WAAW,EACX,SAAS,EACT,UAAU,GACe;IACzB,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,EAAE;QAClC,8EAA8E;QAC9E,IAAI,cAAc;YAAE,OAAO,cAAc,CAAC;QAE1C,sDAAsD;QACtD,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAE5B,qEAAqE;QACrE,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,0BAA0B,CAAC;gBAChC,SAAS;gBACT,WAAW;gBACX,UAAU;gBACV,WAAW;gBACX,SAAS,EAAE,aAAa;aACqC,CAAC,CAAC;QACnE,CAAC;QAED,4CAA4C;QAC5C,OAAO,SAAS,CAAC;IACnB,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;IAE/E,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,cAAc;YAAE,OAAO;QAC5B,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,IAAI,QAAQ,GAAsB,EAAE,CAAC;QAErC,CAAC,KAAK,IAAI,EAAE;;YACV,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;gBACtC,IAAI,CAAC,MAAM,IAAI,SAAS;oBAAE,OAAO;gBAEjC,gCAAgC;gBAChC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;gBAC1D,IAAI,CAAC,OAAO,CAAC,MAAM;oBAAE,OAAO;gBAE5B,+DAA+D;gBAC/D,eAAe,CAAC,OAAyB,CAAC,CAAC;gBAE3C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;gBAChD,MAAM,WAAW,GAAG,GAAG,CAAC,iBAAiB,EAAE,CAAC;gBAC5C,MAAM,OAAO,GAAG,GAAG,CAAC,oBAAoB,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;gBAEzD,MAAM,GAAG,GAAG;oBACV,WAAW;oBACX,OAAO;oBACP,UAAU;oBACV,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;wBACrB,uBAAuB,EAAE,MAAA,SAAS,CAAC,uBAAuB,0CAAE,IAAI,CAAC,SAAS,CAAC;qBAC5E,CAAC,CAAC,CAAC,SAAS;oBACb,OAAO,EAAE,CAAC,IAAY,EAAE,OAAa,EAAE,EAAE;;wBACvC,IAAI,CAAC,SAAS;4BAAE,OAAO;wBACvB,MAAA,SAAS,CAAC,WAAW,0DAAG,IAAI,EAAE,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,mCAAI,EAAE,EAAE,SAAS,CAAC,CAAC;oBAClE,CAAC;iBACF,CAAC;gBAEF,kBAAkB;gBAClB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;oBAC7B,IAAI,CAAC,CAAA,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,0CAAE,MAAM,CAAA,IAAI,SAAS;wBAAE,SAAS;oBAClD,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,MAAsB,EAAE,GAAG,CAAC,CAAC;oBACnE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC;YACrD,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QAEL,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;YACjB,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,aAAF,EAAE,uBAAF,EAAE,EAAI,CAAC,CAAC;YAC/B,YAAY,EAAE,CAAC;QACjB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,cAAc,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CanvasConfigFetcher,
|
|
1
|
+
import type { CanvasConfigFetcher, TileConfig, CanvasThemeConfig, LauncherConfig } from "../types";
|
|
2
2
|
import type { Patch } from "../hostPatcher/core/types";
|
|
3
3
|
import type { ExperimentClient } from "../experiments/types";
|
|
4
4
|
export interface UseShadowCanvasConfigOptions {
|
|
@@ -7,14 +7,21 @@ export interface UseShadowCanvasConfigOptions {
|
|
|
7
7
|
experiments?: ExperimentClient;
|
|
8
8
|
}
|
|
9
9
|
export interface ShadowCanvasConfigState {
|
|
10
|
-
|
|
10
|
+
tiles: TileConfig[];
|
|
11
11
|
isLoading: boolean;
|
|
12
12
|
error?: string;
|
|
13
13
|
fetchedAt?: string;
|
|
14
14
|
canvasTitle?: string;
|
|
15
15
|
configVersion?: string;
|
|
16
16
|
patches?: Patch[];
|
|
17
|
+
/** @deprecated Use overlayRecipes instead */
|
|
17
18
|
overlayRecipe?: import('../overlays/types').CanvasRecipe;
|
|
19
|
+
/** Multiple overlay recipes (tours) */
|
|
20
|
+
overlayRecipes?: import('../overlays/types').CanvasRecipe[];
|
|
18
21
|
displayMode?: 'standard' | 'focused';
|
|
22
|
+
/** Theme configuration from the canvas config (workspace settings) */
|
|
23
|
+
theme?: CanvasThemeConfig;
|
|
24
|
+
/** Launcher button configuration */
|
|
25
|
+
launcher?: LauncherConfig;
|
|
19
26
|
}
|
|
20
27
|
export declare function useShadowCanvasConfig({ fetcher, pollIntervalMs, experiments, }: UseShadowCanvasConfigOptions): ShadowCanvasConfigState;
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
2
|
-
const
|
|
2
|
+
const sortTiles = (tiles) => [...tiles].sort((a, b) => { var _a, _b; return ((_a = a.order) !== null && _a !== void 0 ? _a : 0) - ((_b = b.order) !== null && _b !== void 0 ? _b : 0); });
|
|
3
3
|
export function useShadowCanvasConfig({ fetcher, pollIntervalMs = 30000, experiments, }) {
|
|
4
4
|
const [state, setState] = useState({
|
|
5
|
-
|
|
5
|
+
tiles: [],
|
|
6
6
|
isLoading: true,
|
|
7
7
|
});
|
|
8
8
|
const load = useCallback(async () => {
|
|
9
9
|
try {
|
|
10
10
|
setState((prev) => ({ ...prev, isLoading: true, error: undefined }));
|
|
11
|
-
// Cast to legacy type which supports both tiles and rectangles
|
|
12
11
|
const response = await fetcher();
|
|
13
|
-
|
|
14
|
-
let rectangles = response.tiles || response.rectangles || [];
|
|
12
|
+
let tiles = response.tiles || [];
|
|
15
13
|
if (experiments) {
|
|
16
|
-
|
|
14
|
+
tiles = tiles.filter((tile) => experiments.shouldRenderRectangle(tile));
|
|
17
15
|
}
|
|
18
16
|
setState({
|
|
19
|
-
|
|
17
|
+
tiles: sortTiles(tiles),
|
|
20
18
|
isLoading: false,
|
|
21
19
|
fetchedAt: response.fetchedAt,
|
|
22
20
|
canvasTitle: response.canvasTitle,
|
|
23
21
|
configVersion: response.configVersion,
|
|
24
22
|
patches: response.patches,
|
|
25
23
|
overlayRecipe: response.overlayRecipe,
|
|
26
|
-
|
|
24
|
+
overlayRecipes: response.overlayRecipes,
|
|
25
|
+
theme: response.theme,
|
|
26
|
+
launcher: response.launcher,
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
29
|
catch (err) {
|