@syntrologie/runtime-sdk 2.10.0 → 2.12.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.
- package/CAPABILITIES.md +176 -117
- package/README.md +2 -0
- package/dist/actions/schema.d.ts +7 -7
- package/dist/actions/schema.js +1 -1
- package/dist/actions/types.d.ts +1 -1
- package/dist/actions/validation-core.d.ts +24 -0
- package/dist/actions/validation-rules.d.ts +74 -0
- package/dist/actions/validation.d.ts +5 -11
- package/dist/bootstrap-init.d.ts +33 -0
- package/dist/bootstrap-runtime.d.ts +7 -0
- package/dist/bootstrap-types.d.ts +90 -0
- package/dist/bootstrap.d.ts +17 -83
- package/dist/{chunk-OIDBMIRB.js → chunk-J2LGX2PV.js} +1282 -488
- package/dist/chunk-J2LGX2PV.js.map +7 -0
- package/dist/{chunk-R5DNAIRI.js → chunk-L6RJMBR2.js} +2 -2
- package/dist/{chunk-R5DNAIRI.js.map → chunk-L6RJMBR2.js.map} +2 -2
- package/dist/events/EventBus.d.ts +27 -1
- package/dist/events/history.d.ts +9 -0
- package/dist/events/index.d.ts +3 -0
- package/dist/events/normalizers/posthog.d.ts +4 -50
- package/dist/events/types.d.ts +30 -23
- package/dist/events/validation.d.ts +7 -0
- package/dist/index.d.ts +0 -2
- package/dist/index.js +1125 -2027
- package/dist/index.js.map +4 -4
- package/dist/overlays/runtime/overlay/overlay-runner.d.ts +4 -0
- package/dist/overlays/runtime/overlay/overlay-state.d.ts +21 -0
- package/dist/overlays/types.d.ts +3 -1
- package/dist/react.js +4 -2
- package/dist/react.js.map +2 -2
- package/dist/smart-canvas.esm.js +92 -108
- package/dist/smart-canvas.esm.js.map +4 -4
- package/dist/smart-canvas.js +5225 -5012
- package/dist/smart-canvas.js.map +4 -4
- package/dist/smart-canvas.min.js +92 -108
- package/dist/smart-canvas.min.js.map +4 -4
- package/dist/telemetry/adapters/posthog.d.ts +30 -4
- package/dist/test/setup.d.ts +1 -0
- package/dist/token.d.ts +2 -0
- package/dist/version.d.ts +1 -1
- package/package.json +23 -28
- package/schema/canvas-config.schema.json +1 -1
- package/scripts/syntroReactPlugin.mjs +3 -0
- package/scripts/validate-config.mjs +42 -0
- package/dist/chunk-OIDBMIRB.js.map +0 -7
|
@@ -127,6 +127,12 @@ function sanitizeHtml(html) {
|
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
|
+
const svgs = Array.from(root.querySelectorAll("svg"));
|
|
131
|
+
for (const svg of svgs) {
|
|
132
|
+
if (toRemove.some((el) => svg.contains(el) && el.tagName.toLowerCase() === "script")) {
|
|
133
|
+
toRemove.push(svg);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
130
136
|
for (const el of toRemove) {
|
|
131
137
|
while (el.firstChild) {
|
|
132
138
|
(_a2 = el.parentNode) == null ? void 0 : _a2.insertBefore(el.firstChild, el);
|
|
@@ -755,6 +761,10 @@ var CelebrationEngine = class {
|
|
|
755
761
|
this.container = null;
|
|
756
762
|
}
|
|
757
763
|
start(container, effect, config) {
|
|
764
|
+
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
765
|
+
if (prefersReducedMotion) {
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
758
768
|
this.container = container;
|
|
759
769
|
this.effect = effect;
|
|
760
770
|
this.duration = config.duration;
|
|
@@ -1398,7 +1408,7 @@ var alert = {
|
|
|
1398
1408
|
var tag = {
|
|
1399
1409
|
content: slateGrey[10],
|
|
1400
1410
|
border: slateGrey[4],
|
|
1401
|
-
background:
|
|
1411
|
+
background: slateGrey[3]
|
|
1402
1412
|
};
|
|
1403
1413
|
var menu = {
|
|
1404
1414
|
backgroundDefault: slateGrey[2],
|
|
@@ -2283,7 +2293,7 @@ function extractWorkflowsFromActive(activeActions) {
|
|
|
2283
2293
|
const workflows = /* @__PURE__ */ new Map();
|
|
2284
2294
|
for (const entry of activeActions) {
|
|
2285
2295
|
const action = entry.action;
|
|
2286
|
-
if (action.kind === "
|
|
2296
|
+
if (action.kind === "overlays:tour" && action.workflow && action.tourId) {
|
|
2287
2297
|
const meta = action.workflow;
|
|
2288
2298
|
const rawSteps = action.steps || [];
|
|
2289
2299
|
const steps = rawSteps.map((s) => {
|
|
@@ -2806,7 +2816,7 @@ var executors2 = [
|
|
|
2806
2816
|
{ kind: "overlays:badge", executor: executeBadge },
|
|
2807
2817
|
{ kind: "overlays:tooltip", executor: executeTooltip },
|
|
2808
2818
|
{ kind: "overlays:modal", executor: executeModal },
|
|
2809
|
-
{ kind: "
|
|
2819
|
+
{ kind: "overlays:tour", executor: executeTour },
|
|
2810
2820
|
{ kind: "overlays:celebrate", executor: executeCelebrate }
|
|
2811
2821
|
];
|
|
2812
2822
|
var runtime2 = {
|
|
@@ -2926,7 +2936,15 @@ var CORE_ACTION_KINDS = /* @__PURE__ */ new Set([
|
|
|
2926
2936
|
"core:wait",
|
|
2927
2937
|
"core:sequence",
|
|
2928
2938
|
"core:parallel",
|
|
2929
|
-
"
|
|
2939
|
+
"overlays:tour"
|
|
2940
|
+
]);
|
|
2941
|
+
var BUNDLED_APP_IDS = /* @__PURE__ */ new Set([
|
|
2942
|
+
"adaptive-chatbot",
|
|
2943
|
+
"adaptive-content",
|
|
2944
|
+
"adaptive-faq",
|
|
2945
|
+
"adaptive-gamification",
|
|
2946
|
+
"adaptive-nav",
|
|
2947
|
+
"adaptive-overlays"
|
|
2930
2948
|
]);
|
|
2931
2949
|
var NAMESPACE_TO_APP_ID = {
|
|
2932
2950
|
faq: "adaptive-faq",
|
|
@@ -3080,6 +3098,9 @@ function createAppLoader(options) {
|
|
|
3080
3098
|
}
|
|
3081
3099
|
}
|
|
3082
3100
|
}
|
|
3101
|
+
for (const bundled of BUNDLED_APP_IDS) {
|
|
3102
|
+
appIds.delete(bundled);
|
|
3103
|
+
}
|
|
3083
3104
|
return Array.from(appIds);
|
|
3084
3105
|
}
|
|
3085
3106
|
async function loadAppsForConfig(config) {
|
|
@@ -3435,7 +3456,7 @@ function getAntiFlickerSnippet(config = {}) {
|
|
|
3435
3456
|
}
|
|
3436
3457
|
|
|
3437
3458
|
// src/version.ts
|
|
3438
|
-
var SDK_VERSION = "2.
|
|
3459
|
+
var SDK_VERSION = "2.12.0";
|
|
3439
3460
|
|
|
3440
3461
|
// src/types.ts
|
|
3441
3462
|
var SDK_SCHEMA_VERSION = "2.0";
|
|
@@ -3586,12 +3607,15 @@ function getCachedConfig(sdkVersion) {
|
|
|
3586
3607
|
var resolveConfigUri = ({
|
|
3587
3608
|
configUri,
|
|
3588
3609
|
experiments,
|
|
3589
|
-
featureKey
|
|
3610
|
+
featureKey
|
|
3590
3611
|
}) => {
|
|
3591
3612
|
var _a2;
|
|
3592
3613
|
if (configUri) return configUri;
|
|
3593
|
-
|
|
3594
|
-
|
|
3614
|
+
if (experiments) {
|
|
3615
|
+
const key = featureKey != null ? featureKey : "smart-canvas-config";
|
|
3616
|
+
const fromFeature = (_a2 = experiments.getFeatureValue) == null ? void 0 : _a2.call(experiments, key, null);
|
|
3617
|
+
if (fromFeature) return fromFeature;
|
|
3618
|
+
}
|
|
3595
3619
|
return void 0;
|
|
3596
3620
|
};
|
|
3597
3621
|
function getVariantFlagKeys(experiments, manifestKey, variantFlagPrefix) {
|
|
@@ -3617,14 +3641,15 @@ var createCanvasConfigFetcher = ({
|
|
|
3617
3641
|
experiments,
|
|
3618
3642
|
featureKey,
|
|
3619
3643
|
credentials,
|
|
3620
|
-
configFeatureKey
|
|
3644
|
+
configFeatureKey,
|
|
3621
3645
|
manifestKey,
|
|
3622
3646
|
variantFlagPrefix,
|
|
3623
3647
|
sdkVersion
|
|
3624
3648
|
}) => async () => {
|
|
3625
3649
|
var _a2;
|
|
3626
|
-
|
|
3627
|
-
|
|
3650
|
+
const effectiveConfigKey = configFeatureKey != null ? configFeatureKey : "smart-canvas-config";
|
|
3651
|
+
if (experiments) {
|
|
3652
|
+
const directConfig = (_a2 = experiments.getFeatureValue) == null ? void 0 : _a2.call(experiments, effectiveConfigKey, null);
|
|
3628
3653
|
if (directConfig && typeof directConfig === "object") {
|
|
3629
3654
|
debug("SmartCanvas Config", "Resolved config directly from feature flag", directConfig);
|
|
3630
3655
|
return directConfig;
|
|
@@ -3812,8 +3837,529 @@ function useShadowRoot() {
|
|
|
3812
3837
|
return ctx;
|
|
3813
3838
|
}
|
|
3814
3839
|
|
|
3815
|
-
//
|
|
3840
|
+
// ../event-processor/dist/types.js
|
|
3841
|
+
var EVENT_SCHEMA_VERSION = "1.0.0";
|
|
3816
3842
|
var StandardEvents = {
|
|
3843
|
+
UI_CLICK: "ui.click",
|
|
3844
|
+
UI_SCROLL: "ui.scroll",
|
|
3845
|
+
UI_INPUT: "ui.input",
|
|
3846
|
+
UI_CHANGE: "ui.change",
|
|
3847
|
+
UI_SUBMIT: "ui.submit",
|
|
3848
|
+
NAV_PAGE_VIEW: "nav.page_view",
|
|
3849
|
+
NAV_PAGE_LEAVE: "nav.page_leave",
|
|
3850
|
+
UI_HESITATE: "ui.hesitate",
|
|
3851
|
+
UI_RAGE_CLICK: "ui.rage_click",
|
|
3852
|
+
UI_SCROLL_THRASH: "ui.scroll_thrash",
|
|
3853
|
+
UI_FOCUS_BOUNCE: "ui.focus_bounce",
|
|
3854
|
+
UI_IDLE: "ui.idle",
|
|
3855
|
+
UI_HOVER: "ui.hover"
|
|
3856
|
+
};
|
|
3857
|
+
var RRWebSource = {
|
|
3858
|
+
Mutation: 0,
|
|
3859
|
+
MouseMove: 1,
|
|
3860
|
+
MouseInteraction: 2,
|
|
3861
|
+
Scroll: 3,
|
|
3862
|
+
ViewportResize: 4,
|
|
3863
|
+
Input: 5,
|
|
3864
|
+
TouchMove: 6,
|
|
3865
|
+
MediaInteraction: 7,
|
|
3866
|
+
Drag: 12
|
|
3867
|
+
};
|
|
3868
|
+
var RRWebMouseInteraction = {
|
|
3869
|
+
MouseUp: 0,
|
|
3870
|
+
MouseDown: 1,
|
|
3871
|
+
Click: 2,
|
|
3872
|
+
ContextMenu: 3,
|
|
3873
|
+
DblClick: 4,
|
|
3874
|
+
Focus: 5,
|
|
3875
|
+
Blur: 6,
|
|
3876
|
+
TouchStart: 7,
|
|
3877
|
+
TouchEnd: 9
|
|
3878
|
+
};
|
|
3879
|
+
var DEFAULT_DETECTOR_CONFIG = {
|
|
3880
|
+
hesitationMs: 3e3,
|
|
3881
|
+
hesitationRadiusPx: 10,
|
|
3882
|
+
rageClickCount: 3,
|
|
3883
|
+
rageClickWindowMs: 1e3,
|
|
3884
|
+
rageClickRadiusPx: 30,
|
|
3885
|
+
scrollThrashReversals: 3,
|
|
3886
|
+
scrollThrashWindowMs: 2e3,
|
|
3887
|
+
focusBounceMaxInputs: 0,
|
|
3888
|
+
idleMs: 5e3,
|
|
3889
|
+
hoverSampleMs: 100
|
|
3890
|
+
};
|
|
3891
|
+
|
|
3892
|
+
// ../event-processor/dist/normalizers/posthog.js
|
|
3893
|
+
var POSTHOG_EVENT_MAP = {
|
|
3894
|
+
// NOTE: $autocapture is intentionally NOT in this map.
|
|
3895
|
+
// It's handled below in getEventName() with $event_type refinement
|
|
3896
|
+
// so that change/submit events aren't all mapped to ui.click.
|
|
3897
|
+
$click: StandardEvents.UI_CLICK,
|
|
3898
|
+
$scroll: StandardEvents.UI_SCROLL,
|
|
3899
|
+
$input: StandardEvents.UI_INPUT,
|
|
3900
|
+
$change: StandardEvents.UI_CHANGE,
|
|
3901
|
+
$submit: StandardEvents.UI_SUBMIT,
|
|
3902
|
+
// Navigation events
|
|
3903
|
+
$pageview: StandardEvents.NAV_PAGE_VIEW,
|
|
3904
|
+
$pageleave: StandardEvents.NAV_PAGE_LEAVE,
|
|
3905
|
+
// Session events
|
|
3906
|
+
$session_start: "session.start",
|
|
3907
|
+
// Identify events
|
|
3908
|
+
$identify: "user.identify"
|
|
3909
|
+
};
|
|
3910
|
+
function getEventName(phEvent) {
|
|
3911
|
+
var _a2, _b;
|
|
3912
|
+
const eventName = phEvent.event;
|
|
3913
|
+
if (typeof eventName !== "string") {
|
|
3914
|
+
return "posthog.unknown";
|
|
3915
|
+
}
|
|
3916
|
+
if (POSTHOG_EVENT_MAP[eventName]) {
|
|
3917
|
+
return POSTHOG_EVENT_MAP[eventName];
|
|
3918
|
+
}
|
|
3919
|
+
if (eventName === "$autocapture") {
|
|
3920
|
+
const tagName = (_a2 = phEvent.properties) == null ? void 0 : _a2.$tag_name;
|
|
3921
|
+
const eventType = (_b = phEvent.properties) == null ? void 0 : _b.$event_type;
|
|
3922
|
+
if (eventType === "submit")
|
|
3923
|
+
return StandardEvents.UI_SUBMIT;
|
|
3924
|
+
if (eventType === "change")
|
|
3925
|
+
return StandardEvents.UI_CHANGE;
|
|
3926
|
+
if (tagName === "input" || tagName === "textarea")
|
|
3927
|
+
return StandardEvents.UI_INPUT;
|
|
3928
|
+
return StandardEvents.UI_CLICK;
|
|
3929
|
+
}
|
|
3930
|
+
if (!eventName.startsWith("$")) {
|
|
3931
|
+
return `posthog.${eventName}`;
|
|
3932
|
+
}
|
|
3933
|
+
return eventName.replace("$", "posthog.");
|
|
3934
|
+
}
|
|
3935
|
+
var INTERACTIVE_TAGS = /* @__PURE__ */ new Set(["a", "button", "input", "select", "textarea"]);
|
|
3936
|
+
function resolveInteractiveTag(elements, directTag) {
|
|
3937
|
+
if (directTag && INTERACTIVE_TAGS.has(directTag))
|
|
3938
|
+
return directTag;
|
|
3939
|
+
if (!elements)
|
|
3940
|
+
return directTag;
|
|
3941
|
+
for (const el of elements) {
|
|
3942
|
+
const tag2 = el.tag_name;
|
|
3943
|
+
if (tag2 && INTERACTIVE_TAGS.has(tag2))
|
|
3944
|
+
return tag2;
|
|
3945
|
+
}
|
|
3946
|
+
return directTag;
|
|
3947
|
+
}
|
|
3948
|
+
function extractProps(phEvent) {
|
|
3949
|
+
var _a2, _b;
|
|
3950
|
+
const props = {};
|
|
3951
|
+
const phProps = phEvent.properties || {};
|
|
3952
|
+
const elements = phProps.$elements;
|
|
3953
|
+
const directTag = (_b = phProps.$tag_name) != null ? _b : (_a2 = elements == null ? void 0 : elements[0]) == null ? void 0 : _a2.tag_name;
|
|
3954
|
+
const isClickEvent = phEvent.event === "$autocapture" || phEvent.event === "$click";
|
|
3955
|
+
props.tagName = isClickEvent ? resolveInteractiveTag(elements, directTag) : directTag;
|
|
3956
|
+
if (phProps.$el_text)
|
|
3957
|
+
props.elementText = phProps.$el_text;
|
|
3958
|
+
if (elements)
|
|
3959
|
+
props.elements = elements;
|
|
3960
|
+
if (phProps.$current_url)
|
|
3961
|
+
props.url = phProps.$current_url;
|
|
3962
|
+
if (phProps.$pathname)
|
|
3963
|
+
props.pathname = phProps.$pathname;
|
|
3964
|
+
if (phProps.$host)
|
|
3965
|
+
props.host = phProps.$host;
|
|
3966
|
+
if (phProps.$viewport_width)
|
|
3967
|
+
props.viewportWidth = phProps.$viewport_width;
|
|
3968
|
+
if (phProps.$viewport_height)
|
|
3969
|
+
props.viewportHeight = phProps.$viewport_height;
|
|
3970
|
+
if (phProps.$session_id)
|
|
3971
|
+
props.sessionId = phProps.$session_id;
|
|
3972
|
+
if (phProps.$scroll_depth)
|
|
3973
|
+
props.scrollDepth = phProps.$scroll_depth;
|
|
3974
|
+
if (phProps.$scroll_percentage)
|
|
3975
|
+
props.scrollPercentage = phProps.$scroll_percentage;
|
|
3976
|
+
props.originalEvent = phEvent.event;
|
|
3977
|
+
return props;
|
|
3978
|
+
}
|
|
3979
|
+
function normalizePostHogEvent(phEvent) {
|
|
3980
|
+
let ts;
|
|
3981
|
+
if (typeof phEvent.timestamp === "number") {
|
|
3982
|
+
ts = phEvent.timestamp;
|
|
3983
|
+
} else if (typeof phEvent.timestamp === "string") {
|
|
3984
|
+
ts = new Date(phEvent.timestamp).getTime();
|
|
3985
|
+
} else {
|
|
3986
|
+
ts = Date.now();
|
|
3987
|
+
}
|
|
3988
|
+
return {
|
|
3989
|
+
ts,
|
|
3990
|
+
name: getEventName(phEvent),
|
|
3991
|
+
source: "posthog",
|
|
3992
|
+
props: extractProps(phEvent),
|
|
3993
|
+
schemaVersion: EVENT_SCHEMA_VERSION
|
|
3994
|
+
};
|
|
3995
|
+
}
|
|
3996
|
+
function shouldNormalizeEvent(phEvent) {
|
|
3997
|
+
const eventName = phEvent.event;
|
|
3998
|
+
if (typeof eventName !== "string")
|
|
3999
|
+
return false;
|
|
4000
|
+
const skipEvents = [
|
|
4001
|
+
"$feature_flag_called",
|
|
4002
|
+
"$feature_flags",
|
|
4003
|
+
"$groups",
|
|
4004
|
+
"$groupidentify",
|
|
4005
|
+
"$set",
|
|
4006
|
+
"$set_once",
|
|
4007
|
+
"$unset",
|
|
4008
|
+
"$create_alias",
|
|
4009
|
+
"$capture_metrics",
|
|
4010
|
+
"$performance_event",
|
|
4011
|
+
"$web_vitals",
|
|
4012
|
+
"$exception",
|
|
4013
|
+
"$dead_click",
|
|
4014
|
+
"$heatmap"
|
|
4015
|
+
];
|
|
4016
|
+
if (skipEvents.includes(eventName)) {
|
|
4017
|
+
return false;
|
|
4018
|
+
}
|
|
4019
|
+
return true;
|
|
4020
|
+
}
|
|
4021
|
+
function createPostHogNormalizer(publishFn) {
|
|
4022
|
+
return (eventName, properties) => {
|
|
4023
|
+
if (typeof eventName !== "string")
|
|
4024
|
+
return;
|
|
4025
|
+
const phEvent = {
|
|
4026
|
+
event: eventName,
|
|
4027
|
+
properties,
|
|
4028
|
+
timestamp: Date.now()
|
|
4029
|
+
};
|
|
4030
|
+
if (shouldNormalizeEvent(phEvent)) {
|
|
4031
|
+
const normalizedEvent = normalizePostHogEvent(phEvent);
|
|
4032
|
+
publishFn(normalizedEvent);
|
|
4033
|
+
}
|
|
4034
|
+
};
|
|
4035
|
+
}
|
|
4036
|
+
|
|
4037
|
+
// ../event-processor/dist/detectors/focus-bounce.js
|
|
4038
|
+
var FocusBounceDetector = class {
|
|
4039
|
+
constructor(config, emit2) {
|
|
4040
|
+
this.config = config;
|
|
4041
|
+
this.emit = emit2;
|
|
4042
|
+
this.focused = /* @__PURE__ */ new Map();
|
|
4043
|
+
}
|
|
4044
|
+
ingest(raw) {
|
|
4045
|
+
var _a2, _b;
|
|
4046
|
+
if (raw.type !== 3)
|
|
4047
|
+
return;
|
|
4048
|
+
const ts = raw.timestamp;
|
|
4049
|
+
if (raw.data.source === RRWebSource.MouseInteraction) {
|
|
4050
|
+
const id = (_a2 = raw.data.id) != null ? _a2 : 0;
|
|
4051
|
+
if (raw.data.type === RRWebMouseInteraction.Focus) {
|
|
4052
|
+
this.focused.set(id, { id, focusTs: ts, inputCount: 0 });
|
|
4053
|
+
} else if (raw.data.type === RRWebMouseInteraction.Blur) {
|
|
4054
|
+
const entry = this.focused.get(id);
|
|
4055
|
+
if (entry && entry.inputCount <= this.config.focusBounceMaxInputs) {
|
|
4056
|
+
this.emit({
|
|
4057
|
+
ts,
|
|
4058
|
+
name: StandardEvents.UI_FOCUS_BOUNCE,
|
|
4059
|
+
source: "rrweb",
|
|
4060
|
+
schemaVersion: EVENT_SCHEMA_VERSION,
|
|
4061
|
+
props: {
|
|
4062
|
+
elementId: id,
|
|
4063
|
+
duration_ms: ts - entry.focusTs
|
|
4064
|
+
}
|
|
4065
|
+
});
|
|
4066
|
+
}
|
|
4067
|
+
this.focused.delete(id);
|
|
4068
|
+
}
|
|
4069
|
+
} else if (raw.data.source === RRWebSource.Input) {
|
|
4070
|
+
const id = (_b = raw.data.id) != null ? _b : 0;
|
|
4071
|
+
const entry = this.focused.get(id);
|
|
4072
|
+
if (entry) {
|
|
4073
|
+
entry.inputCount++;
|
|
4074
|
+
}
|
|
4075
|
+
}
|
|
4076
|
+
}
|
|
4077
|
+
};
|
|
4078
|
+
|
|
4079
|
+
// ../event-processor/dist/detectors/hesitation.js
|
|
4080
|
+
var HesitationDetector = class {
|
|
4081
|
+
constructor(config, emit2) {
|
|
4082
|
+
this.config = config;
|
|
4083
|
+
this.emit = emit2;
|
|
4084
|
+
this.anchorX = 0;
|
|
4085
|
+
this.anchorY = 0;
|
|
4086
|
+
this.anchorTs = 0;
|
|
4087
|
+
this.emitted = false;
|
|
4088
|
+
this.hasPosition = false;
|
|
4089
|
+
}
|
|
4090
|
+
ingest(raw) {
|
|
4091
|
+
var _a2;
|
|
4092
|
+
if (raw.type !== 3 || raw.data.source !== RRWebSource.MouseMove)
|
|
4093
|
+
return;
|
|
4094
|
+
const positions = raw.data.positions;
|
|
4095
|
+
if (!positions || positions.length === 0)
|
|
4096
|
+
return;
|
|
4097
|
+
const last = positions[positions.length - 1];
|
|
4098
|
+
const ts = raw.timestamp + ((_a2 = last.timeOffset) != null ? _a2 : 0);
|
|
4099
|
+
if (!this.hasPosition) {
|
|
4100
|
+
this.anchorX = last.x;
|
|
4101
|
+
this.anchorY = last.y;
|
|
4102
|
+
this.anchorTs = ts;
|
|
4103
|
+
this.hasPosition = true;
|
|
4104
|
+
this.emitted = false;
|
|
4105
|
+
return;
|
|
4106
|
+
}
|
|
4107
|
+
const dx = last.x - this.anchorX;
|
|
4108
|
+
const dy = last.y - this.anchorY;
|
|
4109
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
4110
|
+
if (dist > this.config.hesitationRadiusPx) {
|
|
4111
|
+
this.anchorX = last.x;
|
|
4112
|
+
this.anchorY = last.y;
|
|
4113
|
+
this.anchorTs = ts;
|
|
4114
|
+
this.emitted = false;
|
|
4115
|
+
}
|
|
4116
|
+
}
|
|
4117
|
+
tick(now) {
|
|
4118
|
+
if (!this.hasPosition || this.emitted)
|
|
4119
|
+
return;
|
|
4120
|
+
const elapsed = now - this.anchorTs;
|
|
4121
|
+
if (elapsed >= this.config.hesitationMs) {
|
|
4122
|
+
this.emit({
|
|
4123
|
+
ts: now,
|
|
4124
|
+
name: StandardEvents.UI_HESITATE,
|
|
4125
|
+
source: "rrweb",
|
|
4126
|
+
schemaVersion: EVENT_SCHEMA_VERSION,
|
|
4127
|
+
props: {
|
|
4128
|
+
x: this.anchorX,
|
|
4129
|
+
y: this.anchorY,
|
|
4130
|
+
duration_ms: elapsed
|
|
4131
|
+
}
|
|
4132
|
+
});
|
|
4133
|
+
this.emitted = true;
|
|
4134
|
+
}
|
|
4135
|
+
}
|
|
4136
|
+
};
|
|
4137
|
+
|
|
4138
|
+
// ../event-processor/dist/detectors/hover.js
|
|
4139
|
+
var HoverTracker = class {
|
|
4140
|
+
constructor(config, emit2, elementResolver) {
|
|
4141
|
+
this.config = config;
|
|
4142
|
+
this.emit = emit2;
|
|
4143
|
+
this.elementResolver = elementResolver;
|
|
4144
|
+
this.currentElement = null;
|
|
4145
|
+
this.hoverStartTs = null;
|
|
4146
|
+
this.lastX = 0;
|
|
4147
|
+
this.lastY = 0;
|
|
4148
|
+
this.lastSampleTs = -Infinity;
|
|
4149
|
+
}
|
|
4150
|
+
ingest(raw) {
|
|
4151
|
+
if (raw.type !== 3 || raw.data.source !== RRWebSource.MouseMove)
|
|
4152
|
+
return;
|
|
4153
|
+
const positions = raw.data.positions;
|
|
4154
|
+
if (!positions || positions.length === 0)
|
|
4155
|
+
return;
|
|
4156
|
+
const last = positions[positions.length - 1];
|
|
4157
|
+
this.lastX = last.x;
|
|
4158
|
+
this.lastY = last.y;
|
|
4159
|
+
}
|
|
4160
|
+
tick(now) {
|
|
4161
|
+
if (!this.elementResolver)
|
|
4162
|
+
return;
|
|
4163
|
+
if (now - this.lastSampleTs < this.config.hoverSampleMs)
|
|
4164
|
+
return;
|
|
4165
|
+
this.lastSampleTs = now;
|
|
4166
|
+
const newElement = this.elementResolver(this.lastX, this.lastY);
|
|
4167
|
+
const newKey = newElement ? elementKey(newElement) : null;
|
|
4168
|
+
const currentKey = this.currentElement ? elementKey(this.currentElement) : null;
|
|
4169
|
+
if (newKey !== currentKey) {
|
|
4170
|
+
if (this.currentElement && this.hoverStartTs !== null) {
|
|
4171
|
+
this.emit({
|
|
4172
|
+
ts: now,
|
|
4173
|
+
name: StandardEvents.UI_HOVER,
|
|
4174
|
+
source: "rrweb",
|
|
4175
|
+
schemaVersion: EVENT_SCHEMA_VERSION,
|
|
4176
|
+
props: {
|
|
4177
|
+
x: this.lastX,
|
|
4178
|
+
y: this.lastY,
|
|
4179
|
+
duration_ms: now - this.hoverStartTs,
|
|
4180
|
+
element: this.currentElement
|
|
4181
|
+
}
|
|
4182
|
+
});
|
|
4183
|
+
}
|
|
4184
|
+
this.currentElement = newElement;
|
|
4185
|
+
this.hoverStartTs = now;
|
|
4186
|
+
}
|
|
4187
|
+
}
|
|
4188
|
+
};
|
|
4189
|
+
function elementKey(el) {
|
|
4190
|
+
var _a2, _b, _c;
|
|
4191
|
+
return `${(_a2 = el.tag_name) != null ? _a2 : ""}|${(_b = el.attr__id) != null ? _b : ""}|${((_c = el.classes) != null ? _c : []).join(",")}`;
|
|
4192
|
+
}
|
|
4193
|
+
|
|
4194
|
+
// ../event-processor/dist/detectors/idle.js
|
|
4195
|
+
var IdleDetector = class {
|
|
4196
|
+
constructor(config, emit2) {
|
|
4197
|
+
this.config = config;
|
|
4198
|
+
this.emit = emit2;
|
|
4199
|
+
this.lastActivityTs = null;
|
|
4200
|
+
this.emitted = false;
|
|
4201
|
+
}
|
|
4202
|
+
ingest(raw) {
|
|
4203
|
+
if (raw.type !== 3)
|
|
4204
|
+
return;
|
|
4205
|
+
const src = raw.data.source;
|
|
4206
|
+
if (src === RRWebSource.MouseMove || src === RRWebSource.MouseInteraction || src === RRWebSource.Scroll) {
|
|
4207
|
+
this.lastActivityTs = raw.timestamp;
|
|
4208
|
+
this.emitted = false;
|
|
4209
|
+
}
|
|
4210
|
+
}
|
|
4211
|
+
tick(now) {
|
|
4212
|
+
if (this.lastActivityTs === null || this.emitted)
|
|
4213
|
+
return;
|
|
4214
|
+
if (now - this.lastActivityTs >= this.config.idleMs) {
|
|
4215
|
+
this.emit({
|
|
4216
|
+
ts: now,
|
|
4217
|
+
name: StandardEvents.UI_IDLE,
|
|
4218
|
+
source: "rrweb",
|
|
4219
|
+
schemaVersion: EVENT_SCHEMA_VERSION,
|
|
4220
|
+
props: {
|
|
4221
|
+
idle_ms: now - this.lastActivityTs
|
|
4222
|
+
}
|
|
4223
|
+
});
|
|
4224
|
+
this.emitted = true;
|
|
4225
|
+
}
|
|
4226
|
+
}
|
|
4227
|
+
};
|
|
4228
|
+
|
|
4229
|
+
// ../event-processor/dist/detectors/rage-click.js
|
|
4230
|
+
var RageClickDetector = class {
|
|
4231
|
+
constructor(config, emit2) {
|
|
4232
|
+
this.config = config;
|
|
4233
|
+
this.emit = emit2;
|
|
4234
|
+
this.clicks = [];
|
|
4235
|
+
}
|
|
4236
|
+
ingest(raw) {
|
|
4237
|
+
var _a2, _b;
|
|
4238
|
+
if (raw.type !== 3 || raw.data.source !== RRWebSource.MouseInteraction)
|
|
4239
|
+
return;
|
|
4240
|
+
if (raw.data.type !== RRWebMouseInteraction.Click)
|
|
4241
|
+
return;
|
|
4242
|
+
const x = (_a2 = raw.data.x) != null ? _a2 : 0;
|
|
4243
|
+
const y = (_b = raw.data.y) != null ? _b : 0;
|
|
4244
|
+
const ts = raw.timestamp;
|
|
4245
|
+
const cutoff = ts - this.config.rageClickWindowMs;
|
|
4246
|
+
this.clicks = this.clicks.filter((c) => c.ts >= cutoff);
|
|
4247
|
+
this.clicks.push({ ts, x, y });
|
|
4248
|
+
const nearby = this.clicks.filter((c) => {
|
|
4249
|
+
const dx = c.x - x;
|
|
4250
|
+
const dy = c.y - y;
|
|
4251
|
+
return Math.sqrt(dx * dx + dy * dy) <= this.config.rageClickRadiusPx;
|
|
4252
|
+
});
|
|
4253
|
+
if (nearby.length >= this.config.rageClickCount) {
|
|
4254
|
+
this.emit({
|
|
4255
|
+
ts,
|
|
4256
|
+
name: StandardEvents.UI_RAGE_CLICK,
|
|
4257
|
+
source: "rrweb",
|
|
4258
|
+
schemaVersion: EVENT_SCHEMA_VERSION,
|
|
4259
|
+
props: {
|
|
4260
|
+
x,
|
|
4261
|
+
y,
|
|
4262
|
+
clickCount: nearby.length,
|
|
4263
|
+
duration_ms: ts - nearby[0].ts
|
|
4264
|
+
}
|
|
4265
|
+
});
|
|
4266
|
+
this.clicks = [];
|
|
4267
|
+
}
|
|
4268
|
+
}
|
|
4269
|
+
};
|
|
4270
|
+
|
|
4271
|
+
// ../event-processor/dist/detectors/scroll-thrash.js
|
|
4272
|
+
var ScrollThrashDetector = class {
|
|
4273
|
+
constructor(config, emit2) {
|
|
4274
|
+
this.config = config;
|
|
4275
|
+
this.emit = emit2;
|
|
4276
|
+
this.lastY = null;
|
|
4277
|
+
this.lastDirection = null;
|
|
4278
|
+
this.reversals = [];
|
|
4279
|
+
}
|
|
4280
|
+
ingest(raw) {
|
|
4281
|
+
var _a2;
|
|
4282
|
+
if (raw.type !== 3 || raw.data.source !== RRWebSource.Scroll)
|
|
4283
|
+
return;
|
|
4284
|
+
const y = (_a2 = raw.data.y) != null ? _a2 : 0;
|
|
4285
|
+
const ts = raw.timestamp;
|
|
4286
|
+
if (this.lastY !== null) {
|
|
4287
|
+
const direction = y > this.lastY ? "down" : y < this.lastY ? "up" : this.lastDirection;
|
|
4288
|
+
if (direction && direction !== this.lastDirection) {
|
|
4289
|
+
const cutoff = ts - this.config.scrollThrashWindowMs;
|
|
4290
|
+
this.reversals = this.reversals.filter((t) => t > cutoff);
|
|
4291
|
+
this.reversals.push(ts);
|
|
4292
|
+
if (this.reversals.length >= this.config.scrollThrashReversals) {
|
|
4293
|
+
this.emit({
|
|
4294
|
+
ts,
|
|
4295
|
+
name: StandardEvents.UI_SCROLL_THRASH,
|
|
4296
|
+
source: "rrweb",
|
|
4297
|
+
schemaVersion: EVENT_SCHEMA_VERSION,
|
|
4298
|
+
props: {
|
|
4299
|
+
reversals: this.reversals.length,
|
|
4300
|
+
duration_ms: ts - this.reversals[0]
|
|
4301
|
+
}
|
|
4302
|
+
});
|
|
4303
|
+
this.reversals = [];
|
|
4304
|
+
}
|
|
4305
|
+
}
|
|
4306
|
+
this.lastDirection = direction;
|
|
4307
|
+
}
|
|
4308
|
+
this.lastY = y;
|
|
4309
|
+
}
|
|
4310
|
+
};
|
|
4311
|
+
|
|
4312
|
+
// ../event-processor/dist/processor.js
|
|
4313
|
+
function createEventProcessor(options) {
|
|
4314
|
+
const config = { ...DEFAULT_DETECTOR_CONFIG, ...options == null ? void 0 : options.config };
|
|
4315
|
+
const listeners = [];
|
|
4316
|
+
function emit2(event) {
|
|
4317
|
+
for (const cb of listeners)
|
|
4318
|
+
cb(event);
|
|
4319
|
+
}
|
|
4320
|
+
const hesitation = new HesitationDetector(config, emit2);
|
|
4321
|
+
const rageClick = new RageClickDetector(config, emit2);
|
|
4322
|
+
const scrollThrash = new ScrollThrashDetector(config, emit2);
|
|
4323
|
+
const focusBounce = new FocusBounceDetector(config, emit2);
|
|
4324
|
+
const idle = new IdleDetector(config, emit2);
|
|
4325
|
+
const hover = new HoverTracker(config, emit2, options == null ? void 0 : options.elementResolver);
|
|
4326
|
+
const clickAttrBuffer = [];
|
|
4327
|
+
return {
|
|
4328
|
+
ingest(raw) {
|
|
4329
|
+
if (raw.kind === "posthog") {
|
|
4330
|
+
const { kind: _, ...phEvent } = raw;
|
|
4331
|
+
if (shouldNormalizeEvent(phEvent)) {
|
|
4332
|
+
emit2(normalizePostHogEvent(phEvent));
|
|
4333
|
+
}
|
|
4334
|
+
} else if (raw.kind === "rrweb") {
|
|
4335
|
+
hesitation.ingest(raw);
|
|
4336
|
+
rageClick.ingest(raw);
|
|
4337
|
+
scrollThrash.ingest(raw);
|
|
4338
|
+
focusBounce.ingest(raw);
|
|
4339
|
+
idle.ingest(raw);
|
|
4340
|
+
hover.ingest(raw);
|
|
4341
|
+
}
|
|
4342
|
+
},
|
|
4343
|
+
onEvent(callback) {
|
|
4344
|
+
listeners.push(callback);
|
|
4345
|
+
},
|
|
4346
|
+
tick(timestamp) {
|
|
4347
|
+
hesitation.tick(timestamp);
|
|
4348
|
+
idle.tick(timestamp);
|
|
4349
|
+
hover.tick(timestamp);
|
|
4350
|
+
},
|
|
4351
|
+
enrichClickAttributes(timestamp, elements) {
|
|
4352
|
+
clickAttrBuffer.push({ ts: timestamp, elements });
|
|
4353
|
+
const cutoff = timestamp - 500;
|
|
4354
|
+
while (clickAttrBuffer.length > 0 && clickAttrBuffer[0].ts < cutoff) {
|
|
4355
|
+
clickAttrBuffer.shift();
|
|
4356
|
+
}
|
|
4357
|
+
}
|
|
4358
|
+
};
|
|
4359
|
+
}
|
|
4360
|
+
|
|
4361
|
+
// src/events/types.ts
|
|
4362
|
+
var StandardEvents2 = {
|
|
3817
4363
|
// UI events (from PostHog autocapture)
|
|
3818
4364
|
UI_CLICK: "ui.click",
|
|
3819
4365
|
UI_SCROLL: "ui.scroll",
|
|
@@ -3853,7 +4399,6 @@ var StandardEvents = {
|
|
|
3853
4399
|
SURFACE_MOUNTED: "surface.mounted",
|
|
3854
4400
|
SURFACE_UNMOUNTED: "surface.unmounted"
|
|
3855
4401
|
};
|
|
3856
|
-
var EVENT_SCHEMA_VERSION = "1.0.0";
|
|
3857
4402
|
|
|
3858
4403
|
// src/events/normalizers/canvas.ts
|
|
3859
4404
|
function createCanvasEvent(name, props) {
|
|
@@ -3866,48 +4411,48 @@ function createCanvasEvent(name, props) {
|
|
|
3866
4411
|
};
|
|
3867
4412
|
}
|
|
3868
4413
|
function canvasOpened(surface) {
|
|
3869
|
-
return createCanvasEvent(
|
|
4414
|
+
return createCanvasEvent(StandardEvents2.CANVAS_OPENED, { surface });
|
|
3870
4415
|
}
|
|
3871
4416
|
function canvasClosed(surface) {
|
|
3872
|
-
return createCanvasEvent(
|
|
4417
|
+
return createCanvasEvent(StandardEvents2.CANVAS_CLOSED, { surface });
|
|
3873
4418
|
}
|
|
3874
4419
|
function tileViewed(tileId, surface) {
|
|
3875
|
-
return createCanvasEvent(
|
|
4420
|
+
return createCanvasEvent(StandardEvents2.TILE_VIEWED, { tileId, surface });
|
|
3876
4421
|
}
|
|
3877
4422
|
function tileExpanded(tileId, surface) {
|
|
3878
|
-
return createCanvasEvent(
|
|
4423
|
+
return createCanvasEvent(StandardEvents2.TILE_EXPANDED, { tileId, surface });
|
|
3879
4424
|
}
|
|
3880
4425
|
function tileCollapsed(tileId, surface) {
|
|
3881
|
-
return createCanvasEvent(
|
|
4426
|
+
return createCanvasEvent(StandardEvents2.TILE_COLLAPSED, { tileId, surface });
|
|
3882
4427
|
}
|
|
3883
4428
|
function tileAction(tileId, actionId, surface) {
|
|
3884
|
-
return createCanvasEvent(
|
|
4429
|
+
return createCanvasEvent(StandardEvents2.TILE_ACTION, {
|
|
3885
4430
|
tileId,
|
|
3886
4431
|
actionId,
|
|
3887
4432
|
surface
|
|
3888
4433
|
});
|
|
3889
4434
|
}
|
|
3890
4435
|
function overlayStarted(recipeId, recipeName) {
|
|
3891
|
-
return createCanvasEvent(
|
|
4436
|
+
return createCanvasEvent(StandardEvents2.OVERLAY_STARTED, {
|
|
3892
4437
|
recipeId,
|
|
3893
4438
|
recipeName
|
|
3894
4439
|
});
|
|
3895
4440
|
}
|
|
3896
4441
|
function overlayCompleted(recipeId, recipeName) {
|
|
3897
|
-
return createCanvasEvent(
|
|
4442
|
+
return createCanvasEvent(StandardEvents2.OVERLAY_COMPLETED, {
|
|
3898
4443
|
recipeId,
|
|
3899
4444
|
recipeName
|
|
3900
4445
|
});
|
|
3901
4446
|
}
|
|
3902
4447
|
function overlayDismissed(recipeId, recipeName, stepIndex) {
|
|
3903
|
-
return createCanvasEvent(
|
|
4448
|
+
return createCanvasEvent(StandardEvents2.OVERLAY_DISMISSED, {
|
|
3904
4449
|
recipeId,
|
|
3905
4450
|
recipeName,
|
|
3906
4451
|
stepIndex
|
|
3907
4452
|
});
|
|
3908
4453
|
}
|
|
3909
4454
|
function overlayStepViewed(recipeId, stepIndex, stepTitle) {
|
|
3910
|
-
return createCanvasEvent(
|
|
4455
|
+
return createCanvasEvent(StandardEvents2.OVERLAY_STEP_VIEWED, {
|
|
3911
4456
|
recipeId,
|
|
3912
4457
|
stepIndex,
|
|
3913
4458
|
stepTitle
|
|
@@ -4233,7 +4778,7 @@ function useNotifications(eventBus, tiles) {
|
|
|
4233
4778
|
const timerIds = useRef2(/* @__PURE__ */ new Map());
|
|
4234
4779
|
const publishDismissed = useCallback2(
|
|
4235
4780
|
(notif) => {
|
|
4236
|
-
eventBus == null ? void 0 : eventBus.publish(
|
|
4781
|
+
eventBus == null ? void 0 : eventBus.publish(StandardEvents2.NOTIFICATION_DISMISSED, {
|
|
4237
4782
|
notificationId: notif.id,
|
|
4238
4783
|
tileId: notif.tileId,
|
|
4239
4784
|
itemId: notif.itemId
|
|
@@ -4298,7 +4843,7 @@ function useNotifications(eventBus, tiles) {
|
|
|
4298
4843
|
}
|
|
4299
4844
|
return next;
|
|
4300
4845
|
});
|
|
4301
|
-
eventBus.publish(
|
|
4846
|
+
eventBus.publish(StandardEvents2.NOTIFICATION_SHOWN, {
|
|
4302
4847
|
notificationId: matched.id,
|
|
4303
4848
|
tileId: matched.tileId,
|
|
4304
4849
|
itemId: matched.itemId,
|
|
@@ -4511,7 +5056,7 @@ function WidgetMount({ widgetId, props }) {
|
|
|
4511
5056
|
prevPropsJsonRef.current = propsJson;
|
|
4512
5057
|
(_a3 = handleRef.current) == null ? void 0 : _a3.update(propsRef.current);
|
|
4513
5058
|
}, [propsJson]);
|
|
4514
|
-
if (!registry
|
|
5059
|
+
if (!(registry == null ? void 0 : registry.has(widgetId))) {
|
|
4515
5060
|
return /* @__PURE__ */ jsxs2(
|
|
4516
5061
|
"div",
|
|
4517
5062
|
{
|
|
@@ -5132,7 +5677,7 @@ function ShadowCanvasOverlay({
|
|
|
5132
5677
|
const handleNotificationClick = useCallback4(
|
|
5133
5678
|
(notif) => {
|
|
5134
5679
|
if (runtime3) {
|
|
5135
|
-
runtime3.events.publish(
|
|
5680
|
+
runtime3.events.publish(StandardEvents2.NOTIFICATION_CLICKED, {
|
|
5136
5681
|
notificationId: notif.id,
|
|
5137
5682
|
tileId: notif.tileId,
|
|
5138
5683
|
itemId: notif.itemId
|
|
@@ -5142,7 +5687,7 @@ function ShadowCanvasOverlay({
|
|
|
5142
5687
|
onToggle();
|
|
5143
5688
|
}
|
|
5144
5689
|
if (runtime3 && notif.tileId) {
|
|
5145
|
-
runtime3.events.publish(
|
|
5690
|
+
runtime3.events.publish(StandardEvents2.NOTIFICATION_DEEP_LINK, {
|
|
5146
5691
|
tileId: notif.tileId,
|
|
5147
5692
|
itemId: notif.itemId
|
|
5148
5693
|
});
|
|
@@ -5215,6 +5760,17 @@ function ShadowCanvasOverlay({
|
|
|
5215
5760
|
}
|
|
5216
5761
|
onToggle();
|
|
5217
5762
|
}, [isOpen, telemetry, runtime3, onToggle]);
|
|
5763
|
+
useEffect7(() => {
|
|
5764
|
+
if (!isOpen) return;
|
|
5765
|
+
const handleOutsideClick = (e) => {
|
|
5766
|
+
const path = e.composedPath();
|
|
5767
|
+
if (containerRef.current && !path.includes(containerRef.current) && launcherRef.current && !path.includes(launcherRef.current)) {
|
|
5768
|
+
toggle2();
|
|
5769
|
+
}
|
|
5770
|
+
};
|
|
5771
|
+
document.addEventListener("mousedown", handleOutsideClick);
|
|
5772
|
+
return () => document.removeEventListener("mousedown", handleOutsideClick);
|
|
5773
|
+
}, [isOpen, toggle2]);
|
|
5218
5774
|
const onLauncherPointerDown = useCallback4((e) => {
|
|
5219
5775
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
5220
5776
|
dragRef.current = {
|
|
@@ -5253,6 +5809,7 @@ function ShadowCanvasOverlay({
|
|
|
5253
5809
|
const isPush = config.canvas.layout === "push";
|
|
5254
5810
|
const canvasBorder = (_b = config.canvas.border) != null ? _b : "none";
|
|
5255
5811
|
const containerRef = useRef5(null);
|
|
5812
|
+
const launcherRef = useRef5(null);
|
|
5256
5813
|
const zIndex = 2147483600;
|
|
5257
5814
|
useEffect7(() => {
|
|
5258
5815
|
var _a3, _b2, _c2, _d2;
|
|
@@ -5340,7 +5897,7 @@ function ShadowCanvasOverlay({
|
|
|
5340
5897
|
style: {
|
|
5341
5898
|
position: "fixed",
|
|
5342
5899
|
inset: 0,
|
|
5343
|
-
pointerEvents:
|
|
5900
|
+
pointerEvents: "none",
|
|
5344
5901
|
zIndex
|
|
5345
5902
|
},
|
|
5346
5903
|
children: /* @__PURE__ */ jsxs3("div", { style: wrapperStyle, children: [
|
|
@@ -5413,17 +5970,7 @@ function ShadowCanvasOverlay({
|
|
|
5413
5970
|
) }),
|
|
5414
5971
|
footerSlot
|
|
5415
5972
|
] }),
|
|
5416
|
-
/* @__PURE__ */ jsx8(
|
|
5417
|
-
"div",
|
|
5418
|
-
{
|
|
5419
|
-
onClick: toggle2,
|
|
5420
|
-
style: {
|
|
5421
|
-
flex: "1 1 auto",
|
|
5422
|
-
pointerEvents: isOpen ? "auto" : "none",
|
|
5423
|
-
cursor: "default"
|
|
5424
|
-
}
|
|
5425
|
-
}
|
|
5426
|
-
)
|
|
5973
|
+
/* @__PURE__ */ jsx8("div", { style: { flex: "1 1 auto" } })
|
|
5427
5974
|
] })
|
|
5428
5975
|
}
|
|
5429
5976
|
);
|
|
@@ -5453,6 +6000,7 @@ function ShadowCanvasOverlay({
|
|
|
5453
6000
|
/* @__PURE__ */ jsxs3(
|
|
5454
6001
|
"button",
|
|
5455
6002
|
{
|
|
6003
|
+
ref: launcherRef,
|
|
5456
6004
|
type: "button",
|
|
5457
6005
|
"aria-label": "Toggle shadow canvas",
|
|
5458
6006
|
className: launcherAnimate && !isOpen ? "syntro-launcher-animate" : void 0,
|
|
@@ -5715,8 +6263,8 @@ function SmartCanvasApp({
|
|
|
5715
6263
|
controller,
|
|
5716
6264
|
fetcher,
|
|
5717
6265
|
configUri,
|
|
5718
|
-
configUriFeatureKey
|
|
5719
|
-
configFeatureKey
|
|
6266
|
+
configUriFeatureKey,
|
|
6267
|
+
configFeatureKey,
|
|
5720
6268
|
fetchCredentials = "include",
|
|
5721
6269
|
pollIntervalMs,
|
|
5722
6270
|
experiments,
|
|
@@ -5786,10 +6334,10 @@ function SmartCanvasAppInner({
|
|
|
5786
6334
|
controller,
|
|
5787
6335
|
fetcher,
|
|
5788
6336
|
configUri,
|
|
5789
|
-
configUriFeatureKey
|
|
5790
|
-
configFeatureKey
|
|
6337
|
+
configUriFeatureKey,
|
|
6338
|
+
configFeatureKey,
|
|
5791
6339
|
fetchCredentials = "include",
|
|
5792
|
-
pollIntervalMs,
|
|
6340
|
+
pollIntervalMs: _pollIntervalMs,
|
|
5793
6341
|
experiments,
|
|
5794
6342
|
telemetry,
|
|
5795
6343
|
runtime: runtime3,
|
|
@@ -7071,17 +7619,18 @@ var PostHogAdapter = class {
|
|
|
7071
7619
|
__publicField(this, "client");
|
|
7072
7620
|
__publicField(this, "featureFlagsCallback");
|
|
7073
7621
|
__publicField(this, "captureCallback");
|
|
7074
|
-
__publicField(this, "
|
|
7622
|
+
__publicField(this, "rrwebCallback");
|
|
7075
7623
|
this.client = options.client;
|
|
7076
7624
|
this.featureFlagsCallback = options.onFeatureFlagsLoaded;
|
|
7077
7625
|
this.captureCallback = options.onCapture;
|
|
7626
|
+
this.rrwebCallback = options.onRRWebEvent;
|
|
7078
7627
|
if (!this.client && options.consent && options.requireExplicitConsent && typeof window !== "undefined" && options.apiKey) {
|
|
7079
7628
|
const consent = options.consent;
|
|
7080
7629
|
const currentStatus = consent.getStatus();
|
|
7081
7630
|
if (currentStatus === "granted") {
|
|
7082
7631
|
this.initPostHog();
|
|
7083
7632
|
}
|
|
7084
|
-
|
|
7633
|
+
consent.subscribe((status) => {
|
|
7085
7634
|
if (status === "granted") {
|
|
7086
7635
|
if (!this.client) {
|
|
7087
7636
|
this.initPostHog();
|
|
@@ -7108,71 +7657,123 @@ var PostHogAdapter = class {
|
|
|
7108
7657
|
if (!options.apiKey) return;
|
|
7109
7658
|
const enableFeatureFlags = (_a2 = options.enableFeatureFlags) != null ? _a2 : true;
|
|
7110
7659
|
const instanceName = `syntro_${options.apiKey.slice(-6) || "sdk"}`;
|
|
7111
|
-
|
|
7112
|
-
options.
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
if (allFlags && this.featureFlagsCallback) {
|
|
7142
|
-
this.featureFlagsCallback(allFlags);
|
|
7143
|
-
}
|
|
7144
|
-
});
|
|
7145
|
-
const existingFlags = this.getAllFeatureFlags();
|
|
7146
|
-
if (existingFlags && Object.keys(existingFlags).length > 0) {
|
|
7147
|
-
this.featureFlagsCallback(existingFlags);
|
|
7660
|
+
const initOptions = {
|
|
7661
|
+
api_host: (_b = options.apiHost) != null ? _b : "https://telemetry.syntrologie.com",
|
|
7662
|
+
// Feature flags for segment membership (in_segment_* flags)
|
|
7663
|
+
// When enabled, /decide is called to get segment flags
|
|
7664
|
+
advanced_disable_feature_flags: !enableFeatureFlags,
|
|
7665
|
+
advanced_disable_feature_flags_on_first_load: !enableFeatureFlags,
|
|
7666
|
+
// Full-page tracking - all ON by default
|
|
7667
|
+
autocapture: (_c = options.autocapture) != null ? _c : true,
|
|
7668
|
+
capture_pageview: (_d = options.capturePageview) != null ? _d : "history_change",
|
|
7669
|
+
capture_pageleave: (_e = options.capturePageleave) != null ? _e : true,
|
|
7670
|
+
disable_session_recording: !((_f = options.sessionRecording) != null ? _f : true),
|
|
7671
|
+
// CRITICAL: Disable user agent filtering to allow headless Chrome
|
|
7672
|
+
// PostHog blocks "HeadlessChrome" user agents by default as bot detection
|
|
7673
|
+
// This enables session recording in Playwright/crawler sessions
|
|
7674
|
+
opt_out_useragent_filter: true,
|
|
7675
|
+
// Cross-domain iframe recording for embeds
|
|
7676
|
+
session_recording: {
|
|
7677
|
+
recordCrossDomainIFrames: true
|
|
7678
|
+
},
|
|
7679
|
+
// Capture performance metrics
|
|
7680
|
+
capture_performance: true,
|
|
7681
|
+
// Enable web vitals
|
|
7682
|
+
enable_recording_console_log: true,
|
|
7683
|
+
// Bootstrap callback for when flags are loaded
|
|
7684
|
+
loaded: (ph) => {
|
|
7685
|
+
if (enableFeatureFlags && this.featureFlagsCallback) {
|
|
7686
|
+
ph.onFeatureFlags(() => {
|
|
7687
|
+
const allFlags = this.getAllFeatureFlags();
|
|
7688
|
+
if (allFlags && this.featureFlagsCallback) {
|
|
7689
|
+
this.featureFlagsCallback(allFlags);
|
|
7148
7690
|
}
|
|
7149
|
-
}
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
const eventName = typeof data === "string" ? data : data == null ? void 0 : data.event;
|
|
7154
|
-
const properties = typeof data === "string" ? void 0 : data == null ? void 0 : data.properties;
|
|
7155
|
-
if (typeof eventName === "string") {
|
|
7156
|
-
(_a3 = this.captureCallback) == null ? void 0 : _a3.call(this, eventName, properties);
|
|
7157
|
-
}
|
|
7158
|
-
});
|
|
7691
|
+
});
|
|
7692
|
+
const existingFlags = this.getAllFeatureFlags();
|
|
7693
|
+
if (existingFlags && Object.keys(existingFlags).length > 0) {
|
|
7694
|
+
this.featureFlagsCallback(existingFlags);
|
|
7159
7695
|
}
|
|
7160
7696
|
}
|
|
7161
|
-
|
|
7697
|
+
if (this.captureCallback) {
|
|
7698
|
+
ph.on("eventCaptured", (...args) => {
|
|
7699
|
+
var _a3;
|
|
7700
|
+
const data = args[0];
|
|
7701
|
+
const eventName = typeof data === "string" ? data : data == null ? void 0 : data.event;
|
|
7702
|
+
const properties = typeof data === "string" ? void 0 : data == null ? void 0 : data.properties;
|
|
7703
|
+
if (typeof eventName === "string") {
|
|
7704
|
+
(_a3 = this.captureCallback) == null ? void 0 : _a3.call(this, eventName, properties);
|
|
7705
|
+
}
|
|
7706
|
+
});
|
|
7707
|
+
}
|
|
7708
|
+
}
|
|
7709
|
+
};
|
|
7710
|
+
const result = posthog.init(
|
|
7711
|
+
options.apiKey,
|
|
7712
|
+
initOptions,
|
|
7162
7713
|
instanceName
|
|
7163
7714
|
);
|
|
7715
|
+
if (result) {
|
|
7716
|
+
this.client = result;
|
|
7717
|
+
}
|
|
7718
|
+
if (this.rrwebCallback && this.client) {
|
|
7719
|
+
this.setupRRWebIntercept();
|
|
7720
|
+
}
|
|
7164
7721
|
}
|
|
7165
7722
|
/**
|
|
7166
|
-
*
|
|
7167
|
-
*
|
|
7723
|
+
* Set up rrweb event interception on PostHog's session recording.
|
|
7724
|
+
*
|
|
7725
|
+
* PostHog lazy-loads the rrweb recorder. The SessionRecording wrapper has
|
|
7726
|
+
* an `onRRwebEmit` method, but rrweb delivers events directly to the
|
|
7727
|
+
* lazy-loaded recorder instance's `onRRwebEmit`, bypassing the wrapper.
|
|
7728
|
+
* We must find and patch the recorder instance, not the wrapper.
|
|
7729
|
+
*
|
|
7730
|
+
* The recorder instance is stored on a minified property of SessionRecording.
|
|
7731
|
+
* We detect it by looking for an object with both `onRRwebEmit` and `start` methods.
|
|
7168
7732
|
*/
|
|
7169
|
-
|
|
7170
|
-
var _a2
|
|
7171
|
-
const
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7733
|
+
setupRRWebIntercept(retries = 30) {
|
|
7734
|
+
var _a2;
|
|
7735
|
+
const sr = (_a2 = this.client) == null ? void 0 : _a2.sessionRecording;
|
|
7736
|
+
if (!sr) {
|
|
7737
|
+
if (retries > 0) {
|
|
7738
|
+
setTimeout(() => this.setupRRWebIntercept(retries - 1), 500);
|
|
7739
|
+
}
|
|
7740
|
+
return;
|
|
7741
|
+
}
|
|
7742
|
+
let recorder = null;
|
|
7743
|
+
const srRecord = sr;
|
|
7744
|
+
for (const key of Object.getOwnPropertyNames(srRecord)) {
|
|
7745
|
+
const val = srRecord[key];
|
|
7746
|
+
if (val && typeof val === "object" && typeof val.onRRwebEmit === "function" && typeof val.start === "function" && val !== sr) {
|
|
7747
|
+
recorder = val;
|
|
7748
|
+
break;
|
|
7749
|
+
}
|
|
7750
|
+
}
|
|
7751
|
+
if (!recorder) {
|
|
7752
|
+
if (retries > 0) {
|
|
7753
|
+
setTimeout(() => this.setupRRWebIntercept(retries - 1), 500);
|
|
7754
|
+
}
|
|
7755
|
+
return;
|
|
7756
|
+
}
|
|
7757
|
+
const originalEmit = recorder.onRRwebEmit.bind(recorder);
|
|
7758
|
+
recorder.onRRwebEmit = (rawEvent) => {
|
|
7759
|
+
var _a3;
|
|
7760
|
+
(_a3 = this.rrwebCallback) == null ? void 0 : _a3.call(this, { kind: "rrweb", ...rawEvent });
|
|
7761
|
+
originalEmit(rawEvent);
|
|
7762
|
+
};
|
|
7763
|
+
if (typeof window !== "undefined") {
|
|
7764
|
+
window.__RRWEB_INTERCEPT_READY__ = true;
|
|
7765
|
+
}
|
|
7766
|
+
}
|
|
7767
|
+
/**
|
|
7768
|
+
* Get all feature flags from PostHog.
|
|
7769
|
+
* Used to extract segment membership flags (in_segment_*).
|
|
7770
|
+
*/
|
|
7771
|
+
getAllFeatureFlags() {
|
|
7772
|
+
var _a2, _b;
|
|
7773
|
+
return (_b = (_a2 = this.client) == null ? void 0 : _a2.featureFlags) == null ? void 0 : _b.getFlagVariants();
|
|
7774
|
+
}
|
|
7775
|
+
/**
|
|
7776
|
+
* Get segment membership flags (in_segment_*) from PostHog.
|
|
7176
7777
|
*/
|
|
7177
7778
|
getSegmentFlags() {
|
|
7178
7779
|
const allFlags = this.getAllFeatureFlags();
|
|
@@ -7520,158 +8121,7 @@ function hasExecutor(kind) {
|
|
|
7520
8121
|
return executorRegistry.has(kind);
|
|
7521
8122
|
}
|
|
7522
8123
|
|
|
7523
|
-
// src/actions/validation.ts
|
|
7524
|
-
var DANGEROUS_ATTRS = /* @__PURE__ */ new Set([
|
|
7525
|
-
"onclick",
|
|
7526
|
-
"onerror",
|
|
7527
|
-
"onload",
|
|
7528
|
-
"onmouseover",
|
|
7529
|
-
"onfocus",
|
|
7530
|
-
"onblur",
|
|
7531
|
-
"onchange",
|
|
7532
|
-
"onsubmit",
|
|
7533
|
-
"onkeydown",
|
|
7534
|
-
"onkeyup",
|
|
7535
|
-
"onkeypress"
|
|
7536
|
-
]);
|
|
7537
|
-
var MAX_HTML_LENGTH = 5e4;
|
|
7538
|
-
var MAX_STYLE_COUNT = 50;
|
|
7539
|
-
function validateAction(action) {
|
|
7540
|
-
const errors = [];
|
|
7541
|
-
const warnings = [];
|
|
7542
|
-
if (!action || typeof action !== "object") {
|
|
7543
|
-
errors.push({
|
|
7544
|
-
code: "INVALID_ACTION",
|
|
7545
|
-
message: "Action must be an object"
|
|
7546
|
-
});
|
|
7547
|
-
return { valid: false, errors, warnings };
|
|
7548
|
-
}
|
|
7549
|
-
const { kind } = action;
|
|
7550
|
-
if (!kind || typeof kind !== "string") {
|
|
7551
|
-
errors.push({
|
|
7552
|
-
code: "MISSING_KIND",
|
|
7553
|
-
message: "Action must have a 'kind' property"
|
|
7554
|
-
});
|
|
7555
|
-
return { valid: false, errors, warnings };
|
|
7556
|
-
}
|
|
7557
|
-
if (!hasExecutor(kind) && kind !== "core:mountWidget") {
|
|
7558
|
-
const registered = executorRegistry.list();
|
|
7559
|
-
console.error(
|
|
7560
|
-
`[ActionValidation] Unknown action kind: "${kind}". Registered kinds (${registered.length}): [${registered.join(", ")}]. This usually means the app that provides "${kind}" hasn't been activated yet, or the executor was never registered in ExecutorRegistry.`
|
|
7561
|
-
);
|
|
7562
|
-
errors.push({
|
|
7563
|
-
code: "UNKNOWN_KIND",
|
|
7564
|
-
message: `Unknown action kind: ${kind}`,
|
|
7565
|
-
field: "kind"
|
|
7566
|
-
});
|
|
7567
|
-
return { valid: false, errors, warnings };
|
|
7568
|
-
}
|
|
7569
|
-
switch (kind) {
|
|
7570
|
-
case "overlays:highlight":
|
|
7571
|
-
case "overlays:pulse":
|
|
7572
|
-
case "navigation:scrollTo":
|
|
7573
|
-
validateAnchorAction(action, errors, warnings);
|
|
7574
|
-
break;
|
|
7575
|
-
case "overlays:badge":
|
|
7576
|
-
validateAnchorAction(action, errors, warnings);
|
|
7577
|
-
validateBadgeAction(action, errors, warnings);
|
|
7578
|
-
break;
|
|
7579
|
-
case "overlays:tooltip":
|
|
7580
|
-
validateAnchorAction(action, errors, warnings);
|
|
7581
|
-
validateTooltipAction(action, errors, warnings);
|
|
7582
|
-
break;
|
|
7583
|
-
case "overlays:modal":
|
|
7584
|
-
validateModalAction(action, errors, warnings);
|
|
7585
|
-
break;
|
|
7586
|
-
case "content:insertHtml":
|
|
7587
|
-
validateAnchorAction(action, errors, warnings);
|
|
7588
|
-
validateInsertHtmlAction(action, errors, warnings);
|
|
7589
|
-
break;
|
|
7590
|
-
case "content:setText":
|
|
7591
|
-
validateAnchorAction(action, errors, warnings);
|
|
7592
|
-
validateSetTextAction(action, errors, warnings);
|
|
7593
|
-
break;
|
|
7594
|
-
case "content:setAttr":
|
|
7595
|
-
validateAnchorAction(action, errors, warnings);
|
|
7596
|
-
validateSetAttrAction(action, errors, warnings);
|
|
7597
|
-
break;
|
|
7598
|
-
case "content:addClass":
|
|
7599
|
-
case "content:removeClass":
|
|
7600
|
-
validateAnchorAction(action, errors, warnings);
|
|
7601
|
-
validateClassAction(action, errors, warnings);
|
|
7602
|
-
break;
|
|
7603
|
-
case "content:setStyle":
|
|
7604
|
-
validateAnchorAction(action, errors, warnings);
|
|
7605
|
-
validateSetStyleAction(action, errors, warnings);
|
|
7606
|
-
break;
|
|
7607
|
-
case "core:mountWidget":
|
|
7608
|
-
validateMountWidgetAction(action, errors, warnings);
|
|
7609
|
-
break;
|
|
7610
|
-
case "core:wait":
|
|
7611
|
-
validateWaitAction(action, errors, warnings);
|
|
7612
|
-
break;
|
|
7613
|
-
case "core:sequence":
|
|
7614
|
-
validateSequenceAction(action, errors, warnings);
|
|
7615
|
-
break;
|
|
7616
|
-
case "core:parallel":
|
|
7617
|
-
validateParallelAction(action, errors, warnings);
|
|
7618
|
-
break;
|
|
7619
|
-
case "core:tour":
|
|
7620
|
-
validateTourAction(action, errors, warnings);
|
|
7621
|
-
break;
|
|
7622
|
-
case "navigation:navigate":
|
|
7623
|
-
validateNavigateAction(action, errors, warnings);
|
|
7624
|
-
break;
|
|
7625
|
-
}
|
|
7626
|
-
return {
|
|
7627
|
-
valid: errors.length === 0,
|
|
7628
|
-
errors,
|
|
7629
|
-
warnings
|
|
7630
|
-
};
|
|
7631
|
-
}
|
|
7632
|
-
function validateAnchorAction(action, errors, warnings) {
|
|
7633
|
-
const anchorId = action.anchorId;
|
|
7634
|
-
if (!anchorId || typeof anchorId !== "object") {
|
|
7635
|
-
errors.push({
|
|
7636
|
-
code: "MISSING_ANCHOR_ID",
|
|
7637
|
-
message: "Action requires an 'anchorId' object with a 'selector' string",
|
|
7638
|
-
field: "anchorId"
|
|
7639
|
-
});
|
|
7640
|
-
return;
|
|
7641
|
-
}
|
|
7642
|
-
if (!anchorId.selector || typeof anchorId.selector !== "string") {
|
|
7643
|
-
errors.push({
|
|
7644
|
-
code: "MISSING_ANCHOR_SELECTOR",
|
|
7645
|
-
message: "anchorId requires a 'selector' string",
|
|
7646
|
-
field: "anchorId.selector"
|
|
7647
|
-
});
|
|
7648
|
-
} else if (anchorId.selector.length > 200) {
|
|
7649
|
-
warnings.push({
|
|
7650
|
-
code: "LONG_ANCHOR_ID",
|
|
7651
|
-
message: "Anchor selector is unusually long",
|
|
7652
|
-
suggestion: "Consider using a shorter, more descriptive selector"
|
|
7653
|
-
});
|
|
7654
|
-
}
|
|
7655
|
-
if (anchorId.route === void 0 || anchorId.route === null) {
|
|
7656
|
-
errors.push({
|
|
7657
|
-
code: "MISSING_ANCHOR_ROUTE",
|
|
7658
|
-
message: `anchorId requires a 'route' (string or array of strings). Use "**" for all routes.`,
|
|
7659
|
-
field: "anchorId.route"
|
|
7660
|
-
});
|
|
7661
|
-
} else {
|
|
7662
|
-
const routes = Array.isArray(anchorId.route) ? anchorId.route : [anchorId.route];
|
|
7663
|
-
for (const route of routes) {
|
|
7664
|
-
if (typeof route !== "string") {
|
|
7665
|
-
errors.push({
|
|
7666
|
-
code: "INVALID_ANCHOR_ROUTE",
|
|
7667
|
-
message: "anchorId.route must be a string or array of strings",
|
|
7668
|
-
field: "anchorId.route"
|
|
7669
|
-
});
|
|
7670
|
-
break;
|
|
7671
|
-
}
|
|
7672
|
-
}
|
|
7673
|
-
}
|
|
7674
|
-
}
|
|
8124
|
+
// src/actions/validation-rules.ts
|
|
7675
8125
|
function validateBadgeAction(action, errors, warnings) {
|
|
7676
8126
|
if (!action.content || typeof action.content !== "string") {
|
|
7677
8127
|
errors.push({
|
|
@@ -8058,6 +8508,159 @@ function validateTourAction(action, errors, warnings) {
|
|
|
8058
8508
|
}
|
|
8059
8509
|
}
|
|
8060
8510
|
}
|
|
8511
|
+
|
|
8512
|
+
// src/actions/validation-core.ts
|
|
8513
|
+
var DANGEROUS_ATTRS = /* @__PURE__ */ new Set([
|
|
8514
|
+
"onclick",
|
|
8515
|
+
"onerror",
|
|
8516
|
+
"onload",
|
|
8517
|
+
"onmouseover",
|
|
8518
|
+
"onfocus",
|
|
8519
|
+
"onblur",
|
|
8520
|
+
"onchange",
|
|
8521
|
+
"onsubmit",
|
|
8522
|
+
"onkeydown",
|
|
8523
|
+
"onkeyup",
|
|
8524
|
+
"onkeypress"
|
|
8525
|
+
]);
|
|
8526
|
+
var MAX_HTML_LENGTH = 5e4;
|
|
8527
|
+
var MAX_STYLE_COUNT = 50;
|
|
8528
|
+
function validateAction(action) {
|
|
8529
|
+
const errors = [];
|
|
8530
|
+
const warnings = [];
|
|
8531
|
+
if (!action || typeof action !== "object") {
|
|
8532
|
+
errors.push({
|
|
8533
|
+
code: "INVALID_ACTION",
|
|
8534
|
+
message: "Action must be an object"
|
|
8535
|
+
});
|
|
8536
|
+
return { valid: false, errors, warnings };
|
|
8537
|
+
}
|
|
8538
|
+
const { kind } = action;
|
|
8539
|
+
if (!kind || typeof kind !== "string") {
|
|
8540
|
+
errors.push({
|
|
8541
|
+
code: "MISSING_KIND",
|
|
8542
|
+
message: "Action must have a 'kind' property"
|
|
8543
|
+
});
|
|
8544
|
+
return { valid: false, errors, warnings };
|
|
8545
|
+
}
|
|
8546
|
+
if (!hasExecutor(kind) && kind !== "core:mountWidget") {
|
|
8547
|
+
const registered = executorRegistry.list();
|
|
8548
|
+
console.error(
|
|
8549
|
+
`[ActionValidation] Unknown action kind: "${kind}". Registered kinds (${registered.length}): [${registered.join(", ")}]. This usually means the app that provides "${kind}" hasn't been activated yet, or the executor was never registered in ExecutorRegistry.`
|
|
8550
|
+
);
|
|
8551
|
+
errors.push({
|
|
8552
|
+
code: "UNKNOWN_KIND",
|
|
8553
|
+
message: `Unknown action kind: ${kind}`,
|
|
8554
|
+
field: "kind"
|
|
8555
|
+
});
|
|
8556
|
+
return { valid: false, errors, warnings };
|
|
8557
|
+
}
|
|
8558
|
+
switch (kind) {
|
|
8559
|
+
case "overlays:highlight":
|
|
8560
|
+
case "overlays:pulse":
|
|
8561
|
+
case "navigation:scrollTo":
|
|
8562
|
+
validateAnchorAction(action, errors, warnings);
|
|
8563
|
+
break;
|
|
8564
|
+
case "overlays:badge":
|
|
8565
|
+
validateAnchorAction(action, errors, warnings);
|
|
8566
|
+
validateBadgeAction(action, errors, warnings);
|
|
8567
|
+
break;
|
|
8568
|
+
case "overlays:tooltip":
|
|
8569
|
+
validateAnchorAction(action, errors, warnings);
|
|
8570
|
+
validateTooltipAction(action, errors, warnings);
|
|
8571
|
+
break;
|
|
8572
|
+
case "overlays:modal":
|
|
8573
|
+
validateModalAction(action, errors, warnings);
|
|
8574
|
+
break;
|
|
8575
|
+
case "content:insertHtml":
|
|
8576
|
+
validateAnchorAction(action, errors, warnings);
|
|
8577
|
+
validateInsertHtmlAction(action, errors, warnings);
|
|
8578
|
+
break;
|
|
8579
|
+
case "content:setText":
|
|
8580
|
+
validateAnchorAction(action, errors, warnings);
|
|
8581
|
+
validateSetTextAction(action, errors, warnings);
|
|
8582
|
+
break;
|
|
8583
|
+
case "content:setAttr":
|
|
8584
|
+
validateAnchorAction(action, errors, warnings);
|
|
8585
|
+
validateSetAttrAction(action, errors, warnings);
|
|
8586
|
+
break;
|
|
8587
|
+
case "content:addClass":
|
|
8588
|
+
case "content:removeClass":
|
|
8589
|
+
validateAnchorAction(action, errors, warnings);
|
|
8590
|
+
validateClassAction(action, errors, warnings);
|
|
8591
|
+
break;
|
|
8592
|
+
case "content:setStyle":
|
|
8593
|
+
validateAnchorAction(action, errors, warnings);
|
|
8594
|
+
validateSetStyleAction(action, errors, warnings);
|
|
8595
|
+
break;
|
|
8596
|
+
case "core:mountWidget":
|
|
8597
|
+
validateMountWidgetAction(action, errors, warnings);
|
|
8598
|
+
break;
|
|
8599
|
+
case "core:wait":
|
|
8600
|
+
validateWaitAction(action, errors, warnings);
|
|
8601
|
+
break;
|
|
8602
|
+
case "core:sequence":
|
|
8603
|
+
validateSequenceAction(action, errors, warnings);
|
|
8604
|
+
break;
|
|
8605
|
+
case "core:parallel":
|
|
8606
|
+
validateParallelAction(action, errors, warnings);
|
|
8607
|
+
break;
|
|
8608
|
+
case "overlays:tour":
|
|
8609
|
+
validateTourAction(action, errors, warnings);
|
|
8610
|
+
break;
|
|
8611
|
+
case "navigation:navigate":
|
|
8612
|
+
validateNavigateAction(action, errors, warnings);
|
|
8613
|
+
break;
|
|
8614
|
+
}
|
|
8615
|
+
return {
|
|
8616
|
+
valid: errors.length === 0,
|
|
8617
|
+
errors,
|
|
8618
|
+
warnings
|
|
8619
|
+
};
|
|
8620
|
+
}
|
|
8621
|
+
function validateAnchorAction(action, errors, warnings) {
|
|
8622
|
+
const anchorId = action.anchorId;
|
|
8623
|
+
if (!anchorId || typeof anchorId !== "object") {
|
|
8624
|
+
errors.push({
|
|
8625
|
+
code: "MISSING_ANCHOR_ID",
|
|
8626
|
+
message: "Action requires an 'anchorId' object with a 'selector' string",
|
|
8627
|
+
field: "anchorId"
|
|
8628
|
+
});
|
|
8629
|
+
return;
|
|
8630
|
+
}
|
|
8631
|
+
if (!anchorId.selector || typeof anchorId.selector !== "string") {
|
|
8632
|
+
errors.push({
|
|
8633
|
+
code: "MISSING_ANCHOR_SELECTOR",
|
|
8634
|
+
message: "anchorId requires a 'selector' string",
|
|
8635
|
+
field: "anchorId.selector"
|
|
8636
|
+
});
|
|
8637
|
+
} else if (anchorId.selector.length > 200) {
|
|
8638
|
+
warnings.push({
|
|
8639
|
+
code: "LONG_ANCHOR_ID",
|
|
8640
|
+
message: "Anchor selector is unusually long",
|
|
8641
|
+
suggestion: "Consider using a shorter, more descriptive selector"
|
|
8642
|
+
});
|
|
8643
|
+
}
|
|
8644
|
+
if (anchorId.route === void 0 || anchorId.route === null) {
|
|
8645
|
+
errors.push({
|
|
8646
|
+
code: "MISSING_ANCHOR_ROUTE",
|
|
8647
|
+
message: `anchorId requires a 'route' (string or array of strings). Use "**" for all routes.`,
|
|
8648
|
+
field: "anchorId.route"
|
|
8649
|
+
});
|
|
8650
|
+
} else {
|
|
8651
|
+
const routes = Array.isArray(anchorId.route) ? anchorId.route : [anchorId.route];
|
|
8652
|
+
for (const route of routes) {
|
|
8653
|
+
if (typeof route !== "string") {
|
|
8654
|
+
errors.push({
|
|
8655
|
+
code: "INVALID_ANCHOR_ROUTE",
|
|
8656
|
+
message: "anchorId.route must be a string or array of strings",
|
|
8657
|
+
field: "anchorId.route"
|
|
8658
|
+
});
|
|
8659
|
+
break;
|
|
8660
|
+
}
|
|
8661
|
+
}
|
|
8662
|
+
}
|
|
8663
|
+
}
|
|
8061
8664
|
function validateActions(actions) {
|
|
8062
8665
|
var _a2;
|
|
8063
8666
|
const errors = [];
|
|
@@ -8204,7 +8807,7 @@ function createActionEngine(options) {
|
|
|
8204
8807
|
}
|
|
8205
8808
|
return executor(action, context);
|
|
8206
8809
|
}
|
|
8207
|
-
function subscribeForReeval(id, action, triggerWhen,
|
|
8810
|
+
function subscribeForReeval(id, action, triggerWhen, _handle) {
|
|
8208
8811
|
if (!runtime3) return;
|
|
8209
8812
|
const unsubs = [];
|
|
8210
8813
|
const onReeval = async () => {
|
|
@@ -9174,6 +9777,66 @@ function createEventAccumulator(options) {
|
|
|
9174
9777
|
};
|
|
9175
9778
|
}
|
|
9176
9779
|
|
|
9780
|
+
// src/events/validation.ts
|
|
9781
|
+
var APP_PREFIX = "app:";
|
|
9782
|
+
var RESERVED_PREFIX = "syntro:";
|
|
9783
|
+
var SEGMENT_PATTERN = /^[a-z][a-z0-9_]*$/;
|
|
9784
|
+
function validateEventName(name) {
|
|
9785
|
+
if (!name) {
|
|
9786
|
+
return { valid: false, reason: "Event name cannot be empty" };
|
|
9787
|
+
}
|
|
9788
|
+
if (name.startsWith(RESERVED_PREFIX)) {
|
|
9789
|
+
return { valid: false, reason: '"syntro:" prefix is reserved for internal SDK events' };
|
|
9790
|
+
}
|
|
9791
|
+
if (!name.startsWith(APP_PREFIX)) {
|
|
9792
|
+
return { valid: false, reason: `Custom events must start with "app:" prefix. Got: "${name}"` };
|
|
9793
|
+
}
|
|
9794
|
+
const segments = name.slice(APP_PREFIX.length).split(":");
|
|
9795
|
+
if (segments.length < 2) {
|
|
9796
|
+
return {
|
|
9797
|
+
valid: false,
|
|
9798
|
+
reason: `Event name must have at least 2 segments after "app:" (app:{category}:{action}). Got: "${name}"`
|
|
9799
|
+
};
|
|
9800
|
+
}
|
|
9801
|
+
for (const segment of segments) {
|
|
9802
|
+
if (!SEGMENT_PATTERN.test(segment)) {
|
|
9803
|
+
return {
|
|
9804
|
+
valid: false,
|
|
9805
|
+
reason: `Segment "${segment}" must be lowercase alphanumeric + underscores. Got: "${name}"`
|
|
9806
|
+
};
|
|
9807
|
+
}
|
|
9808
|
+
}
|
|
9809
|
+
return { valid: true };
|
|
9810
|
+
}
|
|
9811
|
+
function isSerializable(value) {
|
|
9812
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null;
|
|
9813
|
+
}
|
|
9814
|
+
function checkDepth(obj, maxDepth, current = 0) {
|
|
9815
|
+
if (current >= maxDepth) return false;
|
|
9816
|
+
for (const value of Object.values(obj)) {
|
|
9817
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
9818
|
+
if (!checkDepth(value, maxDepth, current + 1)) return false;
|
|
9819
|
+
}
|
|
9820
|
+
}
|
|
9821
|
+
return true;
|
|
9822
|
+
}
|
|
9823
|
+
function validateProps(props) {
|
|
9824
|
+
if (props === void 0) return { valid: true };
|
|
9825
|
+
if (props === null || typeof props !== "object" || Array.isArray(props)) {
|
|
9826
|
+
return { valid: false, reason: "Props must be a plain object" };
|
|
9827
|
+
}
|
|
9828
|
+
if (!checkDepth(props, 2)) {
|
|
9829
|
+
return { valid: false, reason: "Props nesting depth exceeds 2 levels" };
|
|
9830
|
+
}
|
|
9831
|
+
const stripped = [];
|
|
9832
|
+
for (const [key, value] of Object.entries(props)) {
|
|
9833
|
+
if (value !== null && typeof value === "object") continue;
|
|
9834
|
+
if (!isSerializable(value)) stripped.push(key);
|
|
9835
|
+
}
|
|
9836
|
+
if (stripped.length > 0) return { valid: true, stripped };
|
|
9837
|
+
return { valid: true };
|
|
9838
|
+
}
|
|
9839
|
+
|
|
9177
9840
|
// src/events/EventBus.ts
|
|
9178
9841
|
function matchesFilter(event, filter) {
|
|
9179
9842
|
if (!filter) return true;
|
|
@@ -9205,8 +9868,16 @@ var EventBus = class {
|
|
|
9205
9868
|
__publicField(this, "subscriptions", /* @__PURE__ */ new Set());
|
|
9206
9869
|
__publicField(this, "history", []);
|
|
9207
9870
|
__publicField(this, "maxHistorySize");
|
|
9208
|
-
|
|
9871
|
+
__publicField(this, "debug");
|
|
9872
|
+
__publicField(this, "emitHistory");
|
|
9873
|
+
__publicField(this, "posthogCapture");
|
|
9874
|
+
__publicField(this, "testMode");
|
|
9875
|
+
var _a2, _b, _c, _d, _e;
|
|
9209
9876
|
this.maxHistorySize = (_a2 = options.maxHistorySize) != null ? _a2 : 100;
|
|
9877
|
+
this.debug = (_b = options.debug) != null ? _b : false;
|
|
9878
|
+
this.emitHistory = (_c = options.history) != null ? _c : null;
|
|
9879
|
+
this.posthogCapture = (_d = options.posthogCapture) != null ? _d : null;
|
|
9880
|
+
this.testMode = (_e = options.testMode) != null ? _e : false;
|
|
9210
9881
|
}
|
|
9211
9882
|
/**
|
|
9212
9883
|
* Subscribe to events matching an optional filter.
|
|
@@ -9259,6 +9930,83 @@ var EventBus = class {
|
|
|
9259
9930
|
}
|
|
9260
9931
|
}
|
|
9261
9932
|
}
|
|
9933
|
+
/**
|
|
9934
|
+
* Emit a validated custom event from the host application.
|
|
9935
|
+
*
|
|
9936
|
+
* Custom events must use the `app:` prefix (e.g. `app:cart:abandoned`).
|
|
9937
|
+
* In debug mode, returns an EmitResult with delivery details.
|
|
9938
|
+
* In production mode, returns undefined.
|
|
9939
|
+
*/
|
|
9940
|
+
emit(name, props) {
|
|
9941
|
+
const nameResult = validateEventName(name);
|
|
9942
|
+
if (!nameResult.valid) {
|
|
9943
|
+
console.warn(`[EventBus] emit() rejected: ${nameResult.reason}`);
|
|
9944
|
+
return this.debug ? { delivered: false, matchedRules: [], posthogCaptured: false, listenersNotified: 0 } : void 0;
|
|
9945
|
+
}
|
|
9946
|
+
const propsResult = validateProps(props);
|
|
9947
|
+
if (!propsResult.valid) {
|
|
9948
|
+
console.warn(`[EventBus] emit() rejected props: ${propsResult.reason}`);
|
|
9949
|
+
return this.debug ? { delivered: false, matchedRules: [], posthogCaptured: false, listenersNotified: 0 } : void 0;
|
|
9950
|
+
}
|
|
9951
|
+
const event = {
|
|
9952
|
+
ts: Date.now(),
|
|
9953
|
+
name,
|
|
9954
|
+
source: "custom",
|
|
9955
|
+
props,
|
|
9956
|
+
schemaVersion: EVENT_SCHEMA_VERSION
|
|
9957
|
+
};
|
|
9958
|
+
this.history.push(event);
|
|
9959
|
+
if (this.history.length > this.maxHistorySize) {
|
|
9960
|
+
this.history.shift();
|
|
9961
|
+
}
|
|
9962
|
+
let listenersNotified = 0;
|
|
9963
|
+
for (const subscription of this.subscriptions) {
|
|
9964
|
+
if (matchesFilter(event, subscription.filter)) {
|
|
9965
|
+
try {
|
|
9966
|
+
subscription.callback(event);
|
|
9967
|
+
listenersNotified++;
|
|
9968
|
+
} catch (err) {
|
|
9969
|
+
console.error("[EventBus] Subscriber error:", err);
|
|
9970
|
+
listenersNotified++;
|
|
9971
|
+
}
|
|
9972
|
+
}
|
|
9973
|
+
}
|
|
9974
|
+
let posthogCaptured = false;
|
|
9975
|
+
if (this.posthogCapture && !this.testMode) {
|
|
9976
|
+
try {
|
|
9977
|
+
this.posthogCapture(name, props);
|
|
9978
|
+
posthogCaptured = true;
|
|
9979
|
+
} catch (err) {
|
|
9980
|
+
console.error("[EventBus] PostHog capture error:", err);
|
|
9981
|
+
}
|
|
9982
|
+
}
|
|
9983
|
+
if (this.emitHistory) {
|
|
9984
|
+
this.emitHistory.record({
|
|
9985
|
+
name,
|
|
9986
|
+
props,
|
|
9987
|
+
source: "custom",
|
|
9988
|
+
timestamp: event.ts,
|
|
9989
|
+
matchedRules: []
|
|
9990
|
+
});
|
|
9991
|
+
}
|
|
9992
|
+
if (this.debug) {
|
|
9993
|
+
console.debug("[EventBus] emit()", { name, props, listenersNotified, posthogCaptured });
|
|
9994
|
+
return {
|
|
9995
|
+
delivered: true,
|
|
9996
|
+
matchedRules: [],
|
|
9997
|
+
posthogCaptured,
|
|
9998
|
+
listenersNotified
|
|
9999
|
+
};
|
|
10000
|
+
}
|
|
10001
|
+
return void 0;
|
|
10002
|
+
}
|
|
10003
|
+
/**
|
|
10004
|
+
* Set the PostHog capture function after construction.
|
|
10005
|
+
* Used by bootstrap to wire PostHog after the EventBus is created.
|
|
10006
|
+
*/
|
|
10007
|
+
setPosthogCapture(fn) {
|
|
10008
|
+
this.posthogCapture = fn;
|
|
10009
|
+
}
|
|
9262
10010
|
/**
|
|
9263
10011
|
* Get recent events matching an optional filter.
|
|
9264
10012
|
*/
|
|
@@ -9308,133 +10056,27 @@ var EventBus = class {
|
|
|
9308
10056
|
function createEventBus(options = {}) {
|
|
9309
10057
|
return new EventBus(options);
|
|
9310
10058
|
}
|
|
9311
|
-
|
|
9312
|
-
// src/events/
|
|
9313
|
-
var
|
|
9314
|
-
|
|
9315
|
-
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
$pageview: StandardEvents.NAV_PAGE_VIEW,
|
|
9324
|
-
$pageleave: StandardEvents.NAV_PAGE_LEAVE,
|
|
9325
|
-
// Session events
|
|
9326
|
-
$session_start: "session.start",
|
|
9327
|
-
// Identify events
|
|
9328
|
-
$identify: "user.identify"
|
|
9329
|
-
};
|
|
9330
|
-
function getEventName(phEvent) {
|
|
9331
|
-
var _a2, _b;
|
|
9332
|
-
const eventName = phEvent.event;
|
|
9333
|
-
if (typeof eventName !== "string") {
|
|
9334
|
-
return "posthog.unknown";
|
|
9335
|
-
}
|
|
9336
|
-
if (POSTHOG_EVENT_MAP[eventName]) {
|
|
9337
|
-
return POSTHOG_EVENT_MAP[eventName];
|
|
9338
|
-
}
|
|
9339
|
-
if (eventName === "$autocapture") {
|
|
9340
|
-
const tagName = (_a2 = phEvent.properties) == null ? void 0 : _a2.$tag_name;
|
|
9341
|
-
const eventType = (_b = phEvent.properties) == null ? void 0 : _b.$event_type;
|
|
9342
|
-
if (eventType === "submit") return StandardEvents.UI_SUBMIT;
|
|
9343
|
-
if (eventType === "change") return StandardEvents.UI_CHANGE;
|
|
9344
|
-
if (tagName === "input" || tagName === "textarea") return StandardEvents.UI_INPUT;
|
|
9345
|
-
return StandardEvents.UI_CLICK;
|
|
9346
|
-
}
|
|
9347
|
-
if (!eventName.startsWith("$")) {
|
|
9348
|
-
return `posthog.${eventName}`;
|
|
9349
|
-
}
|
|
9350
|
-
return eventName.replace("$", "posthog.");
|
|
9351
|
-
}
|
|
9352
|
-
var INTERACTIVE_TAGS = /* @__PURE__ */ new Set(["a", "button", "input", "select", "textarea"]);
|
|
9353
|
-
function resolveInteractiveTag(elements, directTag) {
|
|
9354
|
-
if (directTag && INTERACTIVE_TAGS.has(directTag)) return directTag;
|
|
9355
|
-
if (!elements) return directTag;
|
|
9356
|
-
for (const el of elements) {
|
|
9357
|
-
const tag2 = el.tag_name;
|
|
9358
|
-
if (tag2 && INTERACTIVE_TAGS.has(tag2)) return tag2;
|
|
9359
|
-
}
|
|
9360
|
-
return directTag;
|
|
9361
|
-
}
|
|
9362
|
-
function extractProps(phEvent) {
|
|
9363
|
-
var _a2, _b;
|
|
9364
|
-
const props = {};
|
|
9365
|
-
const phProps = phEvent.properties || {};
|
|
9366
|
-
const elements = phProps.$elements;
|
|
9367
|
-
const directTag = (_b = phProps.$tag_name) != null ? _b : (_a2 = elements == null ? void 0 : elements[0]) == null ? void 0 : _a2.tag_name;
|
|
9368
|
-
const isClickEvent = phEvent.event === "$autocapture" || phEvent.event === "$click";
|
|
9369
|
-
props.tagName = isClickEvent ? resolveInteractiveTag(elements, directTag) : directTag;
|
|
9370
|
-
if (phProps.$el_text) props.elementText = phProps.$el_text;
|
|
9371
|
-
if (elements) props.elements = elements;
|
|
9372
|
-
if (phProps.$current_url) props.url = phProps.$current_url;
|
|
9373
|
-
if (phProps.$pathname) props.pathname = phProps.$pathname;
|
|
9374
|
-
if (phProps.$host) props.host = phProps.$host;
|
|
9375
|
-
if (phProps.$viewport_width) props.viewportWidth = phProps.$viewport_width;
|
|
9376
|
-
if (phProps.$viewport_height) props.viewportHeight = phProps.$viewport_height;
|
|
9377
|
-
if (phProps.$session_id) props.sessionId = phProps.$session_id;
|
|
9378
|
-
if (phProps.$scroll_depth) props.scrollDepth = phProps.$scroll_depth;
|
|
9379
|
-
if (phProps.$scroll_percentage) props.scrollPercentage = phProps.$scroll_percentage;
|
|
9380
|
-
props.originalEvent = phEvent.event;
|
|
9381
|
-
return props;
|
|
9382
|
-
}
|
|
9383
|
-
function normalizePostHogEvent(phEvent) {
|
|
9384
|
-
let ts;
|
|
9385
|
-
if (typeof phEvent.timestamp === "number") {
|
|
9386
|
-
ts = phEvent.timestamp;
|
|
9387
|
-
} else if (typeof phEvent.timestamp === "string") {
|
|
9388
|
-
ts = new Date(phEvent.timestamp).getTime();
|
|
9389
|
-
} else {
|
|
9390
|
-
ts = Date.now();
|
|
9391
|
-
}
|
|
9392
|
-
return {
|
|
9393
|
-
ts,
|
|
9394
|
-
name: getEventName(phEvent),
|
|
9395
|
-
source: "posthog",
|
|
9396
|
-
props: extractProps(phEvent),
|
|
9397
|
-
schemaVersion: EVENT_SCHEMA_VERSION
|
|
9398
|
-
};
|
|
9399
|
-
}
|
|
9400
|
-
function shouldNormalizeEvent(phEvent) {
|
|
9401
|
-
const eventName = phEvent.event;
|
|
9402
|
-
if (typeof eventName !== "string") return false;
|
|
9403
|
-
const skipEvents = [
|
|
9404
|
-
"$feature_flag_called",
|
|
9405
|
-
"$feature_flags",
|
|
9406
|
-
"$groups",
|
|
9407
|
-
"$groupidentify",
|
|
9408
|
-
"$set",
|
|
9409
|
-
"$set_once",
|
|
9410
|
-
"$unset",
|
|
9411
|
-
"$create_alias",
|
|
9412
|
-
"$capture_metrics",
|
|
9413
|
-
"$performance_event",
|
|
9414
|
-
"$web_vitals",
|
|
9415
|
-
"$exception",
|
|
9416
|
-
"$dead_click",
|
|
9417
|
-
"$heatmap"
|
|
9418
|
-
];
|
|
9419
|
-
if (skipEvents.includes(eventName)) {
|
|
9420
|
-
return false;
|
|
9421
|
-
}
|
|
9422
|
-
return true;
|
|
9423
|
-
}
|
|
9424
|
-
function createPostHogNormalizer(publishFn) {
|
|
9425
|
-
return (eventName, properties) => {
|
|
9426
|
-
if (typeof eventName !== "string") return;
|
|
9427
|
-
const phEvent = {
|
|
9428
|
-
event: eventName,
|
|
9429
|
-
properties,
|
|
9430
|
-
timestamp: Date.now()
|
|
9431
|
-
};
|
|
9432
|
-
if (shouldNormalizeEvent(phEvent)) {
|
|
9433
|
-
const normalizedEvent = normalizePostHogEvent(phEvent);
|
|
9434
|
-
publishFn(normalizedEvent);
|
|
10059
|
+
|
|
10060
|
+
// src/events/history.ts
|
|
10061
|
+
var EventHistory = class {
|
|
10062
|
+
constructor(maxSize = 100) {
|
|
10063
|
+
__publicField(this, "entries", []);
|
|
10064
|
+
__publicField(this, "maxSize");
|
|
10065
|
+
this.maxSize = maxSize;
|
|
10066
|
+
}
|
|
10067
|
+
record(entry) {
|
|
10068
|
+
this.entries.push(entry);
|
|
10069
|
+
if (this.maxSize > 0 && this.entries.length > this.maxSize) {
|
|
10070
|
+
this.entries.shift();
|
|
9435
10071
|
}
|
|
9436
|
-
}
|
|
9437
|
-
|
|
10072
|
+
}
|
|
10073
|
+
getAll() {
|
|
10074
|
+
return [...this.entries];
|
|
10075
|
+
}
|
|
10076
|
+
clear() {
|
|
10077
|
+
this.entries = [];
|
|
10078
|
+
}
|
|
10079
|
+
};
|
|
9438
10080
|
|
|
9439
10081
|
// src/navigation/NavigationMonitor.ts
|
|
9440
10082
|
var NavigationMonitor = class {
|
|
@@ -10547,7 +11189,16 @@ function matchesAnchorRoute(anchorId) {
|
|
|
10547
11189
|
const pathname = typeof window !== "undefined" ? window.location.pathname : "/";
|
|
10548
11190
|
const normalizedPath = pathname.replace(/\/$/, "") || "/";
|
|
10549
11191
|
const routes = Array.isArray(anchorId.route) ? anchorId.route : [anchorId.route];
|
|
10550
|
-
return routes.some((pattern) =>
|
|
11192
|
+
return routes.some((pattern) => {
|
|
11193
|
+
let normalized = pattern;
|
|
11194
|
+
if (/^https?:\/\//.test(normalized)) {
|
|
11195
|
+
try {
|
|
11196
|
+
normalized = new URL(normalized).pathname;
|
|
11197
|
+
} catch {
|
|
11198
|
+
}
|
|
11199
|
+
}
|
|
11200
|
+
return matchRoutePattern(normalizedPath, normalized);
|
|
11201
|
+
});
|
|
10551
11202
|
}
|
|
10552
11203
|
function createSmartCanvasRuntime(options = {}) {
|
|
10553
11204
|
var _a2, _b, _c, _d;
|
|
@@ -10719,6 +11370,142 @@ function encodeToken(payload) {
|
|
|
10719
11370
|
return TOKEN_PREFIX + base64;
|
|
10720
11371
|
}
|
|
10721
11372
|
|
|
11373
|
+
// src/bootstrap-init.ts
|
|
11374
|
+
function getEnvVar(name) {
|
|
11375
|
+
if (typeof process !== "undefined" && process.env) {
|
|
11376
|
+
return process.env[name];
|
|
11377
|
+
}
|
|
11378
|
+
try {
|
|
11379
|
+
const meta = (0, eval)("import.meta");
|
|
11380
|
+
if (meta == null ? void 0 : meta.env) {
|
|
11381
|
+
return meta.env[name];
|
|
11382
|
+
}
|
|
11383
|
+
} catch {
|
|
11384
|
+
}
|
|
11385
|
+
return void 0;
|
|
11386
|
+
}
|
|
11387
|
+
var SEGMENT_CACHE_KEY = "syntro_segment_attributes";
|
|
11388
|
+
function loadCachedSegmentAttributes() {
|
|
11389
|
+
if (typeof window === "undefined") return {};
|
|
11390
|
+
try {
|
|
11391
|
+
const cached = localStorage.getItem(SEGMENT_CACHE_KEY);
|
|
11392
|
+
if (cached) {
|
|
11393
|
+
const attrs = JSON.parse(cached);
|
|
11394
|
+
debug("Syntro Bootstrap", "Loaded cached segment attributes:", attrs);
|
|
11395
|
+
return attrs;
|
|
11396
|
+
}
|
|
11397
|
+
} catch (err) {
|
|
11398
|
+
warn("Syntro Bootstrap", "Failed to load cached segment attributes:", err);
|
|
11399
|
+
}
|
|
11400
|
+
return {};
|
|
11401
|
+
}
|
|
11402
|
+
function cacheSegmentAttributes(attrs) {
|
|
11403
|
+
if (typeof window === "undefined") return;
|
|
11404
|
+
try {
|
|
11405
|
+
localStorage.setItem(SEGMENT_CACHE_KEY, JSON.stringify(attrs));
|
|
11406
|
+
debug("Syntro Bootstrap", "Cached segment attributes:", attrs);
|
|
11407
|
+
} catch (err) {
|
|
11408
|
+
warn("Syntro Bootstrap", "Failed to cache segment attributes:", err);
|
|
11409
|
+
}
|
|
11410
|
+
}
|
|
11411
|
+
function extractSegmentFlags(allFlags) {
|
|
11412
|
+
if (!allFlags) return {};
|
|
11413
|
+
const segmentFlags = {};
|
|
11414
|
+
for (const [key, value] of Object.entries(allFlags)) {
|
|
11415
|
+
if (key.startsWith("in_segment_")) {
|
|
11416
|
+
segmentFlags[key] = value === true;
|
|
11417
|
+
}
|
|
11418
|
+
}
|
|
11419
|
+
return segmentFlags;
|
|
11420
|
+
}
|
|
11421
|
+
function collectBrowserMetadata() {
|
|
11422
|
+
var _a2;
|
|
11423
|
+
if (typeof window === "undefined") return {};
|
|
11424
|
+
const attrs = {};
|
|
11425
|
+
try {
|
|
11426
|
+
const params = new URLSearchParams(window.location.search);
|
|
11427
|
+
for (const key of ["utm_source", "utm_medium", "utm_campaign", "utm_content", "utm_term"]) {
|
|
11428
|
+
const val = params.get(key);
|
|
11429
|
+
if (val) attrs[key] = val;
|
|
11430
|
+
}
|
|
11431
|
+
} catch {
|
|
11432
|
+
}
|
|
11433
|
+
try {
|
|
11434
|
+
if (navigator.language) attrs.browser_language = navigator.language;
|
|
11435
|
+
if ((_a2 = navigator.languages) == null ? void 0 : _a2.length) attrs.browser_languages = [...navigator.languages];
|
|
11436
|
+
} catch {
|
|
11437
|
+
}
|
|
11438
|
+
try {
|
|
11439
|
+
const w = window.innerWidth;
|
|
11440
|
+
attrs.device_type = w < 768 ? "mobile" : w < 1024 ? "tablet" : "desktop";
|
|
11441
|
+
} catch {
|
|
11442
|
+
}
|
|
11443
|
+
try {
|
|
11444
|
+
if (document.referrer) {
|
|
11445
|
+
attrs.referrer = document.referrer;
|
|
11446
|
+
try {
|
|
11447
|
+
attrs.referrer_hostname = new URL(document.referrer).hostname;
|
|
11448
|
+
} catch {
|
|
11449
|
+
}
|
|
11450
|
+
}
|
|
11451
|
+
} catch {
|
|
11452
|
+
}
|
|
11453
|
+
try {
|
|
11454
|
+
const ua = navigator.userAgent;
|
|
11455
|
+
if (ua.includes("Edg/")) attrs.browser = "Edge";
|
|
11456
|
+
else if (ua.includes("OPR/") || ua.includes("Opera")) attrs.browser = "Opera";
|
|
11457
|
+
else if (ua.includes("Chrome/") && !ua.includes("Chromium")) attrs.browser = "Chrome";
|
|
11458
|
+
else if (ua.includes("Safari/") && !ua.includes("Chrome")) attrs.browser = "Safari";
|
|
11459
|
+
else if (ua.includes("Firefox/")) attrs.browser = "Firefox";
|
|
11460
|
+
if (ua.includes("Windows")) attrs.os = "Windows";
|
|
11461
|
+
else if (ua.includes("iPhone") || ua.includes("iPad")) attrs.os = "iOS";
|
|
11462
|
+
else if (ua.includes("Mac OS X") || ua.includes("Macintosh")) attrs.os = "macOS";
|
|
11463
|
+
else if (ua.includes("Android")) attrs.os = "Android";
|
|
11464
|
+
else if (ua.includes("Linux")) attrs.os = "Linux";
|
|
11465
|
+
} catch {
|
|
11466
|
+
}
|
|
11467
|
+
try {
|
|
11468
|
+
attrs.page_url = window.location.href;
|
|
11469
|
+
attrs.page_path = window.location.pathname;
|
|
11470
|
+
attrs.page_host = window.location.hostname;
|
|
11471
|
+
if (window.location.search) attrs.page_query = window.location.search;
|
|
11472
|
+
} catch {
|
|
11473
|
+
}
|
|
11474
|
+
return attrs;
|
|
11475
|
+
}
|
|
11476
|
+
var GEO_CACHE_KEY = "syntro_geo";
|
|
11477
|
+
var GEO_DEFAULT_HOST = "https://geo.syntrologie.com";
|
|
11478
|
+
async function fetchGeo(geoHost) {
|
|
11479
|
+
if (typeof window === "undefined") return {};
|
|
11480
|
+
try {
|
|
11481
|
+
const cached = localStorage.getItem(GEO_CACHE_KEY);
|
|
11482
|
+
if (cached) {
|
|
11483
|
+
const parsed = JSON.parse(cached);
|
|
11484
|
+
debug("Syntro Bootstrap", "Geo: using cached data:", parsed);
|
|
11485
|
+
return parsed;
|
|
11486
|
+
}
|
|
11487
|
+
} catch {
|
|
11488
|
+
}
|
|
11489
|
+
try {
|
|
11490
|
+
const res = await fetch(geoHost, { signal: AbortSignal.timeout(2e3) });
|
|
11491
|
+
if (res.ok) {
|
|
11492
|
+
const geo = await res.json();
|
|
11493
|
+
const cleaned = {};
|
|
11494
|
+
for (const [k, v] of Object.entries(geo)) {
|
|
11495
|
+
if (typeof v === "string" && v) cleaned[k] = v;
|
|
11496
|
+
}
|
|
11497
|
+
try {
|
|
11498
|
+
localStorage.setItem(GEO_CACHE_KEY, JSON.stringify(cleaned));
|
|
11499
|
+
} catch {
|
|
11500
|
+
}
|
|
11501
|
+
debug("Syntro Bootstrap", "Geo: fetched from worker:", cleaned);
|
|
11502
|
+
return cleaned;
|
|
11503
|
+
}
|
|
11504
|
+
} catch {
|
|
11505
|
+
}
|
|
11506
|
+
return {};
|
|
11507
|
+
}
|
|
11508
|
+
|
|
10722
11509
|
// src/experiments/registry.ts
|
|
10723
11510
|
var adapters = {
|
|
10724
11511
|
growthbook: (config) => createGrowthBookClient({
|
|
@@ -10856,6 +11643,11 @@ var ExperimentsFetcher = class {
|
|
|
10856
11643
|
};
|
|
10857
11644
|
}
|
|
10858
11645
|
}
|
|
11646
|
+
if (!this.featureKey) {
|
|
11647
|
+
throw new Error(
|
|
11648
|
+
"[SmartCanvas] No featureKey configured and no variant flags found. Ensure at least one config feature flag exists in your experiment platform."
|
|
11649
|
+
);
|
|
11650
|
+
}
|
|
10859
11651
|
const config = (_b = (_a2 = this.client).getFeatureValue) == null ? void 0 : _b.call(_a2, this.featureKey, null);
|
|
10860
11652
|
if (!config || typeof config !== "object") {
|
|
10861
11653
|
throw new Error(
|
|
@@ -10967,95 +11759,9 @@ function createTelemetryClient(provider, config) {
|
|
|
10967
11759
|
return factory(config);
|
|
10968
11760
|
}
|
|
10969
11761
|
|
|
10970
|
-
// src/bootstrap.ts
|
|
10971
|
-
function
|
|
10972
|
-
|
|
10973
|
-
return process.env[name];
|
|
10974
|
-
}
|
|
10975
|
-
try {
|
|
10976
|
-
const meta = (0, eval)("import.meta");
|
|
10977
|
-
if (meta == null ? void 0 : meta.env) {
|
|
10978
|
-
return meta.env[name];
|
|
10979
|
-
}
|
|
10980
|
-
} catch {
|
|
10981
|
-
}
|
|
10982
|
-
return void 0;
|
|
10983
|
-
}
|
|
10984
|
-
var SEGMENT_CACHE_KEY = "syntro_segment_attributes";
|
|
10985
|
-
function loadCachedSegmentAttributes() {
|
|
10986
|
-
if (typeof window === "undefined") return {};
|
|
10987
|
-
try {
|
|
10988
|
-
const cached = localStorage.getItem(SEGMENT_CACHE_KEY);
|
|
10989
|
-
if (cached) {
|
|
10990
|
-
const attrs = JSON.parse(cached);
|
|
10991
|
-
debug("Syntro Bootstrap", "Loaded cached segment attributes:", attrs);
|
|
10992
|
-
return attrs;
|
|
10993
|
-
}
|
|
10994
|
-
} catch (err) {
|
|
10995
|
-
warn("Syntro Bootstrap", "Failed to load cached segment attributes:", err);
|
|
10996
|
-
}
|
|
10997
|
-
return {};
|
|
10998
|
-
}
|
|
10999
|
-
function cacheSegmentAttributes(attrs) {
|
|
11000
|
-
if (typeof window === "undefined") return;
|
|
11001
|
-
try {
|
|
11002
|
-
localStorage.setItem(SEGMENT_CACHE_KEY, JSON.stringify(attrs));
|
|
11003
|
-
debug("Syntro Bootstrap", "Cached segment attributes:", attrs);
|
|
11004
|
-
} catch (err) {
|
|
11005
|
-
warn("Syntro Bootstrap", "Failed to cache segment attributes:", err);
|
|
11006
|
-
}
|
|
11007
|
-
}
|
|
11008
|
-
function extractSegmentFlags(allFlags) {
|
|
11009
|
-
if (!allFlags) return {};
|
|
11010
|
-
const segmentFlags = {};
|
|
11011
|
-
for (const [key, value] of Object.entries(allFlags)) {
|
|
11012
|
-
if (key.startsWith("in_segment_")) {
|
|
11013
|
-
segmentFlags[key] = value === true;
|
|
11014
|
-
}
|
|
11015
|
-
}
|
|
11016
|
-
return segmentFlags;
|
|
11017
|
-
}
|
|
11018
|
-
function collectBrowserMetadata() {
|
|
11019
|
-
var _a2;
|
|
11020
|
-
if (typeof window === "undefined") return {};
|
|
11021
|
-
const attrs = {};
|
|
11022
|
-
try {
|
|
11023
|
-
const params = new URLSearchParams(window.location.search);
|
|
11024
|
-
for (const key of ["utm_source", "utm_medium", "utm_campaign", "utm_content", "utm_term"]) {
|
|
11025
|
-
const val = params.get(key);
|
|
11026
|
-
if (val) attrs[key] = val;
|
|
11027
|
-
}
|
|
11028
|
-
} catch {
|
|
11029
|
-
}
|
|
11030
|
-
try {
|
|
11031
|
-
if (navigator.language) attrs.browser_language = navigator.language;
|
|
11032
|
-
if ((_a2 = navigator.languages) == null ? void 0 : _a2.length) attrs.browser_languages = [...navigator.languages];
|
|
11033
|
-
} catch {
|
|
11034
|
-
}
|
|
11035
|
-
try {
|
|
11036
|
-
const w = window.innerWidth;
|
|
11037
|
-
attrs.device_type = w < 768 ? "mobile" : w < 1024 ? "tablet" : "desktop";
|
|
11038
|
-
} catch {
|
|
11039
|
-
}
|
|
11040
|
-
try {
|
|
11041
|
-
if (document.referrer) {
|
|
11042
|
-
attrs.referrer = document.referrer;
|
|
11043
|
-
try {
|
|
11044
|
-
attrs.referrer_hostname = new URL(document.referrer).hostname;
|
|
11045
|
-
} catch {
|
|
11046
|
-
}
|
|
11047
|
-
}
|
|
11048
|
-
} catch {
|
|
11049
|
-
}
|
|
11050
|
-
try {
|
|
11051
|
-
attrs.page_url = window.location.href;
|
|
11052
|
-
attrs.page_path = window.location.pathname;
|
|
11053
|
-
} catch {
|
|
11054
|
-
}
|
|
11055
|
-
return attrs;
|
|
11056
|
-
}
|
|
11057
|
-
async function init(options) {
|
|
11058
|
-
var _a2, _b, _c, _d, _e, _f;
|
|
11762
|
+
// src/bootstrap-runtime.ts
|
|
11763
|
+
async function _initCore(options) {
|
|
11764
|
+
var _a2, _b, _c, _d, _e, _f, _g;
|
|
11059
11765
|
initLogger();
|
|
11060
11766
|
debug("Syntro Bootstrap", "====== INIT ======");
|
|
11061
11767
|
debug("Syntro Bootstrap", "Options:", {
|
|
@@ -11120,17 +11826,59 @@ async function init(options) {
|
|
|
11120
11826
|
const experimentHost = getEnvVar("NEXT_PUBLIC_SYNTRO_EXPERIMENT_HOST") || getEnvVar("VITE_SYNTRO_EXPERIMENT_HOST") || (payload == null ? void 0 : payload.eh);
|
|
11121
11827
|
const telemetryHost = getEnvVar("NEXT_PUBLIC_SYNTRO_TELEMETRY_HOST") || getEnvVar("VITE_SYNTRO_TELEMETRY_HOST") || (payload == null ? void 0 : payload.th);
|
|
11122
11828
|
const editorUrl = getEnvVar("NEXT_PUBLIC_SYNTRO_EDITOR_URL") || getEnvVar("VITE_SYNTRO_EDITOR_URL") || ((_b = options.canvas) == null ? void 0 : _b.editorUrl);
|
|
11829
|
+
const geoHost = (payload == null ? void 0 : payload.g) || getEnvVar("NEXT_PUBLIC_SYNTRO_GEO_HOST") || getEnvVar("VITE_SYNTRO_GEO_HOST") || GEO_DEFAULT_HOST;
|
|
11123
11830
|
const cachedSegmentAttrs = loadCachedSegmentAttributes();
|
|
11124
11831
|
const browserMetadata = collectBrowserMetadata();
|
|
11125
11832
|
const phaseOneAttrs = { ...browserMetadata, ...cachedSegmentAttrs };
|
|
11126
11833
|
debug("Syntro Bootstrap", "Phase 1: Browser metadata:", browserMetadata);
|
|
11127
11834
|
debug("Syntro Bootstrap", "Phase 1: Cached segment attributes:", cachedSegmentAttrs);
|
|
11835
|
+
const geoPromise = fetchGeo(geoHost);
|
|
11128
11836
|
let experiments;
|
|
11129
|
-
const
|
|
11837
|
+
const isDebugOrTest = options.debug || options.testMode;
|
|
11838
|
+
const events = createEventBus({
|
|
11839
|
+
debug: options.debug,
|
|
11840
|
+
history: isDebugOrTest ? new EventHistory(options.testMode ? 0 : 100) : void 0,
|
|
11841
|
+
testMode: options.testMode
|
|
11842
|
+
});
|
|
11130
11843
|
console.log("[Syntro Bootstrap] EventBus created");
|
|
11131
|
-
const
|
|
11132
|
-
|
|
11844
|
+
const processor = createEventProcessor({
|
|
11845
|
+
elementResolver: typeof window !== "undefined" ? (x, y) => {
|
|
11846
|
+
const el = document.elementFromPoint(x, y);
|
|
11847
|
+
if (!el) return null;
|
|
11848
|
+
const info = { tag_name: el.tagName.toLowerCase() };
|
|
11849
|
+
if (el.id) info.attr__id = el.id;
|
|
11850
|
+
if (el.className && typeof el.className === "string") {
|
|
11851
|
+
info.classes = el.className.split(" ").filter(Boolean);
|
|
11852
|
+
}
|
|
11853
|
+
for (const attr of el.attributes) {
|
|
11854
|
+
if (attr.name.startsWith("data-")) info[`attr__${attr.name}`] = attr.value;
|
|
11855
|
+
}
|
|
11856
|
+
return info;
|
|
11857
|
+
} : void 0
|
|
11133
11858
|
});
|
|
11859
|
+
processor.onEvent((event) => events.publishEvent(event));
|
|
11860
|
+
if (typeof window !== "undefined") {
|
|
11861
|
+
setInterval(() => processor.tick(Date.now()), 1e3);
|
|
11862
|
+
document.addEventListener(
|
|
11863
|
+
"click",
|
|
11864
|
+
(e) => {
|
|
11865
|
+
const chain = [];
|
|
11866
|
+
let el = e.target;
|
|
11867
|
+
while (el && el !== document.body) {
|
|
11868
|
+
const info = { tag_name: el.tagName.toLowerCase() };
|
|
11869
|
+
for (const attr of el.attributes) {
|
|
11870
|
+
if (attr.name.startsWith("data-") || attr.name === "id" || attr.name === "class" || attr.name === "aria-label") {
|
|
11871
|
+
info[`attr__${attr.name}`] = attr.value;
|
|
11872
|
+
}
|
|
11873
|
+
}
|
|
11874
|
+
chain.push(info);
|
|
11875
|
+
el = el.parentElement;
|
|
11876
|
+
}
|
|
11877
|
+
processor.enrichClickAttributes(Date.now(), chain);
|
|
11878
|
+
},
|
|
11879
|
+
true
|
|
11880
|
+
);
|
|
11881
|
+
}
|
|
11134
11882
|
const onFeatureFlagsLoaded = (allFlags) => {
|
|
11135
11883
|
var _a3, _b2, _c2;
|
|
11136
11884
|
debug("Syntro Bootstrap", "Phase 2: PostHog feature flags loaded");
|
|
@@ -11153,12 +11901,26 @@ async function init(options) {
|
|
|
11153
11901
|
// undefined falls back to adapter default
|
|
11154
11902
|
// Enable PostHog feature flags for segment membership
|
|
11155
11903
|
enableFeatureFlags: true,
|
|
11904
|
+
// Disable session recording in debug/dev mode (mock telemetry doesn't
|
|
11905
|
+
// support the PostHog recorder extension, causing console errors)
|
|
11906
|
+
sessionRecording: !payload.d,
|
|
11156
11907
|
// Wire up callback for when flags are loaded (Phase 2)
|
|
11157
11908
|
onFeatureFlagsLoaded,
|
|
11158
|
-
// Wire up event capture to feed into
|
|
11159
|
-
onCapture:
|
|
11909
|
+
// Wire up event capture to feed into event processor
|
|
11910
|
+
onCapture: (eventName, properties) => {
|
|
11911
|
+
processor.ingest({ kind: "posthog", event: eventName, properties, timestamp: Date.now() });
|
|
11912
|
+
},
|
|
11913
|
+
// Wire rrweb events for behavioral signal detection
|
|
11914
|
+
onRRWebEvent: (event) => {
|
|
11915
|
+
processor.ingest(event);
|
|
11916
|
+
}
|
|
11160
11917
|
});
|
|
11161
11918
|
console.log(`[Syntro Bootstrap] Telemetry client created (${provider}) with EventBus wiring`);
|
|
11919
|
+
const telemetryForCapture = telemetry;
|
|
11920
|
+
events.setPosthogCapture((name, props) => {
|
|
11921
|
+
var _a3;
|
|
11922
|
+
(_a3 = telemetryForCapture.track) == null ? void 0 : _a3.call(telemetryForCapture, name, props);
|
|
11923
|
+
});
|
|
11162
11924
|
}
|
|
11163
11925
|
let sessionMetrics;
|
|
11164
11926
|
if (payload == null ? void 0 : payload.e) {
|
|
@@ -11251,11 +12013,17 @@ async function init(options) {
|
|
|
11251
12013
|
warn("Syntro Bootstrap", "Failed to load GrowthBook features:", err);
|
|
11252
12014
|
}
|
|
11253
12015
|
}
|
|
12016
|
+
const geoData = await geoPromise;
|
|
12017
|
+
if (experiments && Object.keys(geoData).length > 0) {
|
|
12018
|
+
const mergedAttrs = { ...browserMetadata, ...geoData };
|
|
12019
|
+
debug("Syntro Bootstrap", "Merging geo data into GrowthBook attributes:", geoData);
|
|
12020
|
+
(_f = experiments.setAttributes) == null ? void 0 : _f.call(experiments, mergedAttrs);
|
|
12021
|
+
}
|
|
11254
12022
|
let baseFetcher;
|
|
11255
12023
|
if (options.fetcher) {
|
|
11256
12024
|
baseFetcher = options.fetcher;
|
|
11257
12025
|
} else if (payload == null ? void 0 : payload.f) {
|
|
11258
|
-
const configFetcher = createConfigFetcher(payload.f, (
|
|
12026
|
+
const configFetcher = createConfigFetcher(payload.f, (_g = payload.o) != null ? _g : {});
|
|
11259
12027
|
baseFetcher = async () => {
|
|
11260
12028
|
var _a3;
|
|
11261
12029
|
const result = await configFetcher.fetch();
|
|
@@ -11269,7 +12037,7 @@ async function init(options) {
|
|
|
11269
12037
|
}
|
|
11270
12038
|
const warnedAppFailures = /* @__PURE__ */ new Set();
|
|
11271
12039
|
const appLoadingFetcher = baseFetcher ? async () => {
|
|
11272
|
-
var _a3, _b2, _c2, _d2, _e2, _f2,
|
|
12040
|
+
var _a3, _b2, _c2, _d2, _e2, _f2, _g2;
|
|
11273
12041
|
const config = await baseFetcher();
|
|
11274
12042
|
console.log(
|
|
11275
12043
|
"[Syntro Bootstrap] Config fetched:",
|
|
@@ -11277,7 +12045,7 @@ async function init(options) {
|
|
|
11277
12045
|
`actions=${(_d2 = (_c2 = config.actions) == null ? void 0 : _c2.length) != null ? _d2 : 0},`,
|
|
11278
12046
|
`theme=${(_f2 = (_e2 = config.theme) == null ? void 0 : _e2.name) != null ? _f2 : "none"}`
|
|
11279
12047
|
);
|
|
11280
|
-
if (((
|
|
12048
|
+
if (((_g2 = config.actions) == null ? void 0 : _g2.length) > 0) {
|
|
11281
12049
|
console.log(
|
|
11282
12050
|
"[Syntro Bootstrap] Actions in config:",
|
|
11283
12051
|
config.actions.map(
|
|
@@ -11340,10 +12108,33 @@ async function init(options) {
|
|
|
11340
12108
|
});
|
|
11341
12109
|
return { canvas, runtime: runtime3, experiments, telemetry, sessionMetrics, appLoader };
|
|
11342
12110
|
}
|
|
12111
|
+
|
|
12112
|
+
// src/bootstrap.ts
|
|
12113
|
+
async function init(options) {
|
|
12114
|
+
var _a2;
|
|
12115
|
+
try {
|
|
12116
|
+
return await _initCore(options);
|
|
12117
|
+
} catch (err) {
|
|
12118
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
12119
|
+
console.warn("[Syntrologie] SDK initialization failed:", message);
|
|
12120
|
+
if (typeof document !== "undefined") {
|
|
12121
|
+
(_a2 = document.getElementById("syntrologie-anti-flicker")) == null ? void 0 : _a2.remove();
|
|
12122
|
+
}
|
|
12123
|
+
return void 0;
|
|
12124
|
+
}
|
|
12125
|
+
}
|
|
12126
|
+
function emit(eventName, props = {}) {
|
|
12127
|
+
var _a2, _b;
|
|
12128
|
+
if (typeof window === "undefined") return;
|
|
12129
|
+
const runtime3 = (_a2 = window.SynOS) == null ? void 0 : _a2.runtime;
|
|
12130
|
+
if (!((_b = runtime3 == null ? void 0 : runtime3.events) == null ? void 0 : _b.publish)) return;
|
|
12131
|
+
runtime3.events.publish({ name: eventName, source: "custom", props });
|
|
12132
|
+
}
|
|
11343
12133
|
var Syntro = {
|
|
11344
12134
|
init,
|
|
11345
12135
|
encodeToken,
|
|
11346
|
-
decodeToken
|
|
12136
|
+
decodeToken,
|
|
12137
|
+
events: { emit }
|
|
11347
12138
|
};
|
|
11348
12139
|
if (typeof window !== "undefined") {
|
|
11349
12140
|
window.Syntro = Syntro;
|
|
@@ -11374,8 +12165,11 @@ export {
|
|
|
11374
12165
|
createSmartCanvasController,
|
|
11375
12166
|
ShadowRootProvider,
|
|
11376
12167
|
useShadowRoot,
|
|
11377
|
-
StandardEvents,
|
|
11378
12168
|
EVENT_SCHEMA_VERSION,
|
|
12169
|
+
normalizePostHogEvent,
|
|
12170
|
+
shouldNormalizeEvent,
|
|
12171
|
+
createPostHogNormalizer,
|
|
12172
|
+
StandardEvents2 as StandardEvents,
|
|
11379
12173
|
CanvasEvents,
|
|
11380
12174
|
NotificationToastStack,
|
|
11381
12175
|
MAX_VISIBLE_TOASTS,
|
|
@@ -11424,11 +12218,11 @@ export {
|
|
|
11424
12218
|
evaluateSync,
|
|
11425
12219
|
createDecisionEngine,
|
|
11426
12220
|
createEventAccumulator,
|
|
12221
|
+
validateEventName,
|
|
12222
|
+
validateProps,
|
|
11427
12223
|
EventBus,
|
|
11428
12224
|
createEventBus,
|
|
11429
|
-
|
|
11430
|
-
shouldNormalizeEvent,
|
|
11431
|
-
createPostHogNormalizer,
|
|
12225
|
+
EventHistory,
|
|
11432
12226
|
NavigationMonitor,
|
|
11433
12227
|
StateStore,
|
|
11434
12228
|
createStateStore,
|
|
@@ -11452,4 +12246,4 @@ export {
|
|
|
11452
12246
|
encodeToken,
|
|
11453
12247
|
Syntro
|
|
11454
12248
|
};
|
|
11455
|
-
//# sourceMappingURL=chunk-
|
|
12249
|
+
//# sourceMappingURL=chunk-J2LGX2PV.js.map
|