@syntrologie/runtime-sdk 2.8.0-canary.9 → 2.8.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.
@@ -34,6 +34,11 @@ function guardAgainstReconciliation(container, anchor, reinsertFn, opts) {
34
34
  debounceTimer = setTimeout(() => {
35
35
  if (disconnected)
36
36
  return;
37
+ if (!anchor.isConnected) {
38
+ observer.disconnect();
39
+ disconnected = true;
40
+ return;
41
+ }
37
42
  retries++;
38
43
  try {
39
44
  reinsertFn();
@@ -75,7 +80,16 @@ var ALLOWED_TAGS = /* @__PURE__ */ new Set([
75
80
  "sup",
76
81
  "sub",
77
82
  "a",
78
- "button"
83
+ "button",
84
+ // SVG elements (for inline Lucide icons in config HTML)
85
+ "svg",
86
+ "path",
87
+ "circle",
88
+ "line",
89
+ "polyline",
90
+ "polygon",
91
+ "rect",
92
+ "g"
79
93
  ]);
80
94
  function sanitizeHtml(html) {
81
95
  var _a2;
@@ -213,15 +227,20 @@ var executeInsertHtml = async (action, context) => {
213
227
  container.removeEventListener("click", deepLinkHandler);
214
228
  }
215
229
  guardCleanup();
216
- if (action.position === "replace" && originalContent !== null) {
217
- const restoredEl = document.createElement(anchorEl.tagName);
218
- restoredEl.innerHTML = originalContent;
219
- Array.from(anchorEl.attributes).forEach((attr) => {
220
- restoredEl.setAttribute(attr.name, attr.value);
221
- });
222
- container.replaceWith(restoredEl);
223
- } else {
224
- container.remove();
230
+ if (!container.isConnected)
231
+ return;
232
+ try {
233
+ if (action.position === "replace" && originalContent !== null) {
234
+ const restoredEl = document.createElement(anchorEl.tagName);
235
+ restoredEl.innerHTML = originalContent;
236
+ Array.from(anchorEl.attributes).forEach((attr) => {
237
+ restoredEl.setAttribute(attr.name, attr.value);
238
+ });
239
+ container.replaceWith(restoredEl);
240
+ } else {
241
+ container.remove();
242
+ }
243
+ } catch {
225
244
  }
226
245
  },
227
246
  updateFn: (changes) => {
@@ -251,6 +270,8 @@ var executeSetText = async (action, context) => {
251
270
  });
252
271
  return {
253
272
  cleanup: () => {
273
+ if (!anchorEl.isConnected)
274
+ return;
254
275
  anchorEl.textContent = originalText;
255
276
  },
256
277
  updateFn: (changes) => {
@@ -292,6 +313,8 @@ var executeSetAttr = async (action, context) => {
292
313
  });
293
314
  return {
294
315
  cleanup: () => {
316
+ if (!anchorEl.isConnected)
317
+ return;
295
318
  if (hadAttribute && originalValue !== null) {
296
319
  anchorEl.setAttribute(action.attr, originalValue);
297
320
  } else {
@@ -325,6 +348,8 @@ var executeAddClass = async (action, context) => {
325
348
  });
326
349
  return {
327
350
  cleanup: () => {
351
+ if (!anchorEl.isConnected)
352
+ return;
328
353
  if (!hadClass) {
329
354
  anchorEl.classList.remove(action.className);
330
355
  }
@@ -351,6 +376,8 @@ var executeRemoveClass = async (action, context) => {
351
376
  });
352
377
  return {
353
378
  cleanup: () => {
379
+ if (!anchorEl.isConnected)
380
+ return;
354
381
  if (hadClass) {
355
382
  anchorEl.classList.add(action.className);
356
383
  }
@@ -383,6 +410,8 @@ var executeSetStyle = async (action, context) => {
383
410
  });
384
411
  return {
385
412
  cleanup: () => {
413
+ if (!anchorEl.isConnected)
414
+ return;
386
415
  for (const [prop, originalValue] of originalStyles) {
387
416
  if (originalValue) {
388
417
  anchorEl.style.setProperty(prop, originalValue);
@@ -1642,8 +1671,14 @@ function showHighlight(anchorEl, overlayRoot, opts) {
1642
1671
  scrim.style.pointerEvents = "none";
1643
1672
  scrim.style.opacity = "0";
1644
1673
  setTimeout(() => {
1645
- scrim.remove();
1646
- ring.remove();
1674
+ try {
1675
+ scrim.remove();
1676
+ } catch {
1677
+ }
1678
+ try {
1679
+ ring.remove();
1680
+ } catch {
1681
+ }
1647
1682
  }, 220);
1648
1683
  }
1649
1684
  };
@@ -1671,7 +1706,16 @@ var ALLOWED_TAGS2 = /* @__PURE__ */ new Set([
1671
1706
  "sup",
1672
1707
  "sub",
1673
1708
  "a",
1674
- "button"
1709
+ "button",
1710
+ // SVG elements (for inline Lucide icons in config HTML)
1711
+ "svg",
1712
+ "path",
1713
+ "circle",
1714
+ "line",
1715
+ "polyline",
1716
+ "polygon",
1717
+ "rect",
1718
+ "g"
1675
1719
  ]);
1676
1720
  function sanitizeHtml2(html) {
1677
1721
  var _a2;
@@ -1880,8 +1924,14 @@ var executeModal = async (action, context) => {
1880
1924
  modal2.style.transform = "translate(-50%, -50%) scale(0.95)";
1881
1925
  scrimEl.style.opacity = "0";
1882
1926
  setTimeout(() => {
1883
- modal2.remove();
1884
- scrimEl.remove();
1927
+ try {
1928
+ modal2.remove();
1929
+ } catch {
1930
+ }
1931
+ try {
1932
+ scrimEl.remove();
1933
+ } catch {
1934
+ }
1885
1935
  }, 200);
1886
1936
  context.publishEvent("action.modal_dismissed", {
1887
1937
  actionClicked
@@ -1928,10 +1978,12 @@ function getAnchorReference(anchorEl) {
1928
1978
  }
1929
1979
  function showTooltip(anchorEl, overlayRoot, opts) {
1930
1980
  var _a2;
1931
- const rect = anchorEl.getBoundingClientRect();
1932
- const isLargeElement = rect.width > window.innerWidth * 0.8 || rect.height > window.innerHeight * 0.8;
1933
- if (!isLargeElement) {
1934
- anchorEl.scrollIntoView({ behavior: "smooth", block: "center", inline: "center" });
1981
+ if (!opts.trigger || opts.trigger === "immediate") {
1982
+ const rect = anchorEl.getBoundingClientRect();
1983
+ const isLargeElement = rect.width > window.innerWidth * 0.8 || rect.height > window.innerHeight * 0.8;
1984
+ if (!isLargeElement) {
1985
+ anchorEl.scrollIntoView({ behavior: "smooth", block: "center", inline: "center" });
1986
+ }
1935
1987
  }
1936
1988
  const div = document.createElement("div");
1937
1989
  div.className = "syntro-tooltip";
@@ -2141,7 +2193,12 @@ function showTooltip(anchorEl, overlayRoot, opts) {
2141
2193
  }
2142
2194
  div.style.pointerEvents = "none";
2143
2195
  div.style.opacity = "0";
2144
- setTimeout(() => div.remove(), 200);
2196
+ setTimeout(() => {
2197
+ try {
2198
+ div.remove();
2199
+ } catch {
2200
+ }
2201
+ }, 200);
2145
2202
  }
2146
2203
  };
2147
2204
  return handle;
@@ -2174,7 +2231,7 @@ function WorkflowTracker({ workflows, expanded, onStepClick, onDismiss }) {
2174
2231
  }
2175
2232
 
2176
2233
  // ../adaptives/adaptive-overlays/dist/WorkflowWidget.js
2177
- function showWorkflowToast(container, notification) {
2234
+ function showWorkflowToast(notification) {
2178
2235
  const toast = document.createElement("div");
2179
2236
  toast.setAttribute("data-testid", "workflow-toast");
2180
2237
  toast.className = "se-fixed se-bottom-4 se-right-4 se-z-50";
@@ -2208,7 +2265,7 @@ function showWorkflowToast(container, notification) {
2208
2265
  bodyEl.textContent = notification.body;
2209
2266
  toast.appendChild(bodyEl);
2210
2267
  }
2211
- container.appendChild(toast);
2268
+ document.body.appendChild(toast);
2212
2269
  let removeTimer;
2213
2270
  const fadeTimer = setTimeout(() => {
2214
2271
  toast.style.opacity = "0";
@@ -2307,10 +2364,10 @@ function WorkflowWidgetInner({ runtime: runtime3 }) {
2307
2364
  return newEntries.length > 0 ? [...prev, ...newEntries] : prev;
2308
2365
  });
2309
2366
  for (const [tourId, { meta }] of tourWorkflows) {
2310
- if (!notifiedRef.current.has(tourId) && meta.notification && containerRef.current && !dismissed.includes(tourId) && !completed[tourId]) {
2367
+ if (!notifiedRef.current.has(tourId) && meta.notification && !dismissed.includes(tourId) && !completed[tourId]) {
2311
2368
  notifiedRef.current.add(tourId);
2312
2369
  (_c = stateNs == null ? void 0 : stateNs.set) == null ? void 0 : _c.call(stateNs, "notified", [...notifiedRef.current]);
2313
- const cleanup = showWorkflowToast(containerRef.current, meta.notification);
2370
+ const cleanup = showWorkflowToast(meta.notification);
2314
2371
  toastCleanupsRef.current.push(cleanup);
2315
2372
  }
2316
2373
  }
@@ -2343,8 +2400,8 @@ function WorkflowWidgetInner({ runtime: runtime3 }) {
2343
2400
  notifiedRef.current.add(tourId);
2344
2401
  (_c = stateNs == null ? void 0 : stateNs.set) == null ? void 0 : _c.call(stateNs, "notified", [...notifiedRef.current]);
2345
2402
  const workflow = currentWorkflows.get(tourId);
2346
- if ((workflow == null ? void 0 : workflow.meta.notification) && containerRef.current) {
2347
- const cleanup = showWorkflowToast(containerRef.current, workflow.meta.notification);
2403
+ if (workflow == null ? void 0 : workflow.meta.notification) {
2404
+ const cleanup = showWorkflowToast(workflow.meta.notification);
2348
2405
  toastCleanupsRef.current.push(cleanup);
2349
2406
  }
2350
2407
  }
@@ -2488,6 +2545,7 @@ var executeHighlight = async (action, context) => {
2488
2545
  cleanup: () => {
2489
2546
  handle.destroy();
2490
2547
  anchorEl.removeAttribute("data-syntro-highlight");
2548
+ anchorEl.removeAttribute("data-syntro-highlight-dismissed");
2491
2549
  }
2492
2550
  };
2493
2551
  };
@@ -2577,6 +2635,8 @@ var executePulse = async (action, context) => {
2577
2635
  return {
2578
2636
  cleanup: () => {
2579
2637
  clearTimeout(timeoutId);
2638
+ if (!anchorEl.isConnected)
2639
+ return;
2580
2640
  anchorEl.style.animation = originalAnimation;
2581
2641
  anchorEl.removeAttribute("data-syntro-pulse");
2582
2642
  }
@@ -2646,7 +2706,12 @@ var executeBadge = async (action, context) => {
2646
2706
  });
2647
2707
  return {
2648
2708
  cleanup: () => {
2649
- badge2.remove();
2709
+ try {
2710
+ badge2.remove();
2711
+ } catch {
2712
+ }
2713
+ if (!anchorEl.isConnected)
2714
+ return;
2650
2715
  if (originalPosition !== void 0) {
2651
2716
  anchorEl.style.position = originalPosition;
2652
2717
  }
@@ -3370,7 +3435,7 @@ function getAntiFlickerSnippet(config = {}) {
3370
3435
  }
3371
3436
 
3372
3437
  // src/version.ts
3373
- var SDK_VERSION = "2.8.0-canary.9";
3438
+ var SDK_VERSION = "2.8.0";
3374
3439
 
3375
3440
  // src/types.ts
3376
3441
  var SDK_SCHEMA_VERSION = "2.0";
@@ -3653,7 +3718,8 @@ function registerFromTriggerWhen(triggerWhen, accumulator) {
3653
3718
  if (cond.type === "event_count" && cond.key) {
3654
3719
  const counter = cond.counter;
3655
3720
  const predicate = counter ? buildPredicate(counter) : () => true;
3656
- accumulator.register(cond.key, predicate);
3721
+ const needsTimestamps = typeof cond.withinMs === "number";
3722
+ accumulator.register(cond.key, predicate, needsTimestamps);
3657
3723
  }
3658
3724
  }
3659
3725
  }
@@ -3865,8 +3931,65 @@ var CanvasEvents = {
3865
3931
  custom: customCanvasEvent
3866
3932
  };
3867
3933
 
3934
+ // src/components/emojiToIcon.tsx
3935
+ import {
3936
+ AlertTriangle,
3937
+ ArrowRight,
3938
+ Banknote,
3939
+ Bell,
3940
+ BookOpen,
3941
+ CheckCircle,
3942
+ ClipboardList,
3943
+ Compass,
3944
+ FileText,
3945
+ Gamepad2,
3946
+ HelpCircle,
3947
+ Landmark,
3948
+ Layers,
3949
+ Lightbulb,
3950
+ MessageCircle,
3951
+ SkipForward,
3952
+ Sparkles,
3953
+ Timer,
3954
+ Trophy
3955
+ } from "lucide-react";
3956
+ import { jsx as jsx2 } from "react/jsx-runtime";
3957
+ var EMOJI_ICON_MAP = {
3958
+ "\u2753": HelpCircle,
3959
+ "\u{1F9ED}": Compass,
3960
+ "\u{1F4DD}": FileText,
3961
+ "\u{1F3AF}": Layers,
3962
+ "\u{1F3C6}": Trophy,
3963
+ "\u2728": Sparkles,
3964
+ "\u{1F4AC}": MessageCircle,
3965
+ "\u{1F3AE}": Gamepad2,
3966
+ "\u{1F4A1}": Lightbulb,
3967
+ "\u{1F4B0}": Banknote,
3968
+ "\u{1F4CB}": ClipboardList,
3969
+ "\u2705": CheckCircle,
3970
+ "\u26A0\uFE0F": AlertTriangle,
3971
+ "\u{1F4B5}": Banknote,
3972
+ "\u{1F3DB}\uFE0F": Landmark,
3973
+ "\u23ED\uFE0F": SkipForward,
3974
+ "\u27A1\uFE0F": ArrowRight,
3975
+ "\u23F1\uFE0F": Timer,
3976
+ "\u{1F4D6}": BookOpen,
3977
+ "\u{1F514}": Bell
3978
+ };
3979
+ function EmojiIcon({
3980
+ emoji,
3981
+ size = 14,
3982
+ color = "currentColor"
3983
+ }) {
3984
+ const Icon = EMOJI_ICON_MAP[emoji];
3985
+ if (!Icon) {
3986
+ return /* @__PURE__ */ jsx2("span", { children: emoji });
3987
+ }
3988
+ return /* @__PURE__ */ jsx2(Icon, { size, color });
3989
+ }
3990
+
3868
3991
  // src/notifications/NotificationToastStack.tsx
3869
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
3992
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
3870
3993
  var TOAST_STYLES_ID = "syntro-toast-styles";
3871
3994
  var TOAST_CSS = `
3872
3995
  @keyframes syntro-toast-slide-in {
@@ -3903,7 +4026,7 @@ function NotificationToastStack({
3903
4026
  const { shadowRoot } = useShadowRoot();
3904
4027
  ensureToastStyles(shadowRoot);
3905
4028
  if (notifications.length === 0) return null;
3906
- return /* @__PURE__ */ jsx2(
4029
+ return /* @__PURE__ */ jsx3(
3907
4030
  "div",
3908
4031
  {
3909
4032
  "data-testid": "notification-toast-stack",
@@ -3958,7 +4081,7 @@ function NotificationToastStack({
3958
4081
  padding: "10px 12px"
3959
4082
  },
3960
4083
  children: [
3961
- /* @__PURE__ */ jsx2(
4084
+ /* @__PURE__ */ jsx3(
3962
4085
  "div",
3963
4086
  {
3964
4087
  style: {
@@ -3972,11 +4095,11 @@ function NotificationToastStack({
3972
4095
  flexShrink: 0,
3973
4096
  fontSize: "14px"
3974
4097
  },
3975
- children: (_a2 = notif.icon) != null ? _a2 : "\u{1F514}"
4098
+ children: /* @__PURE__ */ jsx3(EmojiIcon, { emoji: (_a2 = notif.icon) != null ? _a2 : "\u{1F514}", size: 14 })
3976
4099
  }
3977
4100
  ),
3978
4101
  /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
3979
- /* @__PURE__ */ jsx2(
4102
+ /* @__PURE__ */ jsx3(
3980
4103
  "div",
3981
4104
  {
3982
4105
  style: {
@@ -3991,7 +4114,7 @@ function NotificationToastStack({
3991
4114
  children: notif.title
3992
4115
  }
3993
4116
  ),
3994
- notif.body && /* @__PURE__ */ jsx2(
4117
+ notif.body && /* @__PURE__ */ jsx3(
3995
4118
  "div",
3996
4119
  {
3997
4120
  style: {
@@ -4007,7 +4130,7 @@ function NotificationToastStack({
4007
4130
  }
4008
4131
  )
4009
4132
  ] }),
4010
- /* @__PURE__ */ jsx2(
4133
+ /* @__PURE__ */ jsx3(
4011
4134
  "button",
4012
4135
  {
4013
4136
  type: "button",
@@ -4032,7 +4155,7 @@ function NotificationToastStack({
4032
4155
  ]
4033
4156
  }
4034
4157
  ),
4035
- /* @__PURE__ */ jsx2("div", { style: { height: "2px", background: "rgba(0, 0, 0, 0.08)" }, children: /* @__PURE__ */ jsx2(
4158
+ /* @__PURE__ */ jsx3("div", { style: { height: "2px", background: "rgba(0, 0, 0, 0.08)" }, children: /* @__PURE__ */ jsx3(
4036
4159
  "div",
4037
4160
  {
4038
4161
  className: "syntro-toast-progress",
@@ -4246,7 +4369,7 @@ function useNotifyWatcher(runtime3, tiles, appRegistry2) {
4246
4369
 
4247
4370
  // src/RuntimeProvider.tsx
4248
4371
  import { createContext as createContext2, useContext as useContext2, useEffect as useEffect4, useMemo as useMemo2, useState as useState3 } from "react";
4249
- import { jsx as jsx3 } from "react/jsx-runtime";
4372
+ import { jsx as jsx4 } from "react/jsx-runtime";
4250
4373
  var RuntimeReactContext = createContext2({
4251
4374
  runtime: null,
4252
4375
  context: null
@@ -4264,7 +4387,7 @@ function RuntimeProvider({ runtime: runtime3, children }) {
4264
4387
  return unsubscribe;
4265
4388
  }, [runtime3]);
4266
4389
  const value = useMemo2(() => ({ runtime: runtime3, context }), [runtime3, context]);
4267
- return /* @__PURE__ */ jsx3(RuntimeReactContext.Provider, { value, children });
4390
+ return /* @__PURE__ */ jsx4(RuntimeReactContext.Provider, { value, children });
4268
4391
  }
4269
4392
  function useRuntime() {
4270
4393
  const { runtime: runtime3 } = useContext2(RuntimeReactContext);
@@ -4338,41 +4461,17 @@ import {
4338
4461
  } from "react";
4339
4462
 
4340
4463
  // src/components/TileIcon.tsx
4341
- import {
4342
- Compass,
4343
- FileText,
4344
- Gamepad2,
4345
- HelpCircle,
4346
- Layers,
4347
- MessageCircle,
4348
- Sparkles,
4349
- Trophy
4350
- } from "lucide-react";
4351
- import { jsx as jsx4 } from "react/jsx-runtime";
4352
- var ICON_MAP = {
4353
- "\u2753": HelpCircle,
4354
- "\u{1F9ED}": Compass,
4355
- "\u{1F4DD}": FileText,
4356
- "\u{1F3AF}": Layers,
4357
- "\u{1F3C6}": Trophy,
4358
- "\u2728": Sparkles,
4359
- "\u{1F4AC}": MessageCircle,
4360
- "\u{1F3AE}": Gamepad2
4361
- };
4464
+ import { jsx as jsx5 } from "react/jsx-runtime";
4362
4465
  function TileIcon({
4363
4466
  emoji,
4364
4467
  size = 18,
4365
4468
  color = "currentColor"
4366
4469
  }) {
4367
- const Icon = ICON_MAP[emoji];
4368
- if (!Icon) {
4369
- return /* @__PURE__ */ jsx4("span", { children: emoji });
4370
- }
4371
- return /* @__PURE__ */ jsx4(Icon, { size, color });
4470
+ return /* @__PURE__ */ jsx5(EmojiIcon, { emoji, size, color });
4372
4471
  }
4373
4472
 
4374
4473
  // src/components/TileCard.tsx
4375
- import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
4474
+ import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
4376
4475
  function WidgetMount({ widgetId, props }) {
4377
4476
  var _a2;
4378
4477
  const runtime3 = useRuntime();
@@ -4402,7 +4501,6 @@ function WidgetMount({ widgetId, props }) {
4402
4501
  return () => {
4403
4502
  handle.unmount();
4404
4503
  handleRef.current = null;
4405
- container.remove();
4406
4504
  };
4407
4505
  }, [registry, widgetId, widgetAvailable]);
4408
4506
  const propsJson = JSON.stringify(props);
@@ -4430,7 +4528,7 @@ function WidgetMount({ widgetId, props }) {
4430
4528
  }
4431
4529
  );
4432
4530
  }
4433
- return /* @__PURE__ */ jsx5("div", { ref: parentRef });
4531
+ return /* @__PURE__ */ jsx6("div", { ref: parentRef });
4434
4532
  }
4435
4533
  function TileCard({
4436
4534
  config,
@@ -4503,9 +4601,9 @@ function TileCard({
4503
4601
  onMouseLeave,
4504
4602
  children: [
4505
4603
  /* @__PURE__ */ jsxs2("div", { style: headerStyle, children: [
4506
- /* @__PURE__ */ jsx5("div", { style: iconStyle, children: /* @__PURE__ */ jsx5(TileIcon, { emoji: resolvedIcon, size: resolvedSubtitle ? 36 : 24 }) }),
4604
+ /* @__PURE__ */ jsx6("div", { style: iconStyle, children: /* @__PURE__ */ jsx6(TileIcon, { emoji: resolvedIcon, size: resolvedSubtitle ? 36 : 24 }) }),
4507
4605
  /* @__PURE__ */ jsxs2("div", { style: { flex: 1, minWidth: 0 }, children: [
4508
- /* @__PURE__ */ jsx5(
4606
+ /* @__PURE__ */ jsx6(
4509
4607
  "h3",
4510
4608
  {
4511
4609
  style: {
@@ -4520,7 +4618,7 @@ function TileCard({
4520
4618
  children: title != null ? title : widget
4521
4619
  }
4522
4620
  ),
4523
- resolvedSubtitle && /* @__PURE__ */ jsx5(
4621
+ resolvedSubtitle && /* @__PURE__ */ jsx6(
4524
4622
  "p",
4525
4623
  {
4526
4624
  style: {
@@ -4537,14 +4635,14 @@ function TileCard({
4537
4635
  )
4538
4636
  ] })
4539
4637
  ] }),
4540
- /* @__PURE__ */ jsx5(
4638
+ /* @__PURE__ */ jsx6(
4541
4639
  "div",
4542
4640
  {
4543
4641
  style: {
4544
4642
  padding: "var(--sc-tile-body-padding, 0 0.75rem 0.5rem)",
4545
4643
  borderTop: "1px solid rgba(255, 255, 255, 0.06)"
4546
4644
  },
4547
- children: /* @__PURE__ */ jsx5("div", { style: { paddingTop: "var(--sc-tile-gap, 0.25rem)" }, children: /* @__PURE__ */ jsx5(WidgetMount, { widgetId: widget, props: { ...props, instanceId: config.id } }) })
4645
+ children: /* @__PURE__ */ jsx6("div", { style: { paddingTop: "var(--sc-tile-gap, 0.25rem)" }, children: /* @__PURE__ */ jsx6(WidgetMount, { widgetId: widget, props: { ...props, instanceId: config.id } }) })
4548
4646
  }
4549
4647
  )
4550
4648
  ]
@@ -4952,7 +5050,7 @@ function flattenThemeConfig(config) {
4952
5050
 
4953
5051
  // src/theme/ThemeProvider.tsx
4954
5052
  import { createContext as createContext3, useContext as useContext3, useEffect as useEffect6, useMemo as useMemo4 } from "react";
4955
- import { jsx as jsx6 } from "react/jsx-runtime";
5053
+ import { jsx as jsx7 } from "react/jsx-runtime";
4956
5054
  var ThemeContext = createContext3(null);
4957
5055
  function ThemeProvider({
4958
5056
  children,
@@ -4983,7 +5081,7 @@ ${cssRules}
4983
5081
  mode: merged.mode,
4984
5082
  cssVariables
4985
5083
  };
4986
- return /* @__PURE__ */ jsx6(ThemeContext.Provider, { value, children });
5084
+ return /* @__PURE__ */ jsx7(ThemeContext.Provider, { value, children });
4987
5085
  }
4988
5086
  function useTheme() {
4989
5087
  const context = useContext3(ThemeContext);
@@ -4994,7 +5092,7 @@ function useTheme() {
4994
5092
  }
4995
5093
 
4996
5094
  // src/components/ShadowCanvasOverlay.tsx
4997
- import { Fragment, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
5095
+ import { Fragment, jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
4998
5096
  var LAUNCHER_STYLES_ID = "syntro-launcher-styles";
4999
5097
  function ensureLauncherStyles(target, css) {
5000
5098
  if (target.querySelector(`#${LAUNCHER_STYLES_ID}`)) return;
@@ -5235,7 +5333,7 @@ function ShadowCanvasOverlay({
5235
5333
  pointerEvents: "none",
5236
5334
  padding: "0"
5237
5335
  };
5238
- const content = /* @__PURE__ */ jsx7(
5336
+ const content = /* @__PURE__ */ jsx8(
5239
5337
  "div",
5240
5338
  {
5241
5339
  "data-shadow-canvas-id": "overlay-root",
@@ -5247,7 +5345,7 @@ function ShadowCanvasOverlay({
5247
5345
  },
5248
5346
  children: /* @__PURE__ */ jsxs3("div", { style: wrapperStyle, children: [
5249
5347
  /* @__PURE__ */ jsxs3("div", { ref: containerRef, "data-shadow-canvas-id": "overlay-container", style: containerStyle, children: [
5250
- isFocused && canvasTitle && /* @__PURE__ */ jsx7("header", { style: { color: "white", padding: "1.5rem 1.5rem 0" }, children: /* @__PURE__ */ jsx7(
5348
+ isFocused && canvasTitle && /* @__PURE__ */ jsx8("header", { style: { color: "white", padding: "1.5rem 1.5rem 0" }, children: /* @__PURE__ */ jsx8(
5251
5349
  "p",
5252
5350
  {
5253
5351
  style: {
@@ -5260,7 +5358,7 @@ function ShadowCanvasOverlay({
5260
5358
  children: canvasTitle
5261
5359
  }
5262
5360
  ) }),
5263
- /* @__PURE__ */ jsx7("div", { style: { flex: 1, overflowY: "auto", padding: isFocused ? "0" : "1rem" }, children: isLoading ? /* @__PURE__ */ jsx7(
5361
+ /* @__PURE__ */ jsx8("div", { style: { flex: 1, overflowY: "auto", padding: isFocused ? "0" : "1rem" }, children: isLoading ? /* @__PURE__ */ jsx8(
5264
5362
  "div",
5265
5363
  {
5266
5364
  style: { color: "var(--sc-overlay-text-color)", padding: isFocused ? "1rem" : "0" },
@@ -5280,7 +5378,7 @@ function ShadowCanvasOverlay({
5280
5378
  }
5281
5379
  ) : isFocused ? (
5282
5380
  /* Focused Mode: Render first tile full size */
5283
- tiles.length > 0 ? /* @__PURE__ */ jsx7(
5381
+ tiles.length > 0 ? /* @__PURE__ */ jsx8(
5284
5382
  TileCard,
5285
5383
  {
5286
5384
  config: tiles[0],
@@ -5291,7 +5389,7 @@ function ShadowCanvasOverlay({
5291
5389
  ) : null
5292
5390
  ) : (
5293
5391
  /* Standard Mode: Stacked cards — widgets always visible */
5294
- /* @__PURE__ */ jsx7(
5392
+ /* @__PURE__ */ jsx8(
5295
5393
  "div",
5296
5394
  {
5297
5395
  style: {
@@ -5300,7 +5398,7 @@ function ShadowCanvasOverlay({
5300
5398
  gap: "0.75rem",
5301
5399
  width: "100%"
5302
5400
  },
5303
- children: tiles.map((tile) => /* @__PURE__ */ jsx7(
5401
+ children: tiles.map((tile) => /* @__PURE__ */ jsx8(
5304
5402
  TileCard,
5305
5403
  {
5306
5404
  config: tile,
@@ -5315,7 +5413,7 @@ function ShadowCanvasOverlay({
5315
5413
  ) }),
5316
5414
  footerSlot
5317
5415
  ] }),
5318
- /* @__PURE__ */ jsx7(
5416
+ /* @__PURE__ */ jsx8(
5319
5417
  "div",
5320
5418
  {
5321
5419
  onClick: toggle2,
@@ -5343,7 +5441,7 @@ function ShadowCanvasOverlay({
5343
5441
  zIndex: zIndex + 47
5344
5442
  },
5345
5443
  children: [
5346
- /* @__PURE__ */ jsx7(
5444
+ /* @__PURE__ */ jsx8(
5347
5445
  NotificationToastStack,
5348
5446
  {
5349
5447
  notifications,
@@ -5413,11 +5511,11 @@ function ShadowCanvasOverlay({
5413
5511
  focusable: "false",
5414
5512
  style: { transition: "transform 200ms ease" },
5415
5513
  children: [
5416
- /* @__PURE__ */ jsx7("path", { d: "M18 6L6 18" }),
5417
- /* @__PURE__ */ jsx7("path", { d: "M6 6l12 12" })
5514
+ /* @__PURE__ */ jsx8("path", { d: "M18 6L6 18" }),
5515
+ /* @__PURE__ */ jsx8("path", { d: "M6 6l12 12" })
5418
5516
  ]
5419
5517
  }
5420
- ) : launcherIcon ? /* @__PURE__ */ jsx7(
5518
+ ) : launcherIcon ? /* @__PURE__ */ jsx8(
5421
5519
  "img",
5422
5520
  {
5423
5521
  src: launcherIcon,
@@ -5445,16 +5543,16 @@ function ShadowCanvasOverlay({
5445
5543
  focusable: "false",
5446
5544
  style: { transition: "transform 200ms ease" },
5447
5545
  children: [
5448
- /* @__PURE__ */ jsx7("path", { d: "M12 3l1.912 5.813a2 2 0 0 0 1.275 1.275L21 12l-5.813 1.912a2 2 0 0 0-1.275 1.275L12 21l-1.912-5.813a2 2 0 0 0-1.275-1.275L3 12l5.813-1.912a2 2 0 0 0 1.275-1.275L12 3Z" }),
5449
- /* @__PURE__ */ jsx7("path", { d: "M5 3v4" }),
5450
- /* @__PURE__ */ jsx7("path", { d: "M3 5h4" }),
5451
- /* @__PURE__ */ jsx7("path", { d: "M19 17v4" }),
5452
- /* @__PURE__ */ jsx7("path", { d: "M17 19h4" })
5546
+ /* @__PURE__ */ jsx8("path", { d: "M12 3l1.912 5.813a2 2 0 0 0 1.275 1.275L21 12l-5.813 1.912a2 2 0 0 0-1.275 1.275L12 21l-1.912-5.813a2 2 0 0 0-1.275-1.275L3 12l5.813-1.912a2 2 0 0 0 1.275-1.275L12 3Z" }),
5547
+ /* @__PURE__ */ jsx8("path", { d: "M5 3v4" }),
5548
+ /* @__PURE__ */ jsx8("path", { d: "M3 5h4" }),
5549
+ /* @__PURE__ */ jsx8("path", { d: "M19 17v4" }),
5550
+ /* @__PURE__ */ jsx8("path", { d: "M17 19h4" })
5453
5551
  ]
5454
5552
  }
5455
5553
  ),
5456
5554
  !isOpen && notifications.length > 0 && /* @__PURE__ */ jsxs3("div", { style: { position: "absolute", top: -2, right: -2, pointerEvents: "none" }, children: [
5457
- /* @__PURE__ */ jsx7(
5555
+ /* @__PURE__ */ jsx8(
5458
5556
  "span",
5459
5557
  {
5460
5558
  className: "syntro-badge-ping",
@@ -5466,7 +5564,7 @@ function ShadowCanvasOverlay({
5466
5564
  }
5467
5565
  }
5468
5566
  ),
5469
- /* @__PURE__ */ jsx7(
5567
+ /* @__PURE__ */ jsx8(
5470
5568
  "span",
5471
5569
  {
5472
5570
  className: "syntro-badge-glow",
@@ -5477,7 +5575,7 @@ function ShadowCanvasOverlay({
5477
5575
  }
5478
5576
  }
5479
5577
  ),
5480
- /* @__PURE__ */ jsx7(
5578
+ /* @__PURE__ */ jsx8(
5481
5579
  "span",
5482
5580
  {
5483
5581
  className: "syntro-badge-bounce",
@@ -5612,7 +5710,7 @@ function useShadowCanvasConfig({
5612
5710
 
5613
5711
  // src/SmartCanvasApp.tsx
5614
5712
  import { useEffect as useEffect9, useMemo as useMemo7, useRef as useRef7, useState as useState7 } from "react";
5615
- import { jsx as jsx8 } from "react/jsx-runtime";
5713
+ import { jsx as jsx9 } from "react/jsx-runtime";
5616
5714
  function SmartCanvasApp({
5617
5715
  controller,
5618
5716
  fetcher,
@@ -5635,7 +5733,7 @@ function SmartCanvasApp({
5635
5733
  workspaceTheme
5636
5734
  }) {
5637
5735
  if (runtime3) {
5638
- return /* @__PURE__ */ jsx8(RuntimeProvider, { runtime: runtime3, children: /* @__PURE__ */ jsx8(
5736
+ return /* @__PURE__ */ jsx9(RuntimeProvider, { runtime: runtime3, children: /* @__PURE__ */ jsx9(
5639
5737
  SmartCanvasAppInner,
5640
5738
  {
5641
5739
  controller,
@@ -5660,7 +5758,7 @@ function SmartCanvasApp({
5660
5758
  }
5661
5759
  ) });
5662
5760
  }
5663
- return /* @__PURE__ */ jsx8(
5761
+ return /* @__PURE__ */ jsx9(
5664
5762
  SmartCanvasAppInner,
5665
5763
  {
5666
5764
  controller,
@@ -5815,13 +5913,13 @@ function SmartCanvasAppInner({
5815
5913
  }, [runtime3, controller]);
5816
5914
  const { shadowRoot } = useShadowRoot();
5817
5915
  const themeConfig = configState.theme;
5818
- return /* @__PURE__ */ jsx8(
5916
+ return /* @__PURE__ */ jsx9(
5819
5917
  ThemeProvider,
5820
5918
  {
5821
5919
  themeConfig,
5822
5920
  workspaceTheme,
5823
5921
  shadowRoot,
5824
- children: !configState.isLoading && !hasContent ? null : /* @__PURE__ */ jsx8(
5922
+ children: !configState.isLoading && !hasContent ? null : /* @__PURE__ */ jsx9(
5825
5923
  ShadowCanvasOverlay,
5826
5924
  {
5827
5925
  tiles: configState.tiles,
@@ -5846,7 +5944,7 @@ function SmartCanvasAppInner({
5846
5944
 
5847
5945
  // src/SmartCanvasElement.tsx
5848
5946
  import { createRoot as createRoot2 } from "react-dom/client";
5849
- import { jsx as jsx9 } from "react/jsx-runtime";
5947
+ import { jsx as jsx10 } from "react/jsx-runtime";
5850
5948
  var TAG_NAME = "smart-canvas";
5851
5949
  var BASE_CSS = `
5852
5950
  :host {
@@ -5947,13 +6045,13 @@ var SmartCanvasElement = class extends HTMLElement {
5947
6045
  __privateSet(this, _root, createRoot2(__privateGet(this, _mount)));
5948
6046
  }
5949
6047
  __privateGet(this, _root).render(
5950
- /* @__PURE__ */ jsx9(
6048
+ /* @__PURE__ */ jsx10(
5951
6049
  ShadowRootProvider,
5952
6050
  {
5953
6051
  shadowRoot: __privateGet(this, _shadow),
5954
6052
  portalRoot: __privateGet(this, _portalRoot),
5955
6053
  overlayContainer: __privateGet(this, _overlayContainer),
5956
- children: /* @__PURE__ */ jsx9(SmartCanvasApp, { ...__privateGet(this, _lastAppProps), controller: __privateGet(this, _controller), canvasHost: this })
6054
+ children: /* @__PURE__ */ jsx10(SmartCanvasApp, { ...__privateGet(this, _lastAppProps), controller: __privateGet(this, _controller), canvasHost: this })
5957
6055
  }
5958
6056
  )
5959
6057
  );
@@ -8250,13 +8348,9 @@ function createActionEngine(options) {
8250
8348
  entry2.state = "reverted";
8251
8349
  publishEvent("action.reverted", { id, kind: action.kind });
8252
8350
  } catch (error2) {
8253
- entry2.state = "failed";
8254
- publishEvent("action.failed", {
8255
- id,
8256
- kind: action.kind,
8257
- error: String(error2)
8258
- });
8259
- throw error2;
8351
+ console.warn(`[ActionEngine] Cleanup error for ${action.kind} (${id}), ignoring:`, error2);
8352
+ entry2.state = "reverted";
8353
+ publishEvent("action.reverted", { id, kind: action.kind });
8260
8354
  } finally {
8261
8355
  activeActions.delete(id);
8262
8356
  }
@@ -8400,6 +8494,7 @@ function createAnchorResolver(opts) {
8400
8494
  function resolve(selector) {
8401
8495
  if (!root) return null;
8402
8496
  try {
8497
+ if (root.matches(selector)) return root;
8403
8498
  return root.querySelector(selector);
8404
8499
  } catch {
8405
8500
  return null;
@@ -9254,16 +9349,24 @@ function getEventName(phEvent) {
9254
9349
  }
9255
9350
  return eventName.replace("$", "posthog.");
9256
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
+ }
9257
9362
  function extractProps(phEvent) {
9258
- var _a2;
9363
+ var _a2, _b;
9259
9364
  const props = {};
9260
9365
  const phProps = phEvent.properties || {};
9261
9366
  const elements = phProps.$elements;
9262
- if (phProps.$tag_name) {
9263
- props.tagName = phProps.$tag_name;
9264
- } else if ((_a2 = elements == null ? void 0 : elements[0]) == null ? void 0 : _a2.tag_name) {
9265
- props.tagName = elements[0].tag_name;
9266
- }
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;
9267
9370
  if (phProps.$el_text) props.elementText = phProps.$el_text;
9268
9371
  if (elements) props.elements = elements;
9269
9372
  if (phProps.$current_url) props.url = phProps.$current_url;
@@ -10132,9 +10235,18 @@ function createSurfaces(options) {
10132
10235
  }
10133
10236
  async function unmountEntry(entry) {
10134
10237
  var _a2;
10135
- await playExitAnimation(entry.container, entry.options.animation);
10136
- (_a2 = entry.cleanup) == null ? void 0 : _a2.call(entry);
10137
- entry.container.remove();
10238
+ if (entry.container.isConnected) {
10239
+ await playExitAnimation(entry.container, entry.options.animation);
10240
+ }
10241
+ try {
10242
+ (_a2 = entry.cleanup) == null ? void 0 : _a2.call(entry);
10243
+ } catch (error2) {
10244
+ console.warn("[Surfaces] Cleanup error during unmount, ignoring:", error2);
10245
+ }
10246
+ try {
10247
+ entry.container.remove();
10248
+ } catch {
10249
+ }
10138
10250
  mounts.delete(entry.slot);
10139
10251
  publishEvent("surface.unmounted", {
10140
10252
  slot: entry.slot,
@@ -10317,7 +10429,9 @@ var WidgetRegistry = class {
10317
10429
  var _a2;
10318
10430
  const mounted = this.mountedWidgets.get(mountId);
10319
10431
  if (mounted) {
10320
- (_a2 = mounted.cleanup) == null ? void 0 : _a2.call(mounted);
10432
+ if (container.isConnected) {
10433
+ (_a2 = mounted.cleanup) == null ? void 0 : _a2.call(mounted);
10434
+ }
10321
10435
  this.mountedWidgets.delete(mountId);
10322
10436
  container.removeAttribute("data-widget-mount-id");
10323
10437
  container.removeAttribute("data-widget-id");
@@ -11338,4 +11452,4 @@ export {
11338
11452
  encodeToken,
11339
11453
  Syntro
11340
11454
  };
11341
- //# sourceMappingURL=chunk-UURRUKSW.js.map
11455
+ //# sourceMappingURL=chunk-4J6BCKWS.js.map