@syntrologie/runtime-sdk 2.13.0 → 2.15.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.
Files changed (67) hide show
  1. package/README.md +1 -0
  2. package/dist/SmartCanvasElementLit.d.ts +166 -0
  3. package/dist/actions/schema.d.ts +776 -776
  4. package/dist/actions/schema.js +4 -3
  5. package/dist/actions/types.d.ts +8 -2
  6. package/dist/anchor/AnchorResolver.d.ts +1 -0
  7. package/dist/api-lit.d.ts +84 -0
  8. package/dist/apps/builtinRuntimeModules-lit.d.ts +20 -0
  9. package/dist/bootstrap-types.d.ts +10 -0
  10. package/dist/chunk-2IQ2PTLJ.js +871 -0
  11. package/dist/chunk-2IQ2PTLJ.js.map +7 -0
  12. package/dist/chunk-4HXPGXUC.js +226 -0
  13. package/dist/chunk-4HXPGXUC.js.map +7 -0
  14. package/dist/{chunk-GF364MMB.js → chunk-CVMZW3II.js} +1102 -1098
  15. package/dist/chunk-CVMZW3II.js.map +7 -0
  16. package/dist/{chunk-XDYJ64IN.js → chunk-GX7BBYX6.js} +4 -4
  17. package/dist/chunk-GX7BBYX6.js.map +7 -0
  18. package/dist/chunk-JMHRHAEL.js +18 -0
  19. package/dist/chunk-JMHRHAEL.js.map +7 -0
  20. package/dist/{chunk-L6RJMBR2.js → chunk-XVRDKBYF.js} +3 -3
  21. package/dist/components/ShadowCanvasOverlay.d.ts +1 -2
  22. package/dist/components/SyntroCanvasOverlay.d.ts +100 -0
  23. package/dist/components/SyntroDrawer.d.ts +110 -0
  24. package/dist/components/SyntroLauncher.d.ts +105 -0
  25. package/dist/components/SyntroTileCard.d.ts +74 -0
  26. package/dist/components/SyntroTileWheel.d.ts +51 -0
  27. package/dist/config/schema.d.ts +147 -136
  28. package/dist/config/schema.js +3 -2
  29. package/dist/controllers/DecisionController.d.ts +48 -0
  30. package/dist/controllers/NotificationsController.d.ts +59 -0
  31. package/dist/controllers/RuntimeController.d.ts +52 -0
  32. package/dist/controllers/RuntimeEventsController.d.ts +42 -0
  33. package/dist/controllers/ThemeController.d.ts +110 -0
  34. package/dist/controllers/index.d.ts +13 -0
  35. package/dist/decisions/schema.d.ts +47 -47
  36. package/dist/decisions/schema.js +2 -1
  37. package/dist/decisions/types.d.ts +4 -0
  38. package/dist/editorLoader.d.ts +5 -0
  39. package/dist/fetchers/experimentsFetcher.d.ts +3 -3
  40. package/dist/fetchers/mergeConfigs.d.ts +7 -7
  41. package/dist/index-lit.d.ts +40 -0
  42. package/dist/index.js +1264 -19
  43. package/dist/index.js.map +4 -4
  44. package/dist/interop/LitInReact.d.ts +27 -0
  45. package/dist/interop/ReactInLit.d.ts +42 -0
  46. package/dist/interop/index.d.ts +7 -0
  47. package/dist/metrics/sessionMetrics.d.ts +4 -0
  48. package/dist/notifications/SyntroToastStack.d.ts +43 -0
  49. package/dist/react-compat.d.ts +114 -0
  50. package/dist/react.js +6 -4
  51. package/dist/react.js.map +1 -1
  52. package/dist/smart-canvas.esm.js +856 -240
  53. package/dist/smart-canvas.esm.js.map +4 -4
  54. package/dist/smart-canvas.js +31387 -39860
  55. package/dist/smart-canvas.js.map +4 -4
  56. package/dist/smart-canvas.min.js +855 -240
  57. package/dist/smart-canvas.min.js.map +4 -4
  58. package/dist/theme/index.js +30 -0
  59. package/dist/theme/index.js.map +7 -0
  60. package/dist/version.d.ts +1 -1
  61. package/package.json +10 -1
  62. package/schema/canvas-config.schema.json +2347 -11396
  63. package/dist/chunk-BU4Z6PD7.js +0 -218
  64. package/dist/chunk-BU4Z6PD7.js.map +0 -7
  65. package/dist/chunk-GF364MMB.js.map +0 -7
  66. package/dist/chunk-XDYJ64IN.js.map +0 -7
  67. /package/dist/{chunk-L6RJMBR2.js.map → chunk-XVRDKBYF.js.map} +0 -0
@@ -1,9 +1,14 @@
1
+ import {
2
+ ThemeProvider,
3
+ blue,
4
+ useTheme
5
+ } from "./chunk-2IQ2PTLJ.js";
1
6
  import {
2
7
  __privateAdd,
3
8
  __privateGet,
4
9
  __privateSet,
5
10
  __publicField
6
- } from "./chunk-BU4Z6PD7.js";
11
+ } from "./chunk-JMHRHAEL.js";
7
12
 
8
13
  // ../adaptives/adaptive-content/dist/reconciliation-guard.js
9
14
  function guardAgainstReconciliation(container, anchor, reinsertFn, opts) {
@@ -91,13 +96,13 @@ var ALLOWED_TAGS = /* @__PURE__ */ new Set([
91
96
  "rect",
92
97
  "g"
93
98
  ]);
94
- function sanitizeHtml(html) {
99
+ function sanitizeHtml(html2) {
95
100
  var _a2;
96
101
  const hasNative = typeof window.Sanitizer === "function";
97
102
  if (hasNative) {
98
103
  try {
99
104
  const s = new window.Sanitizer({});
100
- const frag = s.sanitizeToFragment(html);
105
+ const frag = s.sanitizeToFragment(html2);
101
106
  const div = document.createElement("div");
102
107
  div.append(frag);
103
108
  return div.innerHTML;
@@ -105,14 +110,14 @@ function sanitizeHtml(html) {
105
110
  }
106
111
  }
107
112
  const tpl = document.createElement("template");
108
- tpl.innerHTML = html;
113
+ tpl.innerHTML = html2;
109
114
  const root = tpl.content;
110
115
  const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, null);
111
116
  const toRemove = [];
112
117
  while (walker.nextNode()) {
113
118
  const el = walker.currentNode;
114
- const tag2 = el.tagName.toLowerCase();
115
- if (!ALLOWED_TAGS.has(tag2)) {
119
+ const tag = el.tagName.toLowerCase();
120
+ if (!ALLOWED_TAGS.has(tag)) {
116
121
  toRemove.push(el);
117
122
  continue;
118
123
  }
@@ -256,6 +261,22 @@ var executeInsertHtml = async (action, context) => {
256
261
  }
257
262
  };
258
263
  };
264
+ function findTextTarget(el) {
265
+ var _a2, _b;
266
+ if (el.children.length === 0)
267
+ return el;
268
+ const textChildren = Array.from(el.children).filter((child) => {
269
+ var _a3;
270
+ return (_a3 = child.textContent) == null ? void 0 : _a3.trim();
271
+ });
272
+ if (textChildren.length === 1) {
273
+ const child = textChildren[0];
274
+ if (((_a2 = child.textContent) == null ? void 0 : _a2.trim()) === ((_b = el.textContent) == null ? void 0 : _b.trim())) {
275
+ return findTextTarget(child);
276
+ }
277
+ }
278
+ return el;
279
+ }
259
280
  var executeSetText = async (action, context) => {
260
281
  var _a2;
261
282
  let anchorEl = context.resolveAnchor(action.anchorId);
@@ -267,8 +288,9 @@ var executeSetText = async (action, context) => {
267
288
  return { cleanup: () => {
268
289
  } };
269
290
  }
270
- const originalText = (_a2 = anchorEl.textContent) != null ? _a2 : "";
271
- anchorEl.textContent = action.text;
291
+ const textTarget = findTextTarget(anchorEl);
292
+ const originalText = (_a2 = textTarget.textContent) != null ? _a2 : "";
293
+ textTarget.textContent = action.text;
272
294
  context.publishEvent("action.applied", {
273
295
  id: context.generateId(),
274
296
  kind: "content:setText",
@@ -278,11 +300,11 @@ var executeSetText = async (action, context) => {
278
300
  cleanup: () => {
279
301
  if (!anchorEl.isConnected)
280
302
  return;
281
- anchorEl.textContent = originalText;
303
+ textTarget.textContent = originalText;
282
304
  },
283
305
  updateFn: (changes) => {
284
306
  if ("text" in changes && typeof changes.text === "string") {
285
- anchorEl.textContent = changes.text;
307
+ textTarget.textContent = changes.text;
286
308
  }
287
309
  }
288
310
  };
@@ -1150,392 +1172,6 @@ var executeTour = async (action, context) => {
1150
1172
  return { cleanup };
1151
1173
  };
1152
1174
 
1153
- // ../design-system/src/tokens/colors.ts
1154
- var base = {
1155
- white: "#ffffff",
1156
- black: "#000000"
1157
- };
1158
- var brand = {
1159
- 0: "#2c0b0a",
1160
- 1: "#5b1715",
1161
- 2: "#89221f",
1162
- 3: "#b72e2a",
1163
- 4: "#d44844",
1164
- 5: "#dd6d69",
1165
- 6: "#e5918f",
1166
- 7: "#eeb6b4",
1167
- 8: "#f6dada",
1168
- 9: "#faebea"
1169
- };
1170
- var slateGrey = {
1171
- 0: "#07080a",
1172
- 1: "#0f1318",
1173
- 2: "#0e1114",
1174
- 3: "#1c222a",
1175
- 4: "#2b333f",
1176
- 5: "#394454",
1177
- 6: "#475569",
1178
- 7: "#677384",
1179
- 8: "#87919f",
1180
- 9: "#a8afba",
1181
- 10: "#cbd0d7",
1182
- 11: "#e8eaee",
1183
- 12: "#f6f7f9"
1184
- };
1185
- var green = {
1186
- 0: "#07230a",
1187
- 1: "#0e4514",
1188
- 2: "#16681e",
1189
- 3: "#1d8a28",
1190
- 4: "#24ad32",
1191
- 5: "#4fbd5a",
1192
- 6: "#7acd82",
1193
- 7: "#a5deab",
1194
- 8: "#d0eed3",
1195
- 9: "#e5f6e7"
1196
- };
1197
- var yellow = {
1198
- 0: "#301f09",
1199
- 1: "#5f3e12",
1200
- 2: "#8f5e1b",
1201
- 3: "#be7d24",
1202
- 4: "#ee9c2d",
1203
- 5: "#f1b057",
1204
- 6: "#f5c481",
1205
- 7: "#f8d7ab",
1206
- 8: "#fcebd5",
1207
- 9: "#fdf5ea"
1208
- };
1209
- var red = {
1210
- 0: "#330707",
1211
- 1: "#660f0e",
1212
- 2: "#991616",
1213
- 3: "#cc1e1d",
1214
- 4: "#ff2524",
1215
- 5: "#ff5150",
1216
- 6: "#ff7c7c",
1217
- 7: "#ffa8a7",
1218
- 8: "#ffd3d3",
1219
- 9: "#ffe9e9"
1220
- };
1221
- var blue = {
1222
- 0: "#051533",
1223
- 1: "#0a2a66",
1224
- 2: "#0f3f98",
1225
- 3: "#1454cb",
1226
- 4: "#1969fe",
1227
- 5: "#4787fe",
1228
- 6: "#75a5fe",
1229
- 7: "#a3c3ff",
1230
- 8: "#d1e1ff",
1231
- 9: "#e8f0ff"
1232
- };
1233
- var orange = {
1234
- 0: "#662500",
1235
- 1: "#993d00",
1236
- 2: "#cc5800",
1237
- 3: "#ff7700",
1238
- 4: "#fea85d",
1239
- 5: "#fec58f",
1240
- 6: "#ffd6ae",
1241
- 7: "#fee6cd",
1242
- 8: "#fff1e1",
1243
- 9: "#fff8f0"
1244
- };
1245
- var purple = {
1246
- 0: "#151229",
1247
- 1: "#2a2452",
1248
- 2: "#40357c",
1249
- 3: "#5547a5",
1250
- 4: "#6a59ce",
1251
- 5: "#887ad8",
1252
- 6: "#a69be2",
1253
- 7: "#c3bdeb",
1254
- 8: "#e1def5",
1255
- 9: "#f0eefa"
1256
- };
1257
- var pink = {
1258
- 0: "#37091f",
1259
- 1: "#69123c",
1260
- 2: "#9b1c58",
1261
- 3: "#cd2575",
1262
- 4: "#ff2e92",
1263
- 5: "#ff58a8",
1264
- 6: "#ff82be",
1265
- 7: "#ffabd3",
1266
- 8: "#ffd5e9",
1267
- 9: "#ffeaf4"
1268
- };
1269
- var text = {
1270
- primary: slateGrey[10],
1271
- secondary: slateGrey[9],
1272
- tertiary: slateGrey[8]
1273
- };
1274
- var background = {
1275
- primary: slateGrey[2],
1276
- secondary: slateGrey[0]
1277
- };
1278
- var border = {
1279
- primary: slateGrey[4],
1280
- secondary: slateGrey[3]
1281
- };
1282
- var button = {
1283
- primary: {
1284
- text: base.white,
1285
- icon: base.white,
1286
- border: brand[3],
1287
- backgroundDefault: brand[3],
1288
- backgroundHover: brand[2]
1289
- },
1290
- neutral: {
1291
- text: slateGrey[10],
1292
- textHover: base.white,
1293
- icon: slateGrey[10],
1294
- iconHover: base.white,
1295
- border: slateGrey[4],
1296
- background: slateGrey[2]
1297
- },
1298
- link: {
1299
- text: base.white,
1300
- icon: base.white,
1301
- hover: brand[5]
1302
- },
1303
- error: {
1304
- text: red[5],
1305
- hover: red[6]
1306
- },
1307
- success: {
1308
- text: green[5],
1309
- hover: green[6]
1310
- }
1311
- };
1312
- var badge = {
1313
- slateGrey: {
1314
- content: slateGrey[10],
1315
- pillOutline: slateGrey[10],
1316
- borderPrimary: slateGrey[5],
1317
- borderSecondary: slateGrey[5],
1318
- background: slateGrey[3]
1319
- },
1320
- brand: {
1321
- content: brand[9],
1322
- pillOutline: brand[9],
1323
- borderPrimary: brand[6],
1324
- borderSecondary: brand[6],
1325
- background: brand[0]
1326
- },
1327
- red: {
1328
- content: red[8],
1329
- pillOutline: red[4],
1330
- borderPrimary: red[2],
1331
- borderSecondary: red[2],
1332
- background: red[0]
1333
- },
1334
- yellow: {
1335
- content: yellow[8],
1336
- pillOutline: yellow[4],
1337
- borderPrimary: yellow[2],
1338
- borderSecondary: yellow[2],
1339
- background: yellow[0]
1340
- },
1341
- green: {
1342
- content: green[8],
1343
- pillOutline: green[4],
1344
- borderPrimary: green[2],
1345
- borderSecondary: green[2],
1346
- background: green[0]
1347
- },
1348
- purple: {
1349
- content: purple[8],
1350
- pillOutline: purple[4],
1351
- borderPrimary: purple[2],
1352
- borderSecondary: purple[2],
1353
- background: purple[0]
1354
- },
1355
- blue: {
1356
- content: blue[8],
1357
- pillOutline: blue[4],
1358
- borderPrimary: blue[2],
1359
- borderSecondary: blue[2],
1360
- background: blue[0]
1361
- },
1362
- orange: {
1363
- content: orange[8],
1364
- pillOutline: orange[4],
1365
- borderPrimary: orange[2],
1366
- borderSecondary: orange[2],
1367
- background: orange[0]
1368
- },
1369
- pink: {
1370
- content: pink[8],
1371
- pillOutline: pink[4],
1372
- borderPrimary: pink[2],
1373
- borderSecondary: pink[2],
1374
- background: pink[0]
1375
- }
1376
- };
1377
- var badgeBanner = {
1378
- green: {
1379
- content: green[8],
1380
- border: green[2],
1381
- background: green[0]
1382
- },
1383
- yellow: {
1384
- content: yellow[8],
1385
- border: yellow[2],
1386
- background: yellow[0]
1387
- },
1388
- red: {
1389
- content: red[8],
1390
- border: red[2],
1391
- background: red[0]
1392
- }
1393
- };
1394
- var alert = {
1395
- green: {
1396
- content: green[1],
1397
- background: green[9]
1398
- },
1399
- yellow: {
1400
- content: yellow[1],
1401
- background: yellow[9]
1402
- },
1403
- red: {
1404
- content: red[1],
1405
- background: red[9]
1406
- }
1407
- };
1408
- var tag = {
1409
- content: slateGrey[10],
1410
- border: slateGrey[4],
1411
- background: slateGrey[3]
1412
- };
1413
- var menu = {
1414
- backgroundDefault: slateGrey[2],
1415
- backgroundHover: slateGrey[1],
1416
- selected: slateGrey[3]
1417
- };
1418
- var inputDropdown = {
1419
- background: slateGrey[2],
1420
- icon: slateGrey[10],
1421
- borderDefault: slateGrey[4],
1422
- borderSelected: brand[3],
1423
- textLabel: slateGrey[9],
1424
- textPlaceholder: slateGrey[8],
1425
- textHint: slateGrey[8]
1426
- };
1427
- var inputField = {
1428
- backgroundDefault: slateGrey[2],
1429
- backgroundDisabled: slateGrey[0],
1430
- textLabel: slateGrey[9],
1431
- textPlaceholder: slateGrey[8],
1432
- textHint: slateGrey[8],
1433
- textError: red[5],
1434
- iconDefault: slateGrey[9],
1435
- iconPlaceholder: slateGrey[10],
1436
- iconError: red[5],
1437
- borderDefault: slateGrey[4],
1438
- borderSelected: brand[3],
1439
- borderError: red[5]
1440
- };
1441
- var toggle = {
1442
- handleDefault: base.white,
1443
- handleDisabled: slateGrey[10],
1444
- off: {
1445
- backgroundDefault: slateGrey[4],
1446
- backgroundHover: slateGrey[5],
1447
- backgroundDisabled: slateGrey[4]
1448
- },
1449
- on: {
1450
- backgroundDefault: green[3],
1451
- backgroundHover: green[2],
1452
- backgroundDisabled: slateGrey[4]
1453
- }
1454
- };
1455
- var checkbox = {
1456
- off: {
1457
- backgroundDefault: "#00000000",
1458
- backgroundHover: slateGrey[5],
1459
- backgroundDisabled: slateGrey[2],
1460
- border: slateGrey[6]
1461
- },
1462
- on: {
1463
- backgroundDefault: green[0],
1464
- backgroundHover: green[1],
1465
- backgroundDisabled: slateGrey[2],
1466
- border: green[3]
1467
- }
1468
- };
1469
- var avatar = {
1470
- content: slateGrey[10],
1471
- background: slateGrey[4]
1472
- };
1473
- var progressBarSlider = {
1474
- background: slateGrey[4],
1475
- active: green[3]
1476
- };
1477
- var card = {
1478
- background: slateGrey[1],
1479
- content: slateGrey[9],
1480
- border: slateGrey[4]
1481
- };
1482
- var sidebar = {
1483
- backgroundDefault: slateGrey[1],
1484
- backgroundHover: slateGrey[3],
1485
- backgroundActive: slateGrey[4],
1486
- border: slateGrey[4],
1487
- contentPrimary: slateGrey[10],
1488
- contentSecondary: slateGrey[9],
1489
- contentTertiary: slateGrey[8]
1490
- };
1491
- var modal = {
1492
- background: slateGrey[1],
1493
- content: slateGrey[9],
1494
- border: slateGrey[4]
1495
- };
1496
- var tab = {
1497
- activeBackground: slateGrey[3],
1498
- activeContent: brand[5],
1499
- inactiveContent: slateGrey[9],
1500
- border: slateGrey[4]
1501
- };
1502
- var table = {
1503
- header: {
1504
- textDefault: slateGrey[9],
1505
- textHover: slateGrey[8],
1506
- backgroundDefault: slateGrey[1]
1507
- },
1508
- border: slateGrey[4],
1509
- cell: {
1510
- textPrimary: slateGrey[10],
1511
- textSecondary: slateGrey[9],
1512
- backgroundDefault: slateGrey[2],
1513
- backgroundHover: slateGrey[1]
1514
- }
1515
- };
1516
- var breadcrumbs = {
1517
- textPrimaryDefault: slateGrey[10],
1518
- textPrimaryHover: slateGrey[10],
1519
- textSecondaryDefault: slateGrey[8],
1520
- textSecondaryHover: slateGrey[9],
1521
- iconPrimary: slateGrey[10],
1522
- iconSecondary: slateGrey[8]
1523
- };
1524
- var loadingIndicator = {
1525
- background: green[1],
1526
- active: green[5]
1527
- };
1528
- var datePicker = {
1529
- textDefault: slateGrey[10],
1530
- textSelected: base.white,
1531
- textDisabled: slateGrey[7],
1532
- backgroundDefault: slateGrey[2],
1533
- backgroundMiddle: slateGrey[3],
1534
- backgroundSelected: brand[3],
1535
- border: slateGrey[4]
1536
- };
1537
- var scroll = slateGrey[9];
1538
-
1539
1175
  // ../adaptives/adaptive-overlays/dist/highlight.js
1540
1176
  var _a;
1541
1177
  var supportsPathClip = typeof CSS !== "undefined" && ((_a = CSS.supports) == null ? void 0 : _a.call(CSS, "clip-path", "path('M0 0 H1 V1 Z')"));
@@ -1727,13 +1363,13 @@ var ALLOWED_TAGS2 = /* @__PURE__ */ new Set([
1727
1363
  "rect",
1728
1364
  "g"
1729
1365
  ]);
1730
- function sanitizeHtml2(html) {
1366
+ function sanitizeHtml2(html2) {
1731
1367
  var _a2;
1732
1368
  const hasNative = typeof window.Sanitizer === "function";
1733
1369
  if (hasNative) {
1734
1370
  try {
1735
1371
  const s = new window.Sanitizer({});
1736
- const frag = s.sanitizeToFragment(html);
1372
+ const frag = s.sanitizeToFragment(html2);
1737
1373
  const div = document.createElement("div");
1738
1374
  div.append(frag);
1739
1375
  return div.innerHTML;
@@ -1741,14 +1377,14 @@ function sanitizeHtml2(html) {
1741
1377
  }
1742
1378
  }
1743
1379
  const tpl = document.createElement("template");
1744
- tpl.innerHTML = html;
1380
+ tpl.innerHTML = html2;
1745
1381
  const root = tpl.content;
1746
1382
  const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, null);
1747
1383
  const toRemove = [];
1748
1384
  while (walker.nextNode()) {
1749
1385
  const el = walker.currentNode;
1750
- const tag2 = el.tagName.toLowerCase();
1751
- if (!ALLOWED_TAGS2.has(tag2)) {
1386
+ const tag = el.tagName.toLowerCase();
1387
+ if (!ALLOWED_TAGS2.has(tag)) {
1752
1388
  toRemove.push(el);
1753
1389
  continue;
1754
1390
  }
@@ -1793,12 +1429,12 @@ var executeModal = async (action, context) => {
1793
1429
  transition: opacity 200ms ease-out;
1794
1430
  `;
1795
1431
  context.overlayRoot.appendChild(scrimEl);
1796
- const modal2 = document.createElement("div");
1797
- modal2.className = `syntro-modal syntro-modal-${size}`;
1798
- modal2.setAttribute("role", "dialog");
1799
- modal2.setAttribute("aria-modal", "true");
1432
+ const modal = document.createElement("div");
1433
+ modal.className = `syntro-modal syntro-modal-${size}`;
1434
+ modal.setAttribute("role", "dialog");
1435
+ modal.setAttribute("aria-modal", "true");
1800
1436
  const sizeMap = { sm: "360px", md: "480px", lg: "640px" };
1801
- modal2.style.cssText = `
1437
+ modal.style.cssText = `
1802
1438
  position: fixed;
1803
1439
  top: 50%;
1804
1440
  left: 50%;
@@ -1813,13 +1449,13 @@ var executeModal = async (action, context) => {
1813
1449
  transition: opacity 200ms ease-out, transform 200ms ease-out;
1814
1450
  padding: 24px;
1815
1451
  `;
1816
- let html = "";
1452
+ let html2 = "";
1817
1453
  if (content.title) {
1818
- html += `<h2 class="syntro-modal-title" style="margin: 0 0 12px 0; font-size: 18px; font-weight: 600; color: ${V.title};">${sanitizeHtml2(content.title)}</h2>`;
1454
+ html2 += `<h2 class="syntro-modal-title" style="margin: 0 0 12px 0; font-size: 18px; font-weight: 600; color: ${V.title};">${sanitizeHtml2(content.title)}</h2>`;
1819
1455
  }
1820
- html += `<div class="syntro-modal-body" style="color: ${V.text}; line-height: 1.5;">${sanitizeHtml2(content.body)}</div>`;
1456
+ html2 += `<div class="syntro-modal-body" style="color: ${V.text}; line-height: 1.5;">${sanitizeHtml2(content.body)}</div>`;
1821
1457
  if ((dismiss == null ? void 0 : dismiss.closeButton) !== false) {
1822
- html += `
1458
+ html2 += `
1823
1459
  <button class="syntro-modal-close" data-syntro-action="dismiss" style="
1824
1460
  position: absolute;
1825
1461
  top: 16px;
@@ -1838,10 +1474,10 @@ var executeModal = async (action, context) => {
1838
1474
  `;
1839
1475
  }
1840
1476
  if (ctaButtons && ctaButtons.length > 0) {
1841
- html += `<div class="syntro-modal-actions" style="display: flex; gap: 12px; margin-top: 24px; justify-content: flex-end;">`;
1477
+ html2 += `<div class="syntro-modal-actions" style="display: flex; gap: 12px; margin-top: 24px; justify-content: flex-end;">`;
1842
1478
  for (const btn of ctaButtons) {
1843
1479
  const isPrimary = (_b = btn.primary) != null ? _b : false;
1844
- html += `
1480
+ html2 += `
1845
1481
  <button
1846
1482
  class="syntro-modal-btn ${isPrimary ? "syntro-modal-btn-primary" : ""}"
1847
1483
  data-syntro-action="${sanitizeHtml2(btn.actionId)}"
@@ -1859,12 +1495,12 @@ var executeModal = async (action, context) => {
1859
1495
  </button>
1860
1496
  `;
1861
1497
  }
1862
- html += `</div>`;
1498
+ html2 += `</div>`;
1863
1499
  }
1864
- modal2.innerHTML = html;
1865
- context.overlayRoot.appendChild(modal2);
1500
+ modal.innerHTML = html2;
1501
+ context.overlayRoot.appendChild(modal);
1866
1502
  let actionClicked = null;
1867
- const actionBtns = modal2.querySelectorAll("[data-syntro-action]");
1503
+ const actionBtns = modal.querySelectorAll("[data-syntro-action]");
1868
1504
  const actionHandler = (e) => {
1869
1505
  const btn = e.currentTarget;
1870
1506
  const actionId = btn.getAttribute("data-syntro-action");
@@ -1904,14 +1540,14 @@ var executeModal = async (action, context) => {
1904
1540
  handle.destroy();
1905
1541
  }, dismiss.timeoutMs);
1906
1542
  }
1907
- const focusableEls = modal2.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
1543
+ const focusableEls = modal.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
1908
1544
  if (focusableEls.length > 0) {
1909
1545
  requestAnimationFrame(() => focusableEls[0].focus());
1910
1546
  }
1911
1547
  requestAnimationFrame(() => {
1912
1548
  scrimEl.style.opacity = "1";
1913
- modal2.style.opacity = "1";
1914
- modal2.style.transform = "translate(-50%, -50%) scale(1)";
1549
+ modal.style.opacity = "1";
1550
+ modal.style.transform = "translate(-50%, -50%) scale(1)";
1915
1551
  });
1916
1552
  context.publishEvent("action.applied", {
1917
1553
  id: context.generateId(),
@@ -1928,14 +1564,14 @@ var executeModal = async (action, context) => {
1928
1564
  scrimEl.removeEventListener("click", onScrimClick);
1929
1565
  actionBtns.forEach((btn) => btn.removeEventListener("click", actionHandler));
1930
1566
  originalInert.forEach((el) => el.removeAttribute("inert"));
1931
- modal2.style.pointerEvents = "none";
1567
+ modal.style.pointerEvents = "none";
1932
1568
  scrimEl.style.pointerEvents = "none";
1933
- modal2.style.opacity = "0";
1934
- modal2.style.transform = "translate(-50%, -50%) scale(0.95)";
1569
+ modal.style.opacity = "0";
1570
+ modal.style.transform = "translate(-50%, -50%) scale(0.95)";
1935
1571
  scrimEl.style.opacity = "0";
1936
1572
  setTimeout(() => {
1937
1573
  try {
1938
- modal2.remove();
1574
+ modal.remove();
1939
1575
  } catch {
1940
1576
  }
1941
1577
  try {
@@ -2163,7 +1799,7 @@ function showTooltip(anchorEl, overlayRoot, opts) {
2163
1799
  };
2164
1800
  }
2165
1801
  if (opts.trigger === "click") {
2166
- const toggle2 = () => {
1802
+ const toggle = () => {
2167
1803
  const isVisible = div.style.visibility === "visible";
2168
1804
  if (isVisible) {
2169
1805
  handle.destroy();
@@ -2175,8 +1811,8 @@ function showTooltip(anchorEl, overlayRoot, opts) {
2175
1811
  div.style.visibility = "hidden";
2176
1812
  div.style.opacity = "0";
2177
1813
  div.style.transition = "opacity 200ms ease, visibility 200ms";
2178
- anchorEl.addEventListener("click", toggle2);
2179
- return () => anchorEl.removeEventListener("click", toggle2);
1814
+ anchorEl.addEventListener("click", toggle);
1815
+ return () => anchorEl.removeEventListener("click", toggle);
2180
1816
  }
2181
1817
  div.style.opacity = "0";
2182
1818
  div.style.transition = "opacity 200ms ease";
@@ -2503,6 +2139,543 @@ var WorkflowMountableWidget = {
2503
2139
  }
2504
2140
  };
2505
2141
 
2142
+ // ../adaptives/adaptive-overlays/dist/WorkflowWidgetLit.js
2143
+ import { html, LitElement, nothing } from "lit";
2144
+ import { styleMap } from "lit/directives/style-map.js";
2145
+ var __classPrivateFieldSet = function(receiver, state, value, kind, f) {
2146
+ if (kind === "m") throw new TypeError("Private method is not writable");
2147
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
2148
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
2149
+ return kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value), value;
2150
+ };
2151
+ var __classPrivateFieldGet = function(receiver, state, kind, f) {
2152
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
2153
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
2154
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
2155
+ };
2156
+ var _WorkflowTrackerLit_unsubTourStarted;
2157
+ var _WorkflowTrackerLit_unsubTourEvents;
2158
+ var _WorkflowTrackerLit_toastCleanups;
2159
+ var _WorkflowTrackerLit_notified;
2160
+ var _WorkflowTrackerLit_completedMap;
2161
+ var _WorkflowTrackerLit_persistInitialized;
2162
+ var _WorkflowTrackerLit_tourWorkflows;
2163
+ var TOKEN_BLUE_4 = "#1969fe";
2164
+ var TOKEN_GREEN_4 = "#24ad32";
2165
+ var TOKEN_SLATE_2 = "#0e1114";
2166
+ var TOKEN_SLATE_7 = "#677384";
2167
+ var TOKEN_SLATE_9 = "#a8afba";
2168
+ var TOKEN_SLATE_12 = "#f6f7f9";
2169
+ var TOKEN_WHITE = "#ffffff";
2170
+ function showWorkflowToast2(notification) {
2171
+ const toast = document.createElement("div");
2172
+ toast.setAttribute("data-testid", "workflow-toast");
2173
+ Object.assign(toast.style, {
2174
+ position: "fixed",
2175
+ bottom: "16px",
2176
+ right: "16px",
2177
+ zIndex: "2147483646",
2178
+ padding: "12px 16px",
2179
+ borderRadius: "8px",
2180
+ backgroundColor: `var(--se-color-bg-surface, ${TOKEN_WHITE})`,
2181
+ color: `var(--se-color-text-primary, ${TOKEN_SLATE_2})`,
2182
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
2183
+ maxWidth: "320px",
2184
+ fontFamily: "var(--se-font-family, system-ui, sans-serif)",
2185
+ fontSize: "14px",
2186
+ lineHeight: "1.4",
2187
+ transition: "opacity 0.3s ease"
2188
+ });
2189
+ const titleEl = document.createElement("div");
2190
+ titleEl.style.fontWeight = "600";
2191
+ titleEl.textContent = notification.title;
2192
+ toast.appendChild(titleEl);
2193
+ if (notification.body) {
2194
+ const bodyEl = document.createElement("div");
2195
+ bodyEl.style.marginTop = "4px";
2196
+ bodyEl.style.fontSize = "13px";
2197
+ bodyEl.style.color = "var(--se-color-text-secondary, #666)";
2198
+ bodyEl.textContent = notification.body;
2199
+ toast.appendChild(bodyEl);
2200
+ }
2201
+ document.body.appendChild(toast);
2202
+ let removeTimer;
2203
+ const fadeTimer = setTimeout(() => {
2204
+ toast.style.opacity = "0";
2205
+ removeTimer = setTimeout(() => {
2206
+ toast.remove();
2207
+ }, 300);
2208
+ }, 4e3);
2209
+ return () => {
2210
+ clearTimeout(fadeTimer);
2211
+ clearTimeout(removeTimer);
2212
+ toast.remove();
2213
+ };
2214
+ }
2215
+ function extractWorkflowsFromActive2(activeActions) {
2216
+ const workflows = /* @__PURE__ */ new Map();
2217
+ for (const entry of activeActions) {
2218
+ const action = entry.action;
2219
+ if (action.kind === "overlays:tour" && action.workflow && action.tourId) {
2220
+ const meta = action.workflow;
2221
+ const rawSteps = action.steps || [];
2222
+ const steps = rawSteps.map((s) => {
2223
+ var _a2;
2224
+ return {
2225
+ id: s.id,
2226
+ title: ((_a2 = meta.stepTitles) == null ? void 0 : _a2[s.id]) || s.id
2227
+ };
2228
+ });
2229
+ workflows.set(action.tourId, { meta, steps });
2230
+ }
2231
+ }
2232
+ return workflows;
2233
+ }
2234
+ var TAG_NAME = "syntro-workflow-tracker";
2235
+ var WorkflowTrackerLit = class extends LitElement {
2236
+ constructor() {
2237
+ super(...arguments);
2238
+ this.runtimeRef = null;
2239
+ this._workflowEntries = [];
2240
+ this._actionVersion = 0;
2241
+ _WorkflowTrackerLit_unsubTourStarted.set(this, null);
2242
+ _WorkflowTrackerLit_unsubTourEvents.set(this, null);
2243
+ _WorkflowTrackerLit_toastCleanups.set(this, []);
2244
+ _WorkflowTrackerLit_notified.set(this, /* @__PURE__ */ new Set());
2245
+ _WorkflowTrackerLit_completedMap.set(this, {});
2246
+ _WorkflowTrackerLit_persistInitialized.set(this, false);
2247
+ _WorkflowTrackerLit_tourWorkflows.set(this, /* @__PURE__ */ new Map());
2248
+ }
2249
+ // ── Light DOM ─────────────────────────────────────────────────────────────
2250
+ /**
2251
+ * Render into the element itself (light DOM) so host-page CSS variables
2252
+ * flow through without a nested shadow boundary.
2253
+ */
2254
+ createRenderRoot() {
2255
+ return this;
2256
+ }
2257
+ // ── Helpers ───────────────────────────────────────────────────────────────
2258
+ get _stateNs() {
2259
+ var _a2, _b, _c, _d, _e;
2260
+ return (_e = (_d = (_c = (_b = (_a2 = this.runtimeRef) == null ? void 0 : _a2.state) == null ? void 0 : _b.user) == null ? void 0 : _c.ns) == null ? void 0 : _d.call(_c, "workflows")) != null ? _e : null;
2261
+ }
2262
+ /**
2263
+ * Re-scan active actions and update _tourWorkflows + entries.
2264
+ * Called initially and whenever _actionVersion bumps.
2265
+ */
2266
+ _rescanWorkflows() {
2267
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
2268
+ const active = (_d = (_c = (_b = (_a2 = this.runtimeRef) == null ? void 0 : _a2.actions) == null ? void 0 : _b.getActive) == null ? void 0 : _c.call(_b)) != null ? _d : [];
2269
+ const workflows = extractWorkflowsFromActive2(active);
2270
+ __classPrivateFieldSet(this, _WorkflowTrackerLit_tourWorkflows, workflows, "f");
2271
+ if (workflows.size === 0)
2272
+ return;
2273
+ const stateNs = this._stateNs;
2274
+ const dismissed = (_e = stateNs == null ? void 0 : stateNs.get("dismissed")) != null ? _e : [];
2275
+ const completed = (_f = stateNs == null ? void 0 : stateNs.get("completed")) != null ? _f : {};
2276
+ this._workflowEntries = (() => {
2277
+ const existingIds = new Set(this._workflowEntries.map((e) => e.tourId));
2278
+ const newEntries = [];
2279
+ for (const [tourId, { meta, steps }] of workflows) {
2280
+ if (existingIds.has(tourId))
2281
+ continue;
2282
+ let status = "active";
2283
+ if (dismissed.includes(tourId)) {
2284
+ status = "dismissed";
2285
+ } else if (completed[tourId]) {
2286
+ status = "completed";
2287
+ }
2288
+ newEntries.push({
2289
+ tourId,
2290
+ meta,
2291
+ steps,
2292
+ currentStepId: null,
2293
+ completedSteps: [],
2294
+ status,
2295
+ completedAt: completed[tourId] || void 0
2296
+ });
2297
+ }
2298
+ return newEntries.length > 0 ? [...this._workflowEntries, ...newEntries] : this._workflowEntries;
2299
+ })();
2300
+ for (const [tourId, { meta }] of workflows) {
2301
+ const dismissed2 = (_g = stateNs == null ? void 0 : stateNs.get("dismissed")) != null ? _g : [];
2302
+ const completed2 = (_h = stateNs == null ? void 0 : stateNs.get("completed")) != null ? _h : {};
2303
+ if (!__classPrivateFieldGet(this, _WorkflowTrackerLit_notified, "f").has(tourId) && meta.notification && !dismissed2.includes(tourId) && !completed2[tourId]) {
2304
+ __classPrivateFieldGet(this, _WorkflowTrackerLit_notified, "f").add(tourId);
2305
+ stateNs == null ? void 0 : stateNs.set("notified", [...__classPrivateFieldGet(this, _WorkflowTrackerLit_notified, "f")]);
2306
+ const cleanup = showWorkflowToast2(meta.notification);
2307
+ __classPrivateFieldGet(this, _WorkflowTrackerLit_toastCleanups, "f").push(cleanup);
2308
+ }
2309
+ }
2310
+ }
2311
+ // ── Lifecycle ─────────────────────────────────────────────────────────────
2312
+ connectedCallback() {
2313
+ super.connectedCallback();
2314
+ this._initSubscriptions();
2315
+ }
2316
+ disconnectedCallback() {
2317
+ super.disconnectedCallback();
2318
+ this._teardownSubscriptions();
2319
+ for (const cleanup of __classPrivateFieldGet(this, _WorkflowTrackerLit_toastCleanups, "f")) {
2320
+ cleanup();
2321
+ }
2322
+ __classPrivateFieldSet(this, _WorkflowTrackerLit_toastCleanups, [], "f");
2323
+ }
2324
+ updated(changed) {
2325
+ if (changed.has("runtimeRef")) {
2326
+ this._teardownSubscriptions();
2327
+ this._initSubscriptions();
2328
+ }
2329
+ if (changed.has("_actionVersion")) {
2330
+ this._rescanWorkflows();
2331
+ }
2332
+ }
2333
+ // ── Subscription management ───────────────────────────────────────────────
2334
+ _initSubscriptions() {
2335
+ var _a2, _b, _c, _d;
2336
+ if (!((_b = (_a2 = this.runtimeRef) == null ? void 0 : _a2.events) == null ? void 0 : _b.subscribe))
2337
+ return;
2338
+ if (!__classPrivateFieldGet(this, _WorkflowTrackerLit_persistInitialized, "f") && this._stateNs) {
2339
+ const notified = (_c = this._stateNs.get("notified")) != null ? _c : [];
2340
+ for (const id of notified) {
2341
+ __classPrivateFieldGet(this, _WorkflowTrackerLit_notified, "f").add(id);
2342
+ }
2343
+ const completed = (_d = this._stateNs.get("completed")) != null ? _d : {};
2344
+ __classPrivateFieldSet(this, _WorkflowTrackerLit_completedMap, { ...completed }, "f");
2345
+ __classPrivateFieldSet(this, _WorkflowTrackerLit_persistInitialized, true, "f");
2346
+ }
2347
+ __classPrivateFieldSet(this, _WorkflowTrackerLit_unsubTourStarted, this.runtimeRef.events.subscribe({ names: ["tour.started", "tour.resumed"] }, () => {
2348
+ this._actionVersion += 1;
2349
+ }), "f");
2350
+ __classPrivateFieldSet(this, _WorkflowTrackerLit_unsubTourEvents, this.runtimeRef.events.subscribe({ patterns: ["^tour\\."] }, (event) => {
2351
+ this._handleTourEvent(event);
2352
+ }), "f");
2353
+ this._rescanWorkflows();
2354
+ }
2355
+ _teardownSubscriptions() {
2356
+ var _a2, _b;
2357
+ (_a2 = __classPrivateFieldGet(this, _WorkflowTrackerLit_unsubTourStarted, "f")) == null ? void 0 : _a2.call(this);
2358
+ __classPrivateFieldSet(this, _WorkflowTrackerLit_unsubTourStarted, null, "f");
2359
+ (_b = __classPrivateFieldGet(this, _WorkflowTrackerLit_unsubTourEvents, "f")) == null ? void 0 : _b.call(this);
2360
+ __classPrivateFieldSet(this, _WorkflowTrackerLit_unsubTourEvents, null, "f");
2361
+ }
2362
+ // ── Event handler ─────────────────────────────────────────────────────────
2363
+ _handleTourEvent(event) {
2364
+ var _a2;
2365
+ const tourId = (_a2 = event.props) == null ? void 0 : _a2.tourId;
2366
+ if (!tourId)
2367
+ return;
2368
+ if (!__classPrivateFieldGet(this, _WorkflowTrackerLit_tourWorkflows, "f").has(tourId) && event.name === "tour.started") {
2369
+ this._actionVersion += 1;
2370
+ return;
2371
+ }
2372
+ if (!__classPrivateFieldGet(this, _WorkflowTrackerLit_tourWorkflows, "f").has(tourId))
2373
+ return;
2374
+ const stateNs = this._stateNs;
2375
+ this._workflowEntries = this._workflowEntries.map((entry) => {
2376
+ var _a3, _b, _c, _d, _e;
2377
+ if (entry.tourId !== tourId)
2378
+ return entry;
2379
+ switch (event.name) {
2380
+ case "tour.started": {
2381
+ const startStepId = ((_a3 = event.props) == null ? void 0 : _a3.startStepId) || ((_b = entry.steps[0]) == null ? void 0 : _b.id) || null;
2382
+ if (!__classPrivateFieldGet(this, _WorkflowTrackerLit_notified, "f").has(tourId)) {
2383
+ __classPrivateFieldGet(this, _WorkflowTrackerLit_notified, "f").add(tourId);
2384
+ stateNs == null ? void 0 : stateNs.set("notified", [...__classPrivateFieldGet(this, _WorkflowTrackerLit_notified, "f")]);
2385
+ const workflow = __classPrivateFieldGet(this, _WorkflowTrackerLit_tourWorkflows, "f").get(tourId);
2386
+ if (workflow == null ? void 0 : workflow.meta.notification) {
2387
+ const cleanup = showWorkflowToast2(workflow.meta.notification);
2388
+ __classPrivateFieldGet(this, _WorkflowTrackerLit_toastCleanups, "f").push(cleanup);
2389
+ }
2390
+ }
2391
+ const activeIds = this._workflowEntries.filter((e) => e.status === "active" || e.tourId === tourId).map((e) => e.tourId);
2392
+ if (!activeIds.includes(tourId)) {
2393
+ activeIds.push(tourId);
2394
+ }
2395
+ stateNs == null ? void 0 : stateNs.set("active", [...new Set(activeIds)]);
2396
+ return {
2397
+ ...entry,
2398
+ status: "active",
2399
+ currentStepId: startStepId,
2400
+ completedSteps: entry.status === "active" ? entry.completedSteps : []
2401
+ };
2402
+ }
2403
+ case "tour.step_started": {
2404
+ const stepId = (_c = event.props) == null ? void 0 : _c.stepId;
2405
+ return {
2406
+ ...entry,
2407
+ currentStepId: stepId || entry.currentStepId
2408
+ };
2409
+ }
2410
+ case "tour.step_changed": {
2411
+ const previousStepId = (_d = event.props) == null ? void 0 : _d.previousStepId;
2412
+ const nextStepId = (_e = event.props) == null ? void 0 : _e.nextStepId;
2413
+ const completedSteps = previousStepId && !entry.completedSteps.includes(previousStepId) ? [...entry.completedSteps, previousStepId] : entry.completedSteps;
2414
+ return {
2415
+ ...entry,
2416
+ currentStepId: nextStepId || entry.currentStepId,
2417
+ completedSteps
2418
+ };
2419
+ }
2420
+ case "tour.completed": {
2421
+ const completedAt = Date.now();
2422
+ __classPrivateFieldGet(this, _WorkflowTrackerLit_completedMap, "f")[tourId] = completedAt;
2423
+ stateNs == null ? void 0 : stateNs.set("completed", { ...__classPrivateFieldGet(this, _WorkflowTrackerLit_completedMap, "f") });
2424
+ return {
2425
+ ...entry,
2426
+ status: "completed",
2427
+ currentStepId: null,
2428
+ completedSteps: entry.steps.map((s) => s.id),
2429
+ completedAt
2430
+ };
2431
+ }
2432
+ case "tour.paused":
2433
+ return entry;
2434
+ default:
2435
+ return entry;
2436
+ }
2437
+ });
2438
+ }
2439
+ // ── User action handlers ──────────────────────────────────────────────────
2440
+ _handleStepClick(tourId, stepId) {
2441
+ var _a2, _b;
2442
+ (_b = (_a2 = this.runtimeRef) == null ? void 0 : _a2.events) == null ? void 0 : _b.publish("workflow:jump_to_step", { tourId, stepId });
2443
+ this.dispatchEvent(new CustomEvent("workflow-step-click", {
2444
+ bubbles: true,
2445
+ detail: { tourId, stepId }
2446
+ }));
2447
+ }
2448
+ _handleDismiss(tourId) {
2449
+ var _a2;
2450
+ this._workflowEntries = this._workflowEntries.map((entry) => entry.tourId === tourId ? { ...entry, status: "dismissed" } : entry);
2451
+ const dismissedIds = this._workflowEntries.filter((e) => e.status === "dismissed").map((e) => e.tourId);
2452
+ (_a2 = this._stateNs) == null ? void 0 : _a2.set("dismissed", dismissedIds);
2453
+ this.dispatchEvent(new CustomEvent("workflow-dismissed", {
2454
+ bubbles: true,
2455
+ detail: { tourId }
2456
+ }));
2457
+ }
2458
+ // ── Render helpers ────────────────────────────────────────────────────────
2459
+ _renderProgressBar(completed, total) {
2460
+ const percent = total > 0 ? Math.round(completed / total * 100) : 0;
2461
+ const trackStyles = {
2462
+ width: "100%",
2463
+ height: "6px",
2464
+ borderRadius: "9999px",
2465
+ background: "rgba(255,255,255,0.08)",
2466
+ overflow: "hidden"
2467
+ };
2468
+ const fillStyles = {
2469
+ height: "100%",
2470
+ borderRadius: "9999px",
2471
+ background: `var(--se-color-primary, ${TOKEN_BLUE_4})`,
2472
+ transition: "width 0.3s ease",
2473
+ width: `${percent}%`
2474
+ };
2475
+ return html`
2476
+ <div style=${styleMap(trackStyles)}>
2477
+ <div
2478
+ role="progressbar"
2479
+ aria-valuenow=${percent}
2480
+ aria-valuemin="0"
2481
+ aria-valuemax="100"
2482
+ style=${styleMap(fillStyles)}
2483
+ ></div>
2484
+ </div>
2485
+ `;
2486
+ }
2487
+ _renderStepItem(step, isCompleted, isCurrent, tourId) {
2488
+ const btnStyles = {
2489
+ display: "flex",
2490
+ alignItems: "center",
2491
+ gap: "8px",
2492
+ width: "100%",
2493
+ padding: "6px 8px",
2494
+ borderRadius: "4px",
2495
+ border: "none",
2496
+ background: "transparent",
2497
+ cursor: "pointer",
2498
+ textAlign: "left",
2499
+ fontSize: "12px",
2500
+ lineHeight: "1.4",
2501
+ color: isCurrent ? `var(--se-color-text-primary, ${TOKEN_SLATE_12})` : `var(--se-color-text-secondary, ${TOKEN_SLATE_9})`,
2502
+ fontWeight: isCurrent ? "600" : "400"
2503
+ };
2504
+ const indicatorWrapStyles = {
2505
+ flexShrink: "0",
2506
+ width: "16px",
2507
+ textAlign: "center"
2508
+ };
2509
+ const dotStyles = {
2510
+ display: "inline-block",
2511
+ width: "6px",
2512
+ height: "6px",
2513
+ borderRadius: "50%",
2514
+ background: isCurrent ? `var(--se-color-primary, ${TOKEN_BLUE_4})` : "rgba(255,255,255,0.12)"
2515
+ };
2516
+ const checkStyles = {
2517
+ color: `var(--se-color-success, ${TOKEN_GREEN_4})`
2518
+ };
2519
+ const labelStyles = {
2520
+ flex: "1",
2521
+ overflow: "hidden",
2522
+ textOverflow: "ellipsis",
2523
+ whiteSpace: "nowrap"
2524
+ };
2525
+ const indicator = isCompleted ? html`<span role="img" aria-label="completed" style=${styleMap(checkStyles)}>&#10003;</span>` : isCurrent ? html`<span style=${styleMap(dotStyles)}></span>` : html`<span style=${styleMap(dotStyles)}></span>`;
2526
+ return html`
2527
+ <button
2528
+ type="button"
2529
+ data-testid=${`step-${step.id}`}
2530
+ data-current=${isCurrent ? "true" : nothing}
2531
+ data-completed=${isCompleted ? "true" : nothing}
2532
+ aria-current=${isCurrent ? "step" : nothing}
2533
+ style=${styleMap(btnStyles)}
2534
+ @click=${() => this._handleStepClick(tourId, step.id)}
2535
+ >
2536
+ <span style=${styleMap(indicatorWrapStyles)}>${indicator}</span>
2537
+ <span style=${styleMap(labelStyles)}>${step.title}</span>
2538
+ </button>
2539
+ `;
2540
+ }
2541
+ _renderWorkflowCard(workflow) {
2542
+ const completedCount = workflow.completedSteps.length;
2543
+ const totalSteps = workflow.steps.length;
2544
+ const cardStyles = {
2545
+ padding: "12px",
2546
+ borderRadius: "8px",
2547
+ border: "1px solid rgba(255,255,255,0.08)",
2548
+ background: "rgba(255,255,255,0.02)"
2549
+ };
2550
+ const headerStyles = {
2551
+ display: "flex",
2552
+ alignItems: "center",
2553
+ gap: "8px",
2554
+ marginBottom: "8px"
2555
+ };
2556
+ const titleStyles = {
2557
+ flex: "1",
2558
+ fontSize: "13px",
2559
+ fontWeight: "600",
2560
+ color: `var(--se-color-text-primary, ${TOKEN_SLATE_12})`,
2561
+ overflow: "hidden",
2562
+ textOverflow: "ellipsis",
2563
+ whiteSpace: "nowrap"
2564
+ };
2565
+ const dismissBtnStyles = {
2566
+ flexShrink: "0",
2567
+ padding: "2px 6px",
2568
+ border: "none",
2569
+ borderRadius: "4px",
2570
+ background: "transparent",
2571
+ color: `var(--se-color-text-tertiary, ${TOKEN_SLATE_7})`,
2572
+ fontSize: "12px",
2573
+ cursor: "pointer",
2574
+ lineHeight: "1"
2575
+ };
2576
+ const progressWrapStyles = {
2577
+ marginBottom: "8px"
2578
+ };
2579
+ const progressLabelStyles = {
2580
+ fontSize: "10px",
2581
+ color: `var(--se-color-text-tertiary, ${TOKEN_SLATE_7})`,
2582
+ marginTop: "4px"
2583
+ };
2584
+ const stepsColStyles = {
2585
+ display: "flex",
2586
+ flexDirection: "column"
2587
+ };
2588
+ return html`
2589
+ <div style=${styleMap(cardStyles)}>
2590
+ <!-- Header: icon + title + dismiss -->
2591
+ <div style=${styleMap(headerStyles)}>
2592
+ ${workflow.meta.icon ? html`<span data-testid="workflow-icon" style="flex-shrink:0;font-size:14px">${workflow.meta.icon}</span>` : nothing}
2593
+ <span style=${styleMap(titleStyles)}>${workflow.meta.title}</span>
2594
+ <button
2595
+ type="button"
2596
+ data-testid=${`dismiss-${workflow.tourId}`}
2597
+ style=${styleMap(dismissBtnStyles)}
2598
+ aria-label=${`Dismiss ${workflow.meta.title}`}
2599
+ @click=${() => this._handleDismiss(workflow.tourId)}
2600
+ >&#10005;</button>
2601
+ </div>
2602
+
2603
+ <!-- Progress bar + label -->
2604
+ <div style=${styleMap(progressWrapStyles)}>
2605
+ ${this._renderProgressBar(completedCount, totalSteps)}
2606
+ <div style=${styleMap(progressLabelStyles)}>
2607
+ ${completedCount} of ${totalSteps} steps
2608
+ </div>
2609
+ </div>
2610
+
2611
+ <!-- Step list -->
2612
+ <div style=${styleMap(stepsColStyles)}>
2613
+ ${workflow.steps.map((step) => this._renderStepItem(step, workflow.completedSteps.includes(step.id), workflow.currentStepId === step.id, workflow.tourId))}
2614
+ </div>
2615
+ </div>
2616
+ `;
2617
+ }
2618
+ // ── Render ────────────────────────────────────────────────────────────────
2619
+ render() {
2620
+ const activeWorkflows = this._workflowEntries.filter((w) => w.status === "active");
2621
+ if (activeWorkflows.length === 0) {
2622
+ const emptyStyles = {
2623
+ display: "flex",
2624
+ alignItems: "center",
2625
+ justifyContent: "center",
2626
+ padding: "24px 0",
2627
+ fontSize: "12px",
2628
+ color: `var(--se-color-text-tertiary, ${TOKEN_SLATE_7})`
2629
+ };
2630
+ return html`<div style=${styleMap(emptyStyles)}>No active workflows</div>`;
2631
+ }
2632
+ const containerStyles = {
2633
+ display: "flex",
2634
+ flexDirection: "column",
2635
+ gap: "8px"
2636
+ };
2637
+ return html`
2638
+ <div style=${styleMap(containerStyles)}>
2639
+ ${activeWorkflows.map((workflow) => this._renderWorkflowCard(workflow))}
2640
+ </div>
2641
+ `;
2642
+ }
2643
+ };
2644
+ _WorkflowTrackerLit_unsubTourStarted = /* @__PURE__ */ new WeakMap(), _WorkflowTrackerLit_unsubTourEvents = /* @__PURE__ */ new WeakMap(), _WorkflowTrackerLit_toastCleanups = /* @__PURE__ */ new WeakMap(), _WorkflowTrackerLit_notified = /* @__PURE__ */ new WeakMap(), _WorkflowTrackerLit_completedMap = /* @__PURE__ */ new WeakMap(), _WorkflowTrackerLit_persistInitialized = /* @__PURE__ */ new WeakMap(), _WorkflowTrackerLit_tourWorkflows = /* @__PURE__ */ new WeakMap();
2645
+ WorkflowTrackerLit.properties = {
2646
+ // Public input: runtime ref injected by MountableWidget
2647
+ runtimeRef: { attribute: false },
2648
+ // Internal reactive state
2649
+ _workflowEntries: { state: true },
2650
+ _actionVersion: { state: true }
2651
+ };
2652
+ if (typeof window !== "undefined" && !customElements.get(TAG_NAME)) {
2653
+ customElements.define(TAG_NAME, WorkflowTrackerLit);
2654
+ }
2655
+ var WorkflowWidgetLitMountable = {
2656
+ mount(container, config) {
2657
+ var _a2;
2658
+ const runtime3 = (_a2 = config == null ? void 0 : config.runtime) != null ? _a2 : null;
2659
+ if (typeof window !== "undefined" && !customElements.get(TAG_NAME)) {
2660
+ customElements.define(TAG_NAME, WorkflowTrackerLit);
2661
+ }
2662
+ const el = document.createElement(TAG_NAME);
2663
+ el.runtimeRef = runtime3;
2664
+ container.appendChild(el);
2665
+ return () => {
2666
+ el.remove();
2667
+ };
2668
+ },
2669
+ update(container, config) {
2670
+ var _a2;
2671
+ const el = container.querySelector(TAG_NAME);
2672
+ if (!el)
2673
+ return;
2674
+ const runtime3 = (_a2 = config == null ? void 0 : config.runtime) != null ? _a2 : null;
2675
+ el.runtimeRef = runtime3;
2676
+ }
2677
+ };
2678
+
2506
2679
  // ../adaptives/adaptive-overlays/dist/runtime.js
2507
2680
  var executeHighlight = async (action, context) => {
2508
2681
  var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
@@ -2671,10 +2844,10 @@ var executeBadge = async (action, context) => {
2671
2844
  }
2672
2845
  } catch {
2673
2846
  }
2674
- const badge2 = document.createElement("div");
2675
- badge2.textContent = action.content;
2676
- badge2.setAttribute("data-syntro-badge", action.anchorId.selector);
2677
- Object.assign(badge2.style, {
2847
+ const badge = document.createElement("div");
2848
+ badge.textContent = action.content;
2849
+ badge.setAttribute("data-syntro-badge", action.anchorId.selector);
2850
+ Object.assign(badge.style, {
2678
2851
  position: "absolute",
2679
2852
  padding: "2px 6px",
2680
2853
  fontSize: "12px",
@@ -2692,19 +2865,19 @@ var executeBadge = async (action, context) => {
2692
2865
  if (getComputedStyle(anchorEl).position === "static") {
2693
2866
  anchorEl.style.position = "relative";
2694
2867
  }
2695
- anchorEl.appendChild(badge2);
2868
+ anchorEl.appendChild(badge);
2696
2869
  switch (position) {
2697
2870
  case "top-left":
2698
- Object.assign(badge2.style, { top: "-8px", left: "-8px" });
2871
+ Object.assign(badge.style, { top: "-8px", left: "-8px" });
2699
2872
  break;
2700
2873
  case "top-right":
2701
- Object.assign(badge2.style, { top: "-8px", right: "-8px" });
2874
+ Object.assign(badge.style, { top: "-8px", right: "-8px" });
2702
2875
  break;
2703
2876
  case "bottom-left":
2704
- Object.assign(badge2.style, { bottom: "-8px", left: "-8px" });
2877
+ Object.assign(badge.style, { bottom: "-8px", left: "-8px" });
2705
2878
  break;
2706
2879
  case "bottom-right":
2707
- Object.assign(badge2.style, { bottom: "-8px", right: "-8px" });
2880
+ Object.assign(badge.style, { bottom: "-8px", right: "-8px" });
2708
2881
  break;
2709
2882
  }
2710
2883
  context.publishEvent("action.applied", {
@@ -2717,7 +2890,7 @@ var executeBadge = async (action, context) => {
2717
2890
  return {
2718
2891
  cleanup: () => {
2719
2892
  try {
2720
- badge2.remove();
2893
+ badge.remove();
2721
2894
  } catch {
2722
2895
  }
2723
2896
  if (!anchorEl.isConnected)
@@ -2728,7 +2901,7 @@ var executeBadge = async (action, context) => {
2728
2901
  },
2729
2902
  updateFn: (changes) => {
2730
2903
  if ("content" in changes && typeof changes.content === "string") {
2731
- badge2.textContent = changes.content;
2904
+ badge.textContent = changes.content;
2732
2905
  }
2733
2906
  }
2734
2907
  };
@@ -2745,16 +2918,16 @@ var executeTooltip = async (action, context) => {
2745
2918
  } };
2746
2919
  }
2747
2920
  const { content } = action;
2748
- let html = "";
2921
+ let html2 = "";
2749
2922
  if (content.title) {
2750
- html += `<div class="syntro-tt-title">${sanitizeHtml2(content.title)}</div>`;
2923
+ html2 += `<div class="syntro-tt-title">${sanitizeHtml2(content.title)}</div>`;
2751
2924
  }
2752
- html += `<div class="syntro-tt-body">${sanitizeHtml2(content.body)}</div>`;
2925
+ html2 += `<div class="syntro-tt-body">${sanitizeHtml2(content.body)}</div>`;
2753
2926
  if (content.ctaButtons && content.ctaButtons.length > 0) {
2754
- html += `<div class="syntro-tt-actions">`;
2927
+ html2 += `<div class="syntro-tt-actions">`;
2755
2928
  for (const btn of content.ctaButtons) {
2756
2929
  const isPrimary = (_a2 = btn.primary) != null ? _a2 : false;
2757
- html += `
2930
+ html2 += `
2758
2931
  <button
2759
2932
  class="syntro-tt-btn ${isPrimary ? "syntro-tt-btn-primary" : ""}"
2760
2933
  data-syntro-action="${sanitizeHtml2(btn.actionId)}"
@@ -2763,16 +2936,16 @@ var executeTooltip = async (action, context) => {
2763
2936
  </button>
2764
2937
  `;
2765
2938
  }
2766
- html += `</div>`;
2939
+ html2 += `</div>`;
2767
2940
  } else if (content.cta) {
2768
- html += `<div class="syntro-tt-actions">
2941
+ html2 += `<div class="syntro-tt-actions">
2769
2942
  <button class="syntro-tt-btn syntro-tt-btn-primary" data-syntro-action="cta">
2770
2943
  ${sanitizeHtml2(content.cta.label)}
2771
2944
  </button>
2772
2945
  </div>`;
2773
2946
  }
2774
2947
  const handle = showTooltip(anchorEl, context.overlayRoot, {
2775
- html,
2948
+ html: html2,
2776
2949
  placement: (_b = action.placement) != null ? _b : "top",
2777
2950
  trigger: (_c = action.trigger) != null ? _c : "immediate",
2778
2951
  onAction: (actionId) => {
@@ -2834,6 +3007,15 @@ var runtime2 = {
2834
3007
  icon: "\u{1F4CB}",
2835
3008
  description: "Tracks multi-step workflow progress across tours"
2836
3009
  }
3010
+ },
3011
+ {
3012
+ id: "adaptive-overlays:workflow-tracker-lit",
3013
+ component: WorkflowWidgetLitMountable,
3014
+ metadata: {
3015
+ name: "Workflow Tracker (Lit)",
3016
+ icon: "\u{1F4CB}",
3017
+ description: "Lit web component equivalent of the Workflow Tracker \u2014 decorator-free, light DOM"
3018
+ }
2837
3019
  }
2838
3020
  ]
2839
3021
  };
@@ -2950,7 +3132,9 @@ var NAMESPACE_TO_APP_ID = {
2950
3132
  faq: "adaptive-faq",
2951
3133
  nav: "adaptive-nav",
2952
3134
  gamification: "adaptive-gamification",
2953
- chatbot: "adaptive-chatbot"
3135
+ chatbot: "adaptive-chatbot",
3136
+ overlays: "adaptive-overlays",
3137
+ content: "adaptive-content"
2954
3138
  };
2955
3139
  function resolveAppId(namespace) {
2956
3140
  var _a2;
@@ -3456,14 +3640,20 @@ function getAntiFlickerSnippet(config = {}) {
3456
3640
  }
3457
3641
 
3458
3642
  // src/version.ts
3459
- var SDK_VERSION = "2.13.0";
3643
+ var SDK_VERSION = "2.15.0";
3460
3644
 
3461
3645
  // src/types.ts
3462
3646
  var SDK_SCHEMA_VERSION = "2.0";
3463
3647
 
3464
3648
  // src/fetchers/mergeConfigs.ts
3465
- function resolveVariantConfigs(client, keys, _strategy = "first-match") {
3466
- var _a2, _b, _c, _d;
3649
+ function resolveVariantConfigs(client, keys, strategy = "merge") {
3650
+ if (strategy === "first-match") {
3651
+ return resolveFirstMatch(client, keys);
3652
+ }
3653
+ return resolveMerge(client, keys);
3654
+ }
3655
+ function resolveFirstMatch(client, keys) {
3656
+ var _a2;
3467
3657
  for (const key of keys) {
3468
3658
  const value = (_a2 = client.getFeatureValue) == null ? void 0 : _a2.call(client, key, null);
3469
3659
  if (!value || typeof value !== "object") continue;
@@ -3471,20 +3661,60 @@ function resolveVariantConfigs(client, keys, _strategy = "first-match") {
3471
3661
  const hasTiles = variant.tiles && variant.tiles.length > 0;
3472
3662
  const hasActions = variant.actions && variant.actions.length > 0;
3473
3663
  if (hasTiles || hasActions) {
3474
- return {
3475
- tiles: (_b = variant.tiles) != null ? _b : [],
3476
- actions: (_c = variant.actions) != null ? _c : [],
3477
- fetchedAt: (_d = variant.fetchedAt) != null ? _d : (/* @__PURE__ */ new Date()).toISOString(),
3478
- ...variant.schemaVersion && { schemaVersion: variant.schemaVersion },
3479
- ...variant.configVersion && { configVersion: variant.configVersion },
3480
- ...variant.canvasTitle && { canvasTitle: variant.canvasTitle },
3481
- ...variant.theme && { theme: variant.theme },
3482
- ...variant.launcher && { launcher: variant.launcher }
3483
- };
3664
+ return buildConfig([variant]);
3484
3665
  }
3485
3666
  }
3486
3667
  return null;
3487
3668
  }
3669
+ function resolveMerge(client, keys) {
3670
+ var _a2;
3671
+ const variants = [];
3672
+ for (const key of keys) {
3673
+ const value = (_a2 = client.getFeatureValue) == null ? void 0 : _a2.call(client, key, null);
3674
+ if (!value || typeof value !== "object") continue;
3675
+ const variant = value;
3676
+ const hasTiles = variant.tiles && variant.tiles.length > 0;
3677
+ const hasActions = variant.actions && variant.actions.length > 0;
3678
+ if (hasTiles || hasActions) {
3679
+ variants.push(variant);
3680
+ }
3681
+ }
3682
+ if (variants.length === 0) return null;
3683
+ return buildConfig(variants);
3684
+ }
3685
+ function buildConfig(variants) {
3686
+ const allTiles = [];
3687
+ const allActions = [];
3688
+ let fetchedAt;
3689
+ let schemaVersion;
3690
+ let configVersion;
3691
+ let canvasTitle;
3692
+ let theme;
3693
+ let launcher;
3694
+ let meta;
3695
+ for (const variant of variants) {
3696
+ if (variant.tiles) allTiles.push(...variant.tiles);
3697
+ if (variant.actions) allActions.push(...variant.actions);
3698
+ fetchedAt != null ? fetchedAt : fetchedAt = variant.fetchedAt;
3699
+ schemaVersion != null ? schemaVersion : schemaVersion = variant.schemaVersion;
3700
+ configVersion != null ? configVersion : configVersion = variant.configVersion;
3701
+ canvasTitle != null ? canvasTitle : canvasTitle = variant.canvasTitle;
3702
+ theme != null ? theme : theme = variant.theme;
3703
+ launcher != null ? launcher : launcher = variant.launcher;
3704
+ meta != null ? meta : meta = variant.meta;
3705
+ }
3706
+ return {
3707
+ tiles: allTiles,
3708
+ actions: allActions,
3709
+ fetchedAt: fetchedAt != null ? fetchedAt : (/* @__PURE__ */ new Date()).toISOString(),
3710
+ ...schemaVersion && { schemaVersion },
3711
+ ...configVersion && { configVersion },
3712
+ ...canvasTitle && { canvasTitle },
3713
+ ...theme && { theme },
3714
+ ...launcher && { launcher },
3715
+ ...meta && { meta }
3716
+ };
3717
+ }
3488
3718
 
3489
3719
  // src/logger.ts
3490
3720
  var debugEnabled = false;
@@ -3931,30 +4161,66 @@ function getEventName(phEvent) {
3931
4161
  return eventName.replace("$", "posthog.");
3932
4162
  }
3933
4163
  var INTERACTIVE_TAGS = /* @__PURE__ */ new Set(["a", "button", "input", "select", "textarea"]);
4164
+ function parseElementsChain(chain) {
4165
+ if (!chain)
4166
+ return void 0;
4167
+ return chain.split(";").map((segment) => {
4168
+ var _a2;
4169
+ const el = {};
4170
+ const colonIdx = segment.indexOf(":");
4171
+ const tagPart = colonIdx >= 0 ? segment.slice(0, colonIdx) : segment;
4172
+ const attrPart = colonIdx >= 0 ? segment.slice(colonIdx + 1) : "";
4173
+ const dotIdx = tagPart.indexOf(".");
4174
+ if (dotIdx >= 0) {
4175
+ el.tag_name = tagPart.slice(0, dotIdx);
4176
+ el.attr__class = tagPart.slice(dotIdx + 1).replace(/\./g, " ");
4177
+ } else {
4178
+ el.tag_name = tagPart;
4179
+ }
4180
+ if (!/^[a-zA-Z][a-zA-Z0-9-]*$/.test(String((_a2 = el.tag_name) != null ? _a2 : "")))
4181
+ return null;
4182
+ const attrRegex = /([\w$]+)="([^"]*)"/g;
4183
+ let match;
4184
+ while ((match = attrRegex.exec(attrPart)) !== null) {
4185
+ const [, key, value] = match;
4186
+ if (key === "nth-child" || key === "nth-of-type")
4187
+ continue;
4188
+ el[key] = value;
4189
+ }
4190
+ if (el.text) {
4191
+ el.$el_text = el.text;
4192
+ delete el.text;
4193
+ }
4194
+ return el;
4195
+ }).filter((el) => el !== null);
4196
+ }
3934
4197
  function resolveInteractiveTag(elements, directTag) {
3935
4198
  if (directTag && INTERACTIVE_TAGS.has(directTag))
3936
4199
  return directTag;
3937
4200
  if (!elements)
3938
4201
  return directTag;
3939
4202
  for (const el of elements) {
3940
- const tag2 = el.tag_name;
3941
- if (tag2 && INTERACTIVE_TAGS.has(tag2))
3942
- return tag2;
4203
+ const tag = el.tag_name;
4204
+ if (tag && INTERACTIVE_TAGS.has(tag))
4205
+ return tag;
3943
4206
  }
3944
4207
  return directTag;
3945
4208
  }
3946
4209
  function extractProps(phEvent) {
3947
- var _a2, _b;
4210
+ var _a2, _b, _c;
3948
4211
  const props = {};
3949
4212
  const phProps = phEvent.properties || {};
3950
- const elements = phProps.$elements;
3951
- const directTag = (_b = phProps.$tag_name) != null ? _b : (_a2 = elements == null ? void 0 : elements[0]) == null ? void 0 : _a2.tag_name;
4213
+ const elements = (_a2 = phProps.$elements) != null ? _a2 : typeof phProps.$elements_chain === "string" ? parseElementsChain(phProps.$elements_chain) : void 0;
4214
+ const directTag = (_c = phProps.$tag_name) != null ? _c : (_b = elements == null ? void 0 : elements[0]) == null ? void 0 : _b.tag_name;
3952
4215
  const isClickEvent = phEvent.event === "$autocapture" || phEvent.event === "$click";
3953
4216
  props.tagName = isClickEvent ? resolveInteractiveTag(elements, directTag) : directTag;
3954
4217
  if (phProps.$el_text)
3955
4218
  props.elementText = phProps.$el_text;
3956
4219
  if (elements)
3957
4220
  props.elements = elements;
4221
+ if (isClickEvent && !elements) {
4222
+ console.warn(`[PostHogNormalizer] $autocapture click has no element chain. PostHog may have changed wire format. Properties: $elements=${!!phProps.$elements}, $elements_chain=${typeof phProps.$elements_chain}`);
4223
+ }
3958
4224
  if (phProps.$current_url)
3959
4225
  props.url = phProps.$current_url;
3960
4226
  if (phProps.$pathname)
@@ -4878,6 +5144,7 @@ function collectEntries(tiles, appRegistry2) {
4878
5144
  function useNotifyWatcher(runtime3, tiles, appRegistry2) {
4879
5145
  const prevStateRef = useRef3(/* @__PURE__ */ new Map());
4880
5146
  useEffect3(() => {
5147
+ var _a2;
4881
5148
  if (!(runtime3 == null ? void 0 : runtime3.events) || !appRegistry2) return;
4882
5149
  const entries = collectEntries(tiles, appRegistry2);
4883
5150
  if (entries.length === 0) return;
@@ -4892,11 +5159,11 @@ function useNotifyWatcher(runtime3, tiles, appRegistry2) {
4892
5159
  }
4893
5160
  }
4894
5161
  }
4895
- const unsub = runtime3.events.subscribe(() => {
4896
- var _a2;
5162
+ const reeval = () => {
5163
+ var _a3;
4897
5164
  for (const entry of entries) {
4898
5165
  const result = runtime3.evaluateSync(entry.strategy);
4899
- const wasVisible = (_a2 = prevStateRef.current.get(entry.id)) != null ? _a2 : false;
5166
+ const wasVisible = (_a3 = prevStateRef.current.get(entry.id)) != null ? _a3 : false;
4900
5167
  prevStateRef.current.set(entry.id, result.value);
4901
5168
  if (!wasVisible && result.value) {
4902
5169
  notifiedStore.set(entry.id, true);
@@ -4905,8 +5172,13 @@ function useNotifyWatcher(runtime3, tiles, appRegistry2) {
4905
5172
  notifiedStore.remove(entry.id);
4906
5173
  }
4907
5174
  }
4908
- });
4909
- return unsub;
5175
+ };
5176
+ const unsubEvents = runtime3.events.subscribe(reeval);
5177
+ const unsubMetrics = (_a2 = runtime3.sessionMetrics) == null ? void 0 : _a2.subscribe(reeval);
5178
+ return () => {
5179
+ unsubEvents();
5180
+ unsubMetrics == null ? void 0 : unsubMetrics();
5181
+ };
4910
5182
  }, [runtime3, tiles, appRegistry2]);
4911
5183
  }
4912
5184
 
@@ -5240,448 +5512,9 @@ function TileCard({
5240
5512
  }
5241
5513
 
5242
5514
  // src/components/ShadowCanvasOverlay.tsx
5243
- import { useCallback as useCallback4, useEffect as useEffect7, useMemo as useMemo5, useRef as useRef5, useState as useState5 } from "react";
5515
+ import { useCallback as useCallback4, useEffect as useEffect6, useMemo as useMemo4, useRef as useRef5, useState as useState5 } from "react";
5244
5516
  import { createPortal } from "react-dom";
5245
-
5246
- // src/theme/defaultTheme.ts
5247
- function withAlpha(hex, alpha) {
5248
- return `${hex}${Math.round(alpha * 255).toString(16).padStart(2, "0")}`;
5249
- }
5250
- var darkTheme = {
5251
- // Brand colors
5252
- colorPrimary: brand[3],
5253
- colorPrimaryHover: brand[4],
5254
- colorPrimaryMuted: brand[0],
5255
- // Surface colors (with alpha for glass/vibrancy effects)
5256
- colorBackground: withAlpha(slateGrey[1], 0.95),
5257
- colorBackgroundElevated: withAlpha(slateGrey[3], 0.95),
5258
- colorBackgroundSubtle: withAlpha(slateGrey[0], 0.2),
5259
- colorSurface: withAlpha(slateGrey[4], 0.8),
5260
- colorSurfaceHover: withAlpha(slateGrey[5], 0.8),
5261
- // Text colors
5262
- colorText: text.primary,
5263
- colorTextSecondary: text.secondary,
5264
- colorTextMuted: text.tertiary,
5265
- colorTextInverse: slateGrey[1],
5266
- // Border colors
5267
- colorBorder: border.primary,
5268
- colorBorderSubtle: border.secondary,
5269
- // Semantic colors
5270
- colorSuccess: green[4],
5271
- colorSuccessMuted: green[0],
5272
- colorWarning: yellow[4],
5273
- colorWarningMuted: yellow[0],
5274
- colorError: red[4],
5275
- colorErrorMuted: red[0],
5276
- colorInfo: blue[4],
5277
- colorInfoMuted: blue[0],
5278
- // Notification badge
5279
- colorNotification: brand[4],
5280
- colorNotificationMuted: withAlpha(brand[4], 0.4),
5281
- // Glass morphism
5282
- glassBackground: withAlpha(slateGrey[1], 0.6),
5283
- glassBackgroundHover: withAlpha(slateGrey[1], 0.7),
5284
- glassBorder: "rgba(255, 255, 255, 0.08)",
5285
- glassBlur: "blur(24px)",
5286
- glassSaturate: "saturate(1.2)",
5287
- // Typography (SF Pro stack)
5288
- fontFamily: "-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif",
5289
- fontFamilyMono: "'SF Mono', 'Fira Code', Consolas, monospace",
5290
- fontSizeXs: "0.7rem",
5291
- fontSizeSm: "0.8rem",
5292
- fontSizeMd: "0.9rem",
5293
- fontSizeLg: "1rem",
5294
- fontSizeXl: "1.25rem",
5295
- fontSizeXxl: "1.5rem",
5296
- fontWeightNormal: "400",
5297
- fontWeightMedium: "500",
5298
- fontWeightSemibold: "600",
5299
- fontWeightBold: "700",
5300
- lineHeightTight: "1.25",
5301
- lineHeightNormal: "1.5",
5302
- lineHeightRelaxed: "1.75",
5303
- // Spacing
5304
- spacingXs: "0.25rem",
5305
- spacingSm: "0.5rem",
5306
- spacingMd: "0.75rem",
5307
- spacingLg: "1rem",
5308
- spacingXl: "1.5rem",
5309
- // Border radius
5310
- borderRadiusSm: "6px",
5311
- borderRadiusMd: "10px",
5312
- borderRadiusLg: "14px",
5313
- borderRadiusXl: "20px",
5314
- borderRadiusFull: "9999px",
5315
- // Shadows
5316
- shadowSm: "0 1px 2px rgba(0, 0, 0, 0.2)",
5317
- shadowMd: "0 2px 12px rgba(0, 0, 0, 0.3)",
5318
- shadowLg: "0 8px 24px rgba(0, 0, 0, 0.4)",
5319
- shadowXl: "0 16px 48px rgba(0, 0, 0, 0.5)",
5320
- // Backdrop effects
5321
- backdropBlur: "blur(20px)",
5322
- backdropSaturate: "saturate(180%)",
5323
- // Animation
5324
- transitionFast: "0.1s ease",
5325
- transitionNormal: "0.25s ease",
5326
- transitionSlow: "0.4s ease"
5327
- };
5328
- var lightTheme = {
5329
- // Brand colors
5330
- colorPrimary: brand[3],
5331
- colorPrimaryHover: brand[2],
5332
- colorPrimaryMuted: withAlpha(brand[5], 0.1),
5333
- // Surface colors
5334
- colorBackground: withAlpha(slateGrey[12], 0.95),
5335
- colorBackgroundElevated: withAlpha(slateGrey[11], 0.95),
5336
- colorBackgroundSubtle: withAlpha(slateGrey[0], 0.02),
5337
- colorSurface: withAlpha(slateGrey[11], 0.6),
5338
- colorSurfaceHover: withAlpha(slateGrey[10], 0.6),
5339
- // Text colors
5340
- colorText: slateGrey[1],
5341
- colorTextSecondary: slateGrey[6],
5342
- colorTextMuted: slateGrey[8],
5343
- colorTextInverse: slateGrey[12],
5344
- // Border colors
5345
- colorBorder: withAlpha(slateGrey[0], 0.12),
5346
- colorBorderSubtle: withAlpha(slateGrey[0], 0.06),
5347
- // Semantic colors
5348
- colorSuccess: green[4],
5349
- colorSuccessMuted: withAlpha(green[4], 0.12),
5350
- colorWarning: yellow[4],
5351
- colorWarningMuted: withAlpha(yellow[4], 0.12),
5352
- colorError: red[4],
5353
- colorErrorMuted: withAlpha(red[4], 0.12),
5354
- colorInfo: blue[4],
5355
- colorInfoMuted: withAlpha(blue[4], 0.12),
5356
- // Notification badge
5357
- colorNotification: brand[3],
5358
- colorNotificationMuted: withAlpha(brand[3], 0.4),
5359
- // Glass morphism
5360
- glassBackground: withAlpha(slateGrey[12], 0.7),
5361
- glassBackgroundHover: withAlpha(slateGrey[12], 0.8),
5362
- glassBorder: "rgba(0, 0, 0, 0.06)",
5363
- glassBlur: "blur(24px)",
5364
- glassSaturate: "saturate(1.2)",
5365
- // Typography (same as dark)
5366
- fontFamily: "-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif",
5367
- fontFamilyMono: "'SF Mono', 'Fira Code', Consolas, monospace",
5368
- fontSizeXs: "0.7rem",
5369
- fontSizeSm: "0.8rem",
5370
- fontSizeMd: "0.9rem",
5371
- fontSizeLg: "1rem",
5372
- fontSizeXl: "1.25rem",
5373
- fontSizeXxl: "1.5rem",
5374
- fontWeightNormal: "400",
5375
- fontWeightMedium: "500",
5376
- fontWeightSemibold: "600",
5377
- fontWeightBold: "700",
5378
- lineHeightTight: "1.25",
5379
- lineHeightNormal: "1.5",
5380
- lineHeightRelaxed: "1.75",
5381
- // Spacing (same as dark)
5382
- spacingXs: "0.25rem",
5383
- spacingSm: "0.5rem",
5384
- spacingMd: "0.75rem",
5385
- spacingLg: "1rem",
5386
- spacingXl: "1.5rem",
5387
- // Border radius (same as dark)
5388
- borderRadiusSm: "6px",
5389
- borderRadiusMd: "10px",
5390
- borderRadiusLg: "14px",
5391
- borderRadiusXl: "20px",
5392
- borderRadiusFull: "9999px",
5393
- // Shadows (lighter for light mode)
5394
- shadowSm: "0 1px 2px rgba(0, 0, 0, 0.08)",
5395
- shadowMd: "0 2px 12px rgba(0, 0, 0, 0.12)",
5396
- shadowLg: "0 8px 24px rgba(0, 0, 0, 0.16)",
5397
- shadowXl: "0 16px 48px rgba(0, 0, 0, 0.2)",
5398
- // Backdrop effects
5399
- backdropBlur: "blur(20px)",
5400
- backdropSaturate: "saturate(180%)",
5401
- // Animation
5402
- transitionFast: "0.1s ease",
5403
- transitionNormal: "0.25s ease",
5404
- transitionSlow: "0.4s ease"
5405
- };
5406
- function kebabCase(str) {
5407
- return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
5408
- }
5409
- var darkDefaults = {
5410
- mode: "dark",
5411
- fontFamily: "-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif",
5412
- colorPrimary: brand[3],
5413
- colorPrimaryHover: brand[4],
5414
- borderRadius: "12px",
5415
- canvas: {
5416
- position: "right",
5417
- layout: "overlay",
5418
- background: withAlpha(slateGrey[1], 0.6),
5419
- blur: "blur(24px)",
5420
- border: "none",
5421
- width: "clamp(380px, 25vw, 520px)",
5422
- transitionDuration: "300ms",
5423
- transitionEasing: "cubic-bezier(0.16, 1, 0.3, 1)",
5424
- transitionFade: "6%"
5425
- },
5426
- launcher: {
5427
- background: button.primary.backgroundDefault,
5428
- backgroundHover: button.primary.backgroundHover,
5429
- color: button.primary.icon,
5430
- size: "56px",
5431
- shadow: `0 8px 32px ${withAlpha(slateGrey[0], 0.6)}`,
5432
- borderRadius: "9999px"
5433
- },
5434
- tile: {
5435
- background: withAlpha(slateGrey[1], 0.6),
5436
- backgroundHover: withAlpha(slateGrey[1], 0.7),
5437
- border: "1px solid rgba(255, 255, 255, 0.08)",
5438
- borderRadius: "14px",
5439
- shadow: "0 2px 12px rgba(0, 0, 0, 0.3)",
5440
- titleColor: text.primary,
5441
- textColor: text.secondary,
5442
- iconBackground: `linear-gradient(135deg, ${brand[3]} 0%, ${brand[3]}cc 100%)`,
5443
- iconShadow: `0 2px 8px ${brand[3]}40`,
5444
- headerPadding: "0.375rem 0.75rem",
5445
- bodyPadding: "0 0.75rem 0.5rem",
5446
- gap: "0.25rem"
5447
- },
5448
- overlay: {
5449
- background: withAlpha(slateGrey[1], 0.6),
5450
- textColor: text.primary,
5451
- titleColor: text.primary,
5452
- arrowColor: withAlpha(slateGrey[1], 0.6),
5453
- arrowSize: "8px",
5454
- border: "none",
5455
- borderRadius: "0",
5456
- scrimOpacity: "0",
5457
- highlightRing: `2px solid ${brand[3]}`
5458
- },
5459
- notification: {
5460
- background: withAlpha(slateGrey[0], 0.95),
5461
- textColor: text.primary,
5462
- textSecondaryColor: text.secondary,
5463
- border: `1px solid ${slateGrey[5]}`,
5464
- borderRadius: "12px",
5465
- successColor: green[4],
5466
- warningColor: yellow[4],
5467
- errorColor: red[4],
5468
- iconBackground: withAlpha(brand[3], 0.15),
5469
- progressGradient: `linear-gradient(90deg, ${brand[3]}, ${brand[4]})`
5470
- },
5471
- content: {
5472
- background: withAlpha(slateGrey[3], 0.8),
5473
- backgroundHover: withAlpha(slateGrey[5], 0.6),
5474
- border: `1px solid ${withAlpha(slateGrey[5], 0.5)}`,
5475
- borderRadius: "8px",
5476
- textColor: text.primary,
5477
- textSecondaryColor: text.secondary,
5478
- itemDivider: "none",
5479
- itemGap: "6px",
5480
- itemPadding: "12px 16px",
5481
- itemFontSize: "15px",
5482
- bodyPadding: "0 16px 12px 16px",
5483
- bodyFontSize: "14px",
5484
- categoryPadding: "8px 4px 4px 4px",
5485
- categoryGap: "4px",
5486
- categoryFontSize: "12px",
5487
- searchBackground: withAlpha(slateGrey[3], 0.8),
5488
- searchColor: text.primary,
5489
- chevronColor: "currentColor"
5490
- }
5491
- };
5492
- var lightDefaults = {
5493
- mode: "light",
5494
- fontFamily: "-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif",
5495
- colorPrimary: brand[3],
5496
- colorPrimaryHover: brand[2],
5497
- borderRadius: "12px",
5498
- canvas: {
5499
- position: "right",
5500
- layout: "overlay",
5501
- background: withAlpha(slateGrey[12], 0.7),
5502
- blur: "blur(24px)",
5503
- border: "none",
5504
- width: "clamp(380px, 25vw, 520px)",
5505
- transitionDuration: "300ms",
5506
- transitionEasing: "cubic-bezier(0.16, 1, 0.3, 1)",
5507
- transitionFade: "6%"
5508
- },
5509
- launcher: {
5510
- background: brand[3],
5511
- backgroundHover: brand[2],
5512
- color: "#ffffff",
5513
- size: "56px",
5514
- shadow: "0 8px 32px rgba(0, 0, 0, 0.15)",
5515
- borderRadius: "9999px"
5516
- },
5517
- tile: {
5518
- background: withAlpha(slateGrey[12], 0.7),
5519
- backgroundHover: withAlpha(slateGrey[12], 0.8),
5520
- border: "1px solid rgba(0, 0, 0, 0.06)",
5521
- borderRadius: "14px",
5522
- shadow: "0 2px 12px rgba(0, 0, 0, 0.12)",
5523
- titleColor: slateGrey[1],
5524
- textColor: slateGrey[6],
5525
- iconBackground: `linear-gradient(135deg, ${brand[3]} 0%, ${brand[3]}cc 100%)`,
5526
- iconShadow: `0 2px 8px ${brand[3]}40`,
5527
- headerPadding: "0.375rem 0.75rem",
5528
- bodyPadding: "0 0.75rem 0.5rem",
5529
- gap: "0.25rem"
5530
- },
5531
- overlay: {
5532
- background: withAlpha(slateGrey[12], 0.7),
5533
- textColor: slateGrey[1],
5534
- titleColor: slateGrey[1],
5535
- arrowColor: withAlpha(slateGrey[12], 0.7),
5536
- arrowSize: "8px",
5537
- border: "none",
5538
- borderRadius: "0",
5539
- scrimOpacity: "0",
5540
- highlightRing: `2px solid ${brand[3]}`
5541
- },
5542
- notification: {
5543
- background: withAlpha(slateGrey[12], 0.95),
5544
- textColor: slateGrey[1],
5545
- textSecondaryColor: slateGrey[6],
5546
- border: `1px solid ${withAlpha(slateGrey[0], 0.12)}`,
5547
- borderRadius: "12px",
5548
- successColor: green[4],
5549
- warningColor: yellow[4],
5550
- errorColor: red[4],
5551
- iconBackground: withAlpha(brand[3], 0.1),
5552
- progressGradient: `linear-gradient(90deg, ${brand[3]}, ${brand[2]})`
5553
- },
5554
- content: {
5555
- background: withAlpha(slateGrey[12], 0.8),
5556
- backgroundHover: withAlpha(slateGrey[11], 0.6),
5557
- border: `1px solid ${slateGrey[11]}`,
5558
- borderRadius: "8px",
5559
- textColor: slateGrey[1],
5560
- textSecondaryColor: slateGrey[6],
5561
- itemDivider: "none",
5562
- itemGap: "6px",
5563
- itemPadding: "12px 16px",
5564
- itemFontSize: "15px",
5565
- bodyPadding: "0 16px 12px 16px",
5566
- bodyFontSize: "14px",
5567
- categoryPadding: "8px 4px 4px 4px",
5568
- categoryGap: "4px",
5569
- categoryFontSize: "12px",
5570
- searchBackground: slateGrey[12],
5571
- searchColor: slateGrey[1],
5572
- chevronColor: "currentColor"
5573
- }
5574
- };
5575
- function mergeThemeConfig(customer) {
5576
- var _a2, _b, _c, _d, _e;
5577
- const base2 = customer.mode === "light" ? lightDefaults : darkDefaults;
5578
- return {
5579
- mode: (_a2 = customer.mode) != null ? _a2 : base2.mode,
5580
- fontFamily: (_b = customer.fontFamily) != null ? _b : base2.fontFamily,
5581
- colorPrimary: (_c = customer.colorPrimary) != null ? _c : base2.colorPrimary,
5582
- colorPrimaryHover: (_d = customer.colorPrimaryHover) != null ? _d : base2.colorPrimaryHover,
5583
- borderRadius: (_e = customer.borderRadius) != null ? _e : base2.borderRadius,
5584
- canvas: { ...base2.canvas, ...customer.canvas },
5585
- launcher: { ...base2.launcher, ...customer.launcher },
5586
- tile: { ...base2.tile, ...customer.tile },
5587
- overlay: { ...base2.overlay, ...customer.overlay },
5588
- notification: { ...base2.notification, ...customer.notification },
5589
- content: { ...base2.content, ...customer.content }
5590
- };
5591
- }
5592
- function mergeThemeWithWorkspace(workspaceTheme, configTheme) {
5593
- var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5594
- const mode = (_b = (_a2 = configTheme.mode) != null ? _a2 : workspaceTheme.mode) != null ? _b : "dark";
5595
- const base2 = mode === "light" ? lightDefaults : darkDefaults;
5596
- return {
5597
- mode,
5598
- fontFamily: (_d = (_c = configTheme.fontFamily) != null ? _c : workspaceTheme.fontFamily) != null ? _d : base2.fontFamily,
5599
- colorPrimary: (_f = (_e = configTheme.colorPrimary) != null ? _e : workspaceTheme.colorPrimary) != null ? _f : base2.colorPrimary,
5600
- colorPrimaryHover: (_h = (_g = configTheme.colorPrimaryHover) != null ? _g : workspaceTheme.colorPrimaryHover) != null ? _h : base2.colorPrimaryHover,
5601
- borderRadius: (_j = (_i = configTheme.borderRadius) != null ? _i : workspaceTheme.borderRadius) != null ? _j : base2.borderRadius,
5602
- canvas: { ...base2.canvas, ...workspaceTheme.canvas, ...configTheme.canvas },
5603
- launcher: { ...base2.launcher, ...workspaceTheme.launcher, ...configTheme.launcher },
5604
- tile: { ...base2.tile, ...workspaceTheme.tile, ...configTheme.tile },
5605
- overlay: { ...base2.overlay, ...workspaceTheme.overlay, ...configTheme.overlay },
5606
- notification: {
5607
- ...base2.notification,
5608
- ...workspaceTheme.notification,
5609
- ...configTheme.notification
5610
- },
5611
- content: { ...base2.content, ...workspaceTheme.content, ...configTheme.content }
5612
- };
5613
- }
5614
- var ELEMENT_SECTIONS = [
5615
- "canvas",
5616
- "launcher",
5617
- "tile",
5618
- "overlay",
5619
- "notification",
5620
- "content"
5621
- ];
5622
- function flattenThemeConfig(config) {
5623
- const vars = {};
5624
- if (config.fontFamily) vars["--sc-font-family"] = config.fontFamily;
5625
- if (config.colorPrimary) vars["--sc-color-primary"] = config.colorPrimary;
5626
- if (config.colorPrimaryHover) vars["--sc-color-primary-hover"] = config.colorPrimaryHover;
5627
- if (config.borderRadius) vars["--sc-border-radius"] = config.borderRadius;
5628
- for (const section of ELEMENT_SECTIONS) {
5629
- const sectionConfig = config[section];
5630
- if (!sectionConfig) continue;
5631
- for (const [key, value] of Object.entries(sectionConfig)) {
5632
- if (value !== void 0) {
5633
- vars[`--sc-${section}-${kebabCase(key)}`] = value;
5634
- }
5635
- }
5636
- }
5637
- return vars;
5638
- }
5639
-
5640
- // src/theme/ThemeProvider.tsx
5641
- import { createContext as createContext3, useContext as useContext3, useEffect as useEffect6, useMemo as useMemo4 } from "react";
5642
- import { jsx as jsx7 } from "react/jsx-runtime";
5643
- var ThemeContext = createContext3(null);
5644
- function ThemeProvider({
5645
- children,
5646
- themeConfig,
5647
- workspaceTheme,
5648
- shadowRoot
5649
- }) {
5650
- const merged = useMemo4(
5651
- () => workspaceTheme ? mergeThemeWithWorkspace(workspaceTheme, themeConfig != null ? themeConfig : {}) : mergeThemeConfig(themeConfig != null ? themeConfig : {}),
5652
- [themeConfig, workspaceTheme]
5653
- );
5654
- const cssVariables = useMemo4(() => flattenThemeConfig(merged), [merged]);
5655
- useEffect6(() => {
5656
- if (!shadowRoot) return;
5657
- let styleEl = shadowRoot.querySelector("#sc-theme-vars");
5658
- if (!styleEl) {
5659
- styleEl = document.createElement("style");
5660
- styleEl.id = "sc-theme-vars";
5661
- shadowRoot.insertBefore(styleEl, shadowRoot.firstChild);
5662
- }
5663
- const cssRules = Object.entries(cssVariables).map(([key, value2]) => ` ${key}: ${value2};`).join("\n");
5664
- styleEl.textContent = `:host {
5665
- ${cssRules}
5666
- }`;
5667
- }, [shadowRoot, cssVariables]);
5668
- const value = {
5669
- config: merged,
5670
- mode: merged.mode,
5671
- cssVariables
5672
- };
5673
- return /* @__PURE__ */ jsx7(ThemeContext.Provider, { value, children });
5674
- }
5675
- function useTheme() {
5676
- const context = useContext3(ThemeContext);
5677
- if (!context) {
5678
- throw new Error("useTheme must be used within a ThemeProvider");
5679
- }
5680
- return context;
5681
- }
5682
-
5683
- // src/components/ShadowCanvasOverlay.tsx
5684
- import { Fragment, jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
5517
+ import { Fragment, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
5685
5518
  var LAUNCHER_STYLES_ID = "syntro-launcher-styles";
5686
5519
  function ensureLauncherStyles(target, css) {
5687
5520
  if (target.querySelector(`#${LAUNCHER_STYLES_ID}`)) return;
@@ -5695,7 +5528,6 @@ function ShadowCanvasOverlay({
5695
5528
  onToggle,
5696
5529
  telemetry,
5697
5530
  launcherLabel: _launcherLabel = "Adaptives",
5698
- launcherIcon,
5699
5531
  launcherAnimate = false,
5700
5532
  launcherAnimationStyle: _launcherAnimationStyle = "pulse",
5701
5533
  notificationCount: _notificationCount,
@@ -5706,7 +5538,7 @@ function ShadowCanvasOverlay({
5706
5538
  canvasTitle,
5707
5539
  displayMode = "standard"
5708
5540
  }) {
5709
- var _a2, _b, _c, _d;
5541
+ var _a2, _b, _c, _d, _e;
5710
5542
  const [mounted, setMounted] = useState5(false);
5711
5543
  const [launcherPos, setLauncherPos] = useState5(null);
5712
5544
  const dragRef = useRef5(null);
@@ -5740,7 +5572,7 @@ function ShadowCanvasOverlay({
5740
5572
  },
5741
5573
  [runtime3, isOpen, onToggle, dismissNotification]
5742
5574
  );
5743
- const launcherCss = useMemo5(
5575
+ const launcherCss = useMemo4(
5744
5576
  () => `
5745
5577
  @keyframes syntro-launcher-pulse {
5746
5578
  0%, 100% {
@@ -5777,7 +5609,7 @@ function ShadowCanvasOverlay({
5777
5609
  `,
5778
5610
  [config.colorPrimary, config.colorPrimaryHover]
5779
5611
  );
5780
- useEffect7(() => {
5612
+ useEffect6(() => {
5781
5613
  if (!isOpen) return;
5782
5614
  tiles.forEach((tile) => {
5783
5615
  telemetry == null ? void 0 : telemetry.trackRectangleViewed(tile.id, "overlay");
@@ -5787,11 +5619,11 @@ function ShadowCanvasOverlay({
5787
5619
  }
5788
5620
  });
5789
5621
  }, [telemetry, runtime3, isOpen, tiles]);
5790
- useEffect7(() => {
5622
+ useEffect6(() => {
5791
5623
  setMounted(true);
5792
5624
  ensureLauncherStyles(shadowRoot, launcherCss);
5793
5625
  }, [shadowRoot, launcherCss]);
5794
- const toggle2 = useCallback4(() => {
5626
+ const toggle = useCallback4(() => {
5795
5627
  const next = !isOpen;
5796
5628
  if (next) {
5797
5629
  telemetry == null ? void 0 : telemetry.trackCanvasOpened("overlay");
@@ -5804,17 +5636,17 @@ function ShadowCanvasOverlay({
5804
5636
  }
5805
5637
  onToggle();
5806
5638
  }, [isOpen, telemetry, runtime3, onToggle]);
5807
- useEffect7(() => {
5639
+ useEffect6(() => {
5808
5640
  if (!isOpen) return;
5809
5641
  const handleOutsideClick = (e) => {
5810
5642
  const path = e.composedPath();
5811
5643
  if (containerRef.current && !path.includes(containerRef.current) && launcherRef.current && !path.includes(launcherRef.current)) {
5812
- toggle2();
5644
+ toggle();
5813
5645
  }
5814
5646
  };
5815
5647
  document.addEventListener("mousedown", handleOutsideClick);
5816
5648
  return () => document.removeEventListener("mousedown", handleOutsideClick);
5817
- }, [isOpen, toggle2]);
5649
+ }, [isOpen, toggle]);
5818
5650
  const onLauncherPointerDown = useCallback4((e) => {
5819
5651
  const rect = e.currentTarget.getBoundingClientRect();
5820
5652
  dragRef.current = {
@@ -5839,14 +5671,14 @@ function ShadowCanvasOverlay({
5839
5671
  }
5840
5672
  }, []);
5841
5673
  const onLauncherPointerUp = useCallback4(
5842
- (_e) => {
5674
+ (_e2) => {
5843
5675
  const drag = dragRef.current;
5844
5676
  dragRef.current = null;
5845
5677
  if (drag && !drag.dragged) {
5846
- toggle2();
5678
+ toggle();
5847
5679
  }
5848
5680
  },
5849
- [toggle2]
5681
+ [toggle]
5850
5682
  );
5851
5683
  const isFocused = displayMode === "focused";
5852
5684
  const isRight = config.canvas.position === "right";
@@ -5855,7 +5687,7 @@ function ShadowCanvasOverlay({
5855
5687
  const containerRef = useRef5(null);
5856
5688
  const launcherRef = useRef5(null);
5857
5689
  const zIndex = 2147483600;
5858
- useEffect7(() => {
5690
+ useEffect6(() => {
5859
5691
  var _a3, _b2, _c2, _d2;
5860
5692
  if (!isPush) return;
5861
5693
  const root = document.documentElement;
@@ -5875,7 +5707,7 @@ function ShadowCanvasOverlay({
5875
5707
  root.style.transition = prevTransition;
5876
5708
  };
5877
5709
  }, [isPush, isOpen, isRight, config.canvas.transitionDuration, config.canvas.transitionEasing]);
5878
- useEffect7(() => {
5710
+ useEffect6(() => {
5879
5711
  if (!isPush || !isOpen) return;
5880
5712
  const container = containerRef.current;
5881
5713
  if (!container) return;
@@ -5934,7 +5766,7 @@ function ShadowCanvasOverlay({
5934
5766
  pointerEvents: "none",
5935
5767
  padding: "0"
5936
5768
  };
5937
- const content = /* @__PURE__ */ jsx8(
5769
+ const content = /* @__PURE__ */ jsx7(
5938
5770
  "div",
5939
5771
  {
5940
5772
  "data-shadow-canvas-id": "overlay-root",
@@ -5946,7 +5778,7 @@ function ShadowCanvasOverlay({
5946
5778
  },
5947
5779
  children: /* @__PURE__ */ jsxs3("div", { style: wrapperStyle, children: [
5948
5780
  /* @__PURE__ */ jsxs3("div", { ref: containerRef, "data-shadow-canvas-id": "overlay-container", style: containerStyle, children: [
5949
- isFocused && canvasTitle && /* @__PURE__ */ jsx8("header", { style: { color: "white", padding: "1.5rem 1.5rem 0" }, children: /* @__PURE__ */ jsx8(
5781
+ isFocused && canvasTitle && /* @__PURE__ */ jsx7("header", { style: { color: "white", padding: "1.5rem 1.5rem 0" }, children: /* @__PURE__ */ jsx7(
5950
5782
  "p",
5951
5783
  {
5952
5784
  style: {
@@ -5959,7 +5791,7 @@ function ShadowCanvasOverlay({
5959
5791
  children: canvasTitle
5960
5792
  }
5961
5793
  ) }),
5962
- /* @__PURE__ */ jsx8("div", { style: { flex: 1, overflowY: "auto", padding: isFocused ? "0" : "1rem" }, children: isLoading ? /* @__PURE__ */ jsx8(
5794
+ /* @__PURE__ */ jsx7("div", { style: { flex: 1, overflowY: "auto", padding: isFocused ? "0" : "1rem" }, children: isLoading ? /* @__PURE__ */ jsx7(
5963
5795
  "div",
5964
5796
  {
5965
5797
  style: { color: "var(--sc-overlay-text-color)", padding: isFocused ? "1rem" : "0" },
@@ -5979,7 +5811,7 @@ function ShadowCanvasOverlay({
5979
5811
  }
5980
5812
  ) : isFocused ? (
5981
5813
  /* Focused Mode: Render first tile full size */
5982
- tiles.length > 0 ? /* @__PURE__ */ jsx8(
5814
+ tiles.length > 0 ? /* @__PURE__ */ jsx7(
5983
5815
  TileCard,
5984
5816
  {
5985
5817
  config: tiles[0],
@@ -5990,7 +5822,7 @@ function ShadowCanvasOverlay({
5990
5822
  ) : null
5991
5823
  ) : (
5992
5824
  /* Standard Mode: Stacked cards — widgets always visible */
5993
- /* @__PURE__ */ jsx8(
5825
+ /* @__PURE__ */ jsx7(
5994
5826
  "div",
5995
5827
  {
5996
5828
  style: {
@@ -5999,7 +5831,7 @@ function ShadowCanvasOverlay({
5999
5831
  gap: "0.75rem",
6000
5832
  width: "100%"
6001
5833
  },
6002
- children: tiles.map((tile) => /* @__PURE__ */ jsx8(
5834
+ children: tiles.map((tile) => /* @__PURE__ */ jsx7(
6003
5835
  TileCard,
6004
5836
  {
6005
5837
  config: tile,
@@ -6014,7 +5846,7 @@ function ShadowCanvasOverlay({
6014
5846
  ) }),
6015
5847
  footerSlot
6016
5848
  ] }),
6017
- /* @__PURE__ */ jsx8("div", { style: { flex: "1 1 auto" } })
5849
+ /* @__PURE__ */ jsx7("div", { style: { flex: "1 1 auto" } })
6018
5850
  ] })
6019
5851
  }
6020
5852
  );
@@ -6032,7 +5864,7 @@ function ShadowCanvasOverlay({
6032
5864
  zIndex: zIndex + 47
6033
5865
  },
6034
5866
  children: [
6035
- /* @__PURE__ */ jsx8(
5867
+ /* @__PURE__ */ jsx7(
6036
5868
  NotificationToastStack,
6037
5869
  {
6038
5870
  notifications,
@@ -6103,14 +5935,14 @@ function ShadowCanvasOverlay({
6103
5935
  focusable: "false",
6104
5936
  style: { transition: "transform 200ms ease" },
6105
5937
  children: [
6106
- /* @__PURE__ */ jsx8("path", { d: "M18 6L6 18" }),
6107
- /* @__PURE__ */ jsx8("path", { d: "M6 6l12 12" })
5938
+ /* @__PURE__ */ jsx7("path", { d: "M18 6L6 18" }),
5939
+ /* @__PURE__ */ jsx7("path", { d: "M6 6l12 12" })
6108
5940
  ]
6109
5941
  }
6110
- ) : launcherIcon ? /* @__PURE__ */ jsx8(
5942
+ ) : ((_e = config.launcher) == null ? void 0 : _e.icon) ? /* @__PURE__ */ jsx7(
6111
5943
  "img",
6112
5944
  {
6113
- src: launcherIcon,
5945
+ src: config.launcher.icon,
6114
5946
  alt: "",
6115
5947
  "aria-hidden": "true",
6116
5948
  style: {
@@ -6135,16 +5967,16 @@ function ShadowCanvasOverlay({
6135
5967
  focusable: "false",
6136
5968
  style: { transition: "transform 200ms ease" },
6137
5969
  children: [
6138
- /* @__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" }),
6139
- /* @__PURE__ */ jsx8("path", { d: "M5 3v4" }),
6140
- /* @__PURE__ */ jsx8("path", { d: "M3 5h4" }),
6141
- /* @__PURE__ */ jsx8("path", { d: "M19 17v4" }),
6142
- /* @__PURE__ */ jsx8("path", { d: "M17 19h4" })
5970
+ /* @__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" }),
5971
+ /* @__PURE__ */ jsx7("path", { d: "M5 3v4" }),
5972
+ /* @__PURE__ */ jsx7("path", { d: "M3 5h4" }),
5973
+ /* @__PURE__ */ jsx7("path", { d: "M19 17v4" }),
5974
+ /* @__PURE__ */ jsx7("path", { d: "M17 19h4" })
6143
5975
  ]
6144
5976
  }
6145
5977
  ),
6146
5978
  !isOpen && notifications.length > 0 && /* @__PURE__ */ jsxs3("div", { style: { position: "absolute", top: -2, right: -2, pointerEvents: "none" }, children: [
6147
- /* @__PURE__ */ jsx8(
5979
+ /* @__PURE__ */ jsx7(
6148
5980
  "span",
6149
5981
  {
6150
5982
  className: "syntro-badge-ping",
@@ -6156,7 +5988,7 @@ function ShadowCanvasOverlay({
6156
5988
  }
6157
5989
  }
6158
5990
  ),
6159
- /* @__PURE__ */ jsx8(
5991
+ /* @__PURE__ */ jsx7(
6160
5992
  "span",
6161
5993
  {
6162
5994
  className: "syntro-badge-glow",
@@ -6167,7 +5999,7 @@ function ShadowCanvasOverlay({
6167
5999
  }
6168
6000
  }
6169
6001
  ),
6170
- /* @__PURE__ */ jsx8(
6002
+ /* @__PURE__ */ jsx7(
6171
6003
  "span",
6172
6004
  {
6173
6005
  className: "syntro-badge-bounce",
@@ -6201,7 +6033,7 @@ function ShadowCanvasOverlay({
6201
6033
  }
6202
6034
 
6203
6035
  // src/hooks/useShadowCanvasConfig.ts
6204
- import { useCallback as useCallback5, useEffect as useEffect8, useMemo as useMemo6, useRef as useRef6, useState as useState6 } from "react";
6036
+ import { useCallback as useCallback5, useEffect as useEffect7, useMemo as useMemo5, useRef as useRef6, useState as useState6 } from "react";
6205
6037
  var sortTiles = (tiles) => [...tiles].sort((a, b) => {
6206
6038
  var _a2, _b;
6207
6039
  return ((_a2 = b.priority) != null ? _a2 : 0) - ((_b = a.priority) != null ? _b : 0);
@@ -6282,37 +6114,37 @@ function useShadowCanvasConfig({
6282
6114
  }));
6283
6115
  }
6284
6116
  }, [experiments, fetcher, runtime3]);
6285
- useEffect8(() => {
6117
+ useEffect7(() => {
6286
6118
  load();
6287
6119
  if (experiments == null ? void 0 : experiments.onFeaturesChanged) {
6288
6120
  return experiments.onFeaturesChanged(() => load());
6289
6121
  }
6290
6122
  }, [load, experiments, pageUrl]);
6291
- useEffect8(() => {
6123
+ useEffect7(() => {
6292
6124
  if (!(runtime3 == null ? void 0 : runtime3.accumulator)) return;
6293
6125
  return runtime3.accumulator.subscribe(() => {
6294
6126
  refilter();
6295
6127
  });
6296
6128
  }, [runtime3, refilter]);
6297
- useEffect8(() => {
6129
+ useEffect7(() => {
6298
6130
  if (!(runtime3 == null ? void 0 : runtime3.context)) return;
6299
6131
  return runtime3.context.subscribe(() => {
6300
6132
  refilter();
6301
6133
  });
6302
6134
  }, [runtime3, refilter]);
6303
- useEffect8(() => {
6135
+ useEffect7(() => {
6304
6136
  if (!pollIntervalMs) return;
6305
6137
  const id = setInterval(() => {
6306
6138
  load();
6307
6139
  }, pollIntervalMs);
6308
6140
  return () => clearInterval(id);
6309
6141
  }, [load, pollIntervalMs]);
6310
- return useMemo6(() => state, [state]);
6142
+ return useMemo5(() => state, [state]);
6311
6143
  }
6312
6144
 
6313
6145
  // src/SmartCanvasApp.tsx
6314
- import { useEffect as useEffect9, useMemo as useMemo7, useRef as useRef7, useState as useState7 } from "react";
6315
- import { jsx as jsx9 } from "react/jsx-runtime";
6146
+ import { useEffect as useEffect8, useMemo as useMemo6, useRef as useRef7, useState as useState7 } from "react";
6147
+ import { jsx as jsx8 } from "react/jsx-runtime";
6316
6148
  function SmartCanvasApp({
6317
6149
  controller,
6318
6150
  fetcher,
@@ -6335,7 +6167,7 @@ function SmartCanvasApp({
6335
6167
  workspaceTheme
6336
6168
  }) {
6337
6169
  if (runtime3) {
6338
- return /* @__PURE__ */ jsx9(RuntimeProvider, { runtime: runtime3, children: /* @__PURE__ */ jsx9(
6170
+ return /* @__PURE__ */ jsx8(RuntimeProvider, { runtime: runtime3, children: /* @__PURE__ */ jsx8(
6339
6171
  SmartCanvasAppInner,
6340
6172
  {
6341
6173
  controller,
@@ -6360,7 +6192,7 @@ function SmartCanvasApp({
6360
6192
  }
6361
6193
  ) });
6362
6194
  }
6363
- return /* @__PURE__ */ jsx9(
6195
+ return /* @__PURE__ */ jsx8(
6364
6196
  SmartCanvasAppInner,
6365
6197
  {
6366
6198
  controller,
@@ -6405,37 +6237,25 @@ function SmartCanvasAppInner({
6405
6237
  initialBatchHandle,
6406
6238
  workspaceTheme
6407
6239
  }) {
6408
- var _a2, _b, _c, _d, _e, _f, _g;
6240
+ var _a2, _b, _c, _d, _e, _f;
6409
6241
  const [open, setOpen] = useState7(controller.getState().open);
6410
6242
  const pageContext = usePageContext();
6411
6243
  const [localUrl, setLocalUrl] = useState7(
6412
6244
  () => typeof window !== "undefined" ? window.location.href : "/"
6413
6245
  );
6414
6246
  const pageUrl = (_a2 = pageContext == null ? void 0 : pageContext.url) != null ? _a2 : localUrl;
6415
- useEffect9(() => {
6247
+ useEffect8(() => {
6416
6248
  if (runtime3) return;
6417
6249
  if (typeof window === "undefined") return;
6418
6250
  const updateUrl = () => setLocalUrl(window.location.href);
6419
6251
  window.addEventListener("popstate", updateUrl);
6420
6252
  window.addEventListener("hashchange", updateUrl);
6421
- const originalPushState = history.pushState;
6422
- const originalReplaceState = history.replaceState;
6423
- history.pushState = function(...args) {
6424
- originalPushState.apply(this, args);
6425
- queueMicrotask(updateUrl);
6426
- };
6427
- history.replaceState = function(...args) {
6428
- originalReplaceState.apply(this, args);
6429
- queueMicrotask(updateUrl);
6430
- };
6431
6253
  return () => {
6432
6254
  window.removeEventListener("popstate", updateUrl);
6433
6255
  window.removeEventListener("hashchange", updateUrl);
6434
- history.pushState = originalPushState;
6435
- history.replaceState = originalReplaceState;
6436
6256
  };
6437
6257
  }, [runtime3]);
6438
- const derivedFetcher = useMemo7(() => {
6258
+ const derivedFetcher = useMemo6(() => {
6439
6259
  if (fetcher) return fetcher;
6440
6260
  return createCanvasConfigFetcher({
6441
6261
  configUri,
@@ -6452,8 +6272,8 @@ function SmartCanvasAppInner({
6452
6272
  pageUrl
6453
6273
  });
6454
6274
  const hasContent = configState.tiles.length > 0 && !configState.error;
6455
- useEffect9(() => controller.subscribe((state) => setOpen(state.open)), [controller]);
6456
- useEffect9(() => {
6275
+ useEffect8(() => controller.subscribe((state) => setOpen(state.open)), [controller]);
6276
+ useEffect8(() => {
6457
6277
  if (!configState.isLoading && !hasContent && controller.getState().open) {
6458
6278
  controller.setOpen(false);
6459
6279
  }
@@ -6461,7 +6281,8 @@ function SmartCanvasAppInner({
6461
6281
  const batchHandleRef = useRef7(initialBatchHandle != null ? initialBatchHandle : null);
6462
6282
  const adoptedInitialRef = useRef7(!!initialBatchHandle);
6463
6283
  const runVersionRef = useRef7(0);
6464
- useEffect9(() => {
6284
+ const pendingRevertRef = useRef7(null);
6285
+ useEffect8(() => {
6465
6286
  if (!(runtime3 == null ? void 0 : runtime3.actions)) return;
6466
6287
  if (adoptedInitialRef.current) {
6467
6288
  if (configState.actions.length > 0) {
@@ -6472,6 +6293,14 @@ function SmartCanvasAppInner({
6472
6293
  const version = ++runVersionRef.current;
6473
6294
  const stale = () => version !== runVersionRef.current;
6474
6295
  const run = async () => {
6296
+ if (pendingRevertRef.current) {
6297
+ try {
6298
+ await pendingRevertRef.current;
6299
+ } catch (err) {
6300
+ console.error("[SmartCanvasApp] Pending revert failed:", err);
6301
+ }
6302
+ pendingRevertRef.current = null;
6303
+ }
6475
6304
  if (batchHandleRef.current) {
6476
6305
  try {
6477
6306
  await batchHandleRef.current.revertAll();
@@ -6499,14 +6328,14 @@ function SmartCanvasAppInner({
6499
6328
  run();
6500
6329
  return () => {
6501
6330
  if (batchHandleRef.current) {
6502
- batchHandleRef.current.revertAll().catch((err) => {
6331
+ pendingRevertRef.current = batchHandleRef.current.revertAll().catch((err) => {
6503
6332
  console.error("[SmartCanvasApp] Failed to revert actions on cleanup:", err);
6504
6333
  });
6505
6334
  batchHandleRef.current = null;
6506
6335
  }
6507
6336
  };
6508
6337
  }, [runtime3, configState.actions, pageUrl]);
6509
- useEffect9(() => {
6338
+ useEffect8(() => {
6510
6339
  if (!runtime3) return;
6511
6340
  return runtime3.events.subscribe(
6512
6341
  { names: ["canvas.requestOpen"] },
@@ -6515,13 +6344,13 @@ function SmartCanvasAppInner({
6515
6344
  }, [runtime3, controller]);
6516
6345
  const { shadowRoot } = useShadowRoot();
6517
6346
  const themeConfig = configState.theme;
6518
- return /* @__PURE__ */ jsx9(
6347
+ return /* @__PURE__ */ jsx8(
6519
6348
  ThemeProvider,
6520
6349
  {
6521
6350
  themeConfig,
6522
6351
  workspaceTheme,
6523
6352
  shadowRoot,
6524
- children: !configState.isLoading && !hasContent ? null : /* @__PURE__ */ jsx9(
6353
+ children: !configState.isLoading && !hasContent ? null : /* @__PURE__ */ jsx8(
6525
6354
  ShadowCanvasOverlay,
6526
6355
  {
6527
6356
  tiles: configState.tiles,
@@ -6530,10 +6359,9 @@ function SmartCanvasAppInner({
6530
6359
  canvasTitle: configState.canvasTitle,
6531
6360
  telemetry,
6532
6361
  launcherLabel: launcherLabel != null ? launcherLabel : (_b = configState.launcher) == null ? void 0 : _b.label,
6533
- launcherIcon: (_c = configState.launcher) == null ? void 0 : _c.icon,
6534
- launcherAnimate: (_d = configState.launcher) == null ? void 0 : _d.animate,
6535
- launcherAnimationStyle: (_e = configState.launcher) == null ? void 0 : _e.animationStyle,
6536
- notificationCount: (_g = (_f = configState.launcher) == null ? void 0 : _f.notificationCount) != null ? _g : configState.tiles.length,
6362
+ launcherAnimate: (_c = configState.launcher) == null ? void 0 : _c.animate,
6363
+ launcherAnimationStyle: (_d = configState.launcher) == null ? void 0 : _d.animationStyle,
6364
+ notificationCount: (_f = (_e = configState.launcher) == null ? void 0 : _e.notificationCount) != null ? _f : configState.tiles.length,
6537
6365
  footerSlot,
6538
6366
  isOpen: open,
6539
6367
  onToggle: () => controller.toggle(),
@@ -6546,8 +6374,8 @@ function SmartCanvasAppInner({
6546
6374
 
6547
6375
  // src/SmartCanvasElement.tsx
6548
6376
  import { createRoot as createRoot2 } from "react-dom/client";
6549
- import { jsx as jsx10 } from "react/jsx-runtime";
6550
- var TAG_NAME = "smart-canvas";
6377
+ import { jsx as jsx9 } from "react/jsx-runtime";
6378
+ var TAG_NAME2 = "smart-canvas";
6551
6379
  var BASE_CSS = `
6552
6380
  :host {
6553
6381
  font: inherit;
@@ -6647,13 +6475,13 @@ var SmartCanvasElement = class extends HTMLElement {
6647
6475
  __privateSet(this, _root, createRoot2(__privateGet(this, _mount)));
6648
6476
  }
6649
6477
  __privateGet(this, _root).render(
6650
- /* @__PURE__ */ jsx10(
6478
+ /* @__PURE__ */ jsx9(
6651
6479
  ShadowRootProvider,
6652
6480
  {
6653
6481
  shadowRoot: __privateGet(this, _shadow),
6654
6482
  portalRoot: __privateGet(this, _portalRoot),
6655
6483
  overlayContainer: __privateGet(this, _overlayContainer),
6656
- children: /* @__PURE__ */ jsx10(SmartCanvasApp, { ...__privateGet(this, _lastAppProps), controller: __privateGet(this, _controller), canvasHost: this })
6484
+ children: /* @__PURE__ */ jsx9(SmartCanvasApp, { ...__privateGet(this, _lastAppProps), controller: __privateGet(this, _controller), canvasHost: this })
6657
6485
  }
6658
6486
  )
6659
6487
  );
@@ -6679,8 +6507,8 @@ _root = new WeakMap();
6679
6507
  _lastAppProps = new WeakMap();
6680
6508
  var registerSmartCanvasElement = () => {
6681
6509
  if (typeof window === "undefined") return;
6682
- if (!customElements.get(TAG_NAME)) {
6683
- customElements.define(TAG_NAME, SmartCanvasElement);
6510
+ if (!customElements.get(TAG_NAME2)) {
6511
+ customElements.define(TAG_NAME2, SmartCanvasElement);
6684
6512
  }
6685
6513
  };
6686
6514
 
@@ -6707,6 +6535,23 @@ function decodeParam(paramName) {
6707
6535
  return null;
6708
6536
  }
6709
6537
  }
6538
+ var STORAGE_KEY_SOURCE = "__syntro_rt_editor_source";
6539
+ var STORAGE_KEY_CONF = "__syntro_rt_editor_conf";
6540
+ function persistToStorage(key, value) {
6541
+ try {
6542
+ sessionStorage.setItem(key, JSON.stringify(value));
6543
+ } catch {
6544
+ }
6545
+ }
6546
+ function readFromStorage(key) {
6547
+ try {
6548
+ const raw = sessionStorage.getItem(key);
6549
+ if (!raw) return null;
6550
+ return JSON.parse(raw);
6551
+ } catch {
6552
+ return null;
6553
+ }
6554
+ }
6710
6555
  var _cachedSource;
6711
6556
  var _cachedConf;
6712
6557
  function getEditorSource() {
@@ -6715,6 +6560,7 @@ function getEditorSource() {
6715
6560
  const globalParams = typeof window !== "undefined" ? window.__SYNTRO_EDITOR_PARAMS__ : null;
6716
6561
  if (globalParams == null ? void 0 : globalParams.token) {
6717
6562
  _cachedSource = { token: globalParams.token, api_base: globalParams.apiBase || "" };
6563
+ persistToStorage(STORAGE_KEY_SOURCE, _cachedSource);
6718
6564
  console.log(
6719
6565
  `[DIAG] getEditorSource: from __SYNTRO_EDITOR_PARAMS__ (token=${_cachedSource.token.slice(0, 15)}...)`
6720
6566
  );
@@ -6722,6 +6568,15 @@ function getEditorSource() {
6722
6568
  const decoded = decodeParam("editor_source");
6723
6569
  if (decoded) {
6724
6570
  _cachedSource = decoded;
6571
+ persistToStorage(STORAGE_KEY_SOURCE, decoded);
6572
+ } else {
6573
+ const fromStorage = readFromStorage(STORAGE_KEY_SOURCE);
6574
+ if (fromStorage == null ? void 0 : fromStorage.token) {
6575
+ _cachedSource = fromStorage;
6576
+ console.log(
6577
+ `[DIAG] getEditorSource: restored from sessionStorage (token=${fromStorage.token.slice(0, 15)}...)`
6578
+ );
6579
+ }
6725
6580
  }
6726
6581
  console.log(
6727
6582
  `[DIAG] getEditorSource: from URL param \u2192 ${decoded ? `token=${(_a2 = decoded.token) == null ? void 0 : _a2.slice(0, 15)}...` : "NULL"}`
@@ -6743,11 +6598,21 @@ function getEditorConf() {
6743
6598
  syntro_token: globalParams.syntroToken,
6744
6599
  workspace_id: globalParams.workspaceId
6745
6600
  };
6601
+ persistToStorage(STORAGE_KEY_CONF, _cachedConf);
6746
6602
  console.log(`[DIAG] getEditorConf: from __SYNTRO_EDITOR_PARAMS__ (mode=${_cachedConf.mode})`);
6747
6603
  } else {
6748
6604
  const decoded = decodeParam("editor_conf");
6749
6605
  if (decoded) {
6750
6606
  _cachedConf = decoded;
6607
+ persistToStorage(STORAGE_KEY_CONF, decoded);
6608
+ } else {
6609
+ const fromStorage = readFromStorage(STORAGE_KEY_CONF);
6610
+ if (fromStorage == null ? void 0 : fromStorage.mode) {
6611
+ _cachedConf = fromStorage;
6612
+ console.log(
6613
+ `[DIAG] getEditorConf: restored from sessionStorage (mode=${fromStorage.mode})`
6614
+ );
6615
+ }
6751
6616
  }
6752
6617
  console.log(
6753
6618
  `[DIAG] getEditorConf: from URL param \u2192 ${decoded ? `mode=${decoded.mode}` : "NULL"}`
@@ -6830,18 +6695,13 @@ var loadEditorSdk = async (editorUrlOrOptions) => {
6830
6695
  return;
6831
6696
  }
6832
6697
  const token = getToken();
6833
- if (!token) {
6834
- warn("Syntro Runtime", "\u274C No token found in editor_source.");
6835
- debug("Syntro Runtime", "================================");
6836
- return;
6837
- }
6838
- const editorUrl = `${baseEditorUrl}?token=${encodeURIComponent(token)}`;
6698
+ const editorUrl = token ? `${baseEditorUrl}?token=${encodeURIComponent(token)}` : baseEditorUrl;
6839
6699
  debug("Syntro Runtime", "Editor URL:", editorUrl);
6840
6700
  debug("Syntro Runtime", "Options:", {
6841
6701
  hasIntegrity: !!options.integrity,
6842
6702
  hasEditorUrl: !!baseEditorUrl,
6843
6703
  hasApiBase: !!apiBase,
6844
- tokenPrefix: `${token.slice(0, 10)}...`
6704
+ tokenPrefix: token ? `${token.slice(0, 10)}...` : "none"
6845
6705
  });
6846
6706
  if (!validateEditorUrl(baseEditorUrl)) {
6847
6707
  console.error("[Syntro Runtime] \u274C BLOCKED: Editor from untrusted URL:", baseEditorUrl);
@@ -7463,6 +7323,7 @@ var STORAGE_KEY = "syntro_session_metrics";
7463
7323
  var SessionMetricTracker = class {
7464
7324
  constructor(options = {}) {
7465
7325
  __publicField(this, "metrics", /* @__PURE__ */ new Map());
7326
+ __publicField(this, "subscribers", /* @__PURE__ */ new Set());
7466
7327
  __publicField(this, "experiments");
7467
7328
  __publicField(this, "attributePrefix");
7468
7329
  __publicField(this, "onMetricChange");
@@ -7487,6 +7348,7 @@ var SessionMetricTracker = class {
7487
7348
  this.saveToStorage();
7488
7349
  this.updateExperimentAttributes(metricKey, newValue);
7489
7350
  (_b = this.onMetricChange) == null ? void 0 : _b.call(this, metricKey, newValue);
7351
+ this.notifySubscribers();
7490
7352
  return newValue;
7491
7353
  }
7492
7354
  /**
@@ -7501,6 +7363,7 @@ var SessionMetricTracker = class {
7501
7363
  this.saveToStorage();
7502
7364
  this.updateExperimentAttributes(metricKey, value);
7503
7365
  (_a2 = this.onMetricChange) == null ? void 0 : _a2.call(this, metricKey, value);
7366
+ this.notifySubscribers();
7504
7367
  }
7505
7368
  /**
7506
7369
  * Get the current value of a metric.
@@ -7541,6 +7404,7 @@ var SessionMetricTracker = class {
7541
7404
  this.saveToStorage();
7542
7405
  this.updateExperimentAttributes(metricKey, 0);
7543
7406
  (_a2 = this.onMetricChange) == null ? void 0 : _a2.call(this, metricKey, 0);
7407
+ this.notifySubscribers();
7544
7408
  }
7545
7409
  /**
7546
7410
  * Reset all metrics (clear the session).
@@ -7556,6 +7420,16 @@ var SessionMetricTracker = class {
7556
7420
  (_a2 = this.onMetricChange) == null ? void 0 : _a2.call(this, key, 0);
7557
7421
  }
7558
7422
  (_c = (_b = this.experiments) == null ? void 0 : _b.setAttributes) == null ? void 0 : _c.call(_b, attrs);
7423
+ this.notifySubscribers();
7424
+ }
7425
+ subscribe(callback) {
7426
+ this.subscribers.add(callback);
7427
+ return () => {
7428
+ this.subscribers.delete(callback);
7429
+ };
7430
+ }
7431
+ destroy() {
7432
+ this.subscribers.clear();
7559
7433
  }
7560
7434
  /**
7561
7435
  * Update the experiment client (useful if experiments client changes).
@@ -7580,6 +7454,14 @@ var SessionMetricTracker = class {
7580
7454
  }
7581
7455
  this.experiments.setAttributes(attrs);
7582
7456
  }
7457
+ notifySubscribers() {
7458
+ for (const cb of this.subscribers) {
7459
+ try {
7460
+ cb();
7461
+ } catch {
7462
+ }
7463
+ }
7464
+ }
7583
7465
  loadFromStorage() {
7584
7466
  if (typeof window === "undefined" || typeof sessionStorage === "undefined") return;
7585
7467
  try {
@@ -7711,8 +7593,10 @@ var PostHogAdapter = class {
7711
7593
  if (!options.apiKey) return;
7712
7594
  const enableFeatureFlags = (_a2 = options.enableFeatureFlags) != null ? _a2 : true;
7713
7595
  const instanceName = `syntro_${options.apiKey.slice(-6) || "sdk"}`;
7596
+ const baseHost = (_b = options.apiHost) != null ? _b : "https://telemetry.syntrologie.com";
7597
+ const apiHost = `${baseHost.replace(/\/$/, "")}/t/${options.apiKey}`;
7714
7598
  const initOptions = {
7715
- api_host: (_b = options.apiHost) != null ? _b : "https://telemetry.syntrologie.com",
7599
+ api_host: apiHost,
7716
7600
  // Feature flags for segment membership (in_segment_* flags)
7717
7601
  // When enabled, /decide is called to get segment flags
7718
7602
  advanced_disable_feature_flags: !enableFeatureFlags,
@@ -7733,33 +7617,7 @@ var PostHogAdapter = class {
7733
7617
  // Capture performance metrics
7734
7618
  capture_performance: true,
7735
7619
  // Enable web vitals
7736
- enable_recording_console_log: true,
7737
- // Bootstrap callback for when flags are loaded
7738
- loaded: (ph) => {
7739
- if (enableFeatureFlags && this.featureFlagsCallback) {
7740
- ph.onFeatureFlags(() => {
7741
- const allFlags = this.getAllFeatureFlags();
7742
- if (allFlags && this.featureFlagsCallback) {
7743
- this.featureFlagsCallback(allFlags);
7744
- }
7745
- });
7746
- const existingFlags = this.getAllFeatureFlags();
7747
- if (existingFlags && Object.keys(existingFlags).length > 0) {
7748
- this.featureFlagsCallback(existingFlags);
7749
- }
7750
- }
7751
- if (this.captureCallback) {
7752
- ph.on("eventCaptured", (...args) => {
7753
- var _a3;
7754
- const data = args[0];
7755
- const eventName = typeof data === "string" ? data : data == null ? void 0 : data.event;
7756
- const properties = typeof data === "string" ? void 0 : data == null ? void 0 : data.properties;
7757
- if (typeof eventName === "string") {
7758
- (_a3 = this.captureCallback) == null ? void 0 : _a3.call(this, eventName, properties);
7759
- }
7760
- });
7761
- }
7762
- }
7620
+ enable_recording_console_log: true
7763
7621
  };
7764
7622
  const result = posthog.init(
7765
7623
  options.apiKey,
@@ -7769,6 +7627,29 @@ var PostHogAdapter = class {
7769
7627
  if (result) {
7770
7628
  this.client = result;
7771
7629
  }
7630
+ if (this.captureCallback && this.client) {
7631
+ this.client.on("eventCaptured", (...args) => {
7632
+ var _a3;
7633
+ const data = args[0];
7634
+ const eventName = typeof data === "string" ? data : data == null ? void 0 : data.event;
7635
+ const properties = typeof data === "string" ? void 0 : data == null ? void 0 : data.properties;
7636
+ if (typeof eventName === "string") {
7637
+ (_a3 = this.captureCallback) == null ? void 0 : _a3.call(this, eventName, properties);
7638
+ }
7639
+ });
7640
+ }
7641
+ if (enableFeatureFlags && this.featureFlagsCallback && this.client) {
7642
+ this.client.onFeatureFlags(() => {
7643
+ const allFlags = this.getAllFeatureFlags();
7644
+ if (allFlags && this.featureFlagsCallback) {
7645
+ this.featureFlagsCallback(allFlags);
7646
+ }
7647
+ });
7648
+ const existingFlags = this.getAllFeatureFlags();
7649
+ if (existingFlags && Object.keys(existingFlags).length > 0) {
7650
+ this.featureFlagsCallback(existingFlags);
7651
+ }
7652
+ }
7772
7653
  if (this.rrwebCallback && this.client) {
7773
7654
  this.setupRRWebIntercept();
7774
7655
  }
@@ -8917,39 +8798,41 @@ function createActionEngine(options) {
8917
8798
  function subscribeForReeval(id, action, triggerWhen, _handle) {
8918
8799
  if (!runtime3) return;
8919
8800
  const unsubs = [];
8801
+ let reevalInFlight = false;
8920
8802
  const onReeval = async () => {
8803
+ if (reevalInFlight) return;
8921
8804
  const entry = activeActions.get(id);
8922
8805
  if (!entry) return;
8923
- const result = runtime3.evaluateSync(triggerWhen);
8924
- const shouldApply = result.value;
8925
- if (entry.state === "applied" && !shouldApply) {
8926
- try {
8927
- await entry.cleanup();
8928
- } catch (error2) {
8929
- console.error(`[ActionEngine] Error reverting conditional action ${id}:`, error2);
8930
- }
8931
- entry.state = "deferred";
8932
- entry.cleanup = () => {
8933
- };
8934
- entry.updateFn = void 0;
8935
- publishEvent("action.deferred", { id, kind: action.kind });
8936
- } else if (entry.state === "deferred" && shouldApply) {
8937
- try {
8938
- const context = createExecutorContext();
8939
- const execResult = await executeAction(action, context);
8940
- entry.state = "applied";
8941
- entry.cleanup = execResult.cleanup;
8942
- entry.updateFn = execResult.updateFn;
8943
- entry.appliedTs = Date.now();
8944
- publishEvent("action.applied", {
8945
- id,
8946
- kind: action.kind,
8947
- anchorId: "anchorId" in action ? action.anchorId : void 0
8948
- });
8949
- } catch (error2) {
8950
- console.error(`[ActionEngine] Error applying deferred action ${id}:`, error2);
8951
- entry.state = "failed";
8806
+ reevalInFlight = true;
8807
+ try {
8808
+ const result = runtime3.evaluateSync(triggerWhen);
8809
+ const shouldApply = result.value;
8810
+ if (entry.state === "applied" && !shouldApply) {
8811
+ try {
8812
+ await entry.cleanup();
8813
+ } catch (error2) {
8814
+ console.error(`[ActionEngine] Error reverting conditional action ${id}:`, error2);
8815
+ }
8816
+ entry.state = "deferred";
8817
+ entry.cleanup = () => {
8818
+ };
8819
+ entry.updateFn = void 0;
8820
+ publishEvent("action.deferred", { id, kind: action.kind });
8821
+ } else if (entry.state === "deferred" && shouldApply) {
8822
+ try {
8823
+ const context = createExecutorContext();
8824
+ const execResult = await executeAction(action, context);
8825
+ entry.state = "applied";
8826
+ entry.cleanup = execResult.cleanup;
8827
+ entry.updateFn = execResult.updateFn;
8828
+ entry.appliedTs = Date.now();
8829
+ } catch (error2) {
8830
+ console.error(`[ActionEngine] Error applying deferred action ${id}:`, error2);
8831
+ entry.state = "failed";
8832
+ }
8952
8833
  }
8834
+ } finally {
8835
+ reevalInFlight = false;
8953
8836
  }
8954
8837
  };
8955
8838
  if (runtime3.context) {
@@ -8958,6 +8841,12 @@ function createActionEngine(options) {
8958
8841
  if (runtime3.accumulator) {
8959
8842
  unsubs.push(runtime3.accumulator.subscribe(onReeval));
8960
8843
  }
8844
+ if (runtime3.sessionMetrics) {
8845
+ unsubs.push(runtime3.sessionMetrics.subscribe(onReeval));
8846
+ }
8847
+ if (runtime3.events) {
8848
+ unsubs.push(runtime3.events.subscribe(onReeval));
8849
+ }
8961
8850
  conditionalUnsubs.set(id, unsubs);
8962
8851
  }
8963
8852
  async function apply(action) {
@@ -9037,11 +8926,6 @@ function createActionEngine(options) {
9037
8926
  updateFn: result.updateFn
9038
8927
  };
9039
8928
  activeActions.set(id, entry);
9040
- publishEvent("action.applied", {
9041
- id,
9042
- kind: action.kind,
9043
- anchorId: "anchorId" in action ? action.anchorId : void 0
9044
- });
9045
8929
  const handle = {
9046
8930
  id,
9047
8931
  action,
@@ -9113,15 +8997,30 @@ function createActionEngine(options) {
9113
8997
  const handles = [];
9114
8998
  const appliedHandles = [];
9115
8999
  try {
9116
- for (const action of actions) {
9117
- const handle = await apply(action);
9118
- handles.push(handle);
9119
- appliedHandles.push(handle);
9000
+ const results = await Promise.allSettled(actions.map((action) => apply(action)));
9001
+ const errors = [];
9002
+ for (const result of results) {
9003
+ if (result.status === "fulfilled") {
9004
+ handles.push(result.value);
9005
+ appliedHandles.push(result.value);
9006
+ } else {
9007
+ errors.push(
9008
+ result.reason instanceof Error ? result.reason : new Error(String(result.reason))
9009
+ );
9010
+ }
9011
+ }
9012
+ if (errors.length > 0 && appliedHandles.length === 0) {
9013
+ throw errors[0];
9014
+ }
9015
+ if (errors.length > 0) {
9016
+ console.warn(
9017
+ `[ActionEngine] ${errors.length}/${actions.length} action(s) failed in batch:`,
9018
+ errors.map((e) => e.message).join("; ")
9019
+ );
9120
9020
  }
9121
9021
  } catch (error2) {
9122
9022
  console.error(
9123
- `[ActionEngine] Batch apply FAILED at action ${appliedHandles.length + 1}/${actions.length}.`,
9124
- `Successfully applied: ${appliedHandles.length}. Rolling back...`,
9023
+ `[ActionEngine] Batch apply FAILED. Successfully applied: ${appliedHandles.length}. Rolling back...`,
9125
9024
  error2
9126
9025
  );
9127
9026
  for (const handle of appliedHandles) {
@@ -9162,7 +9061,7 @@ function createActionEngine(options) {
9162
9061
  state: entry.state
9163
9062
  }));
9164
9063
  }
9165
- function destroy() {
9064
+ async function destroy() {
9166
9065
  for (const unsubs of conditionalUnsubs.values()) {
9167
9066
  for (const unsub of unsubs) {
9168
9067
  try {
@@ -9172,16 +9071,27 @@ function createActionEngine(options) {
9172
9071
  }
9173
9072
  }
9174
9073
  conditionalUnsubs.clear();
9074
+ const cleanupPromises = [];
9175
9075
  for (const entry of activeActions.values()) {
9176
9076
  if (entry.state === "applied") {
9177
9077
  try {
9178
- entry.cleanup();
9078
+ const result = entry.cleanup();
9079
+ if (result && typeof result.then === "function") {
9080
+ cleanupPromises.push(
9081
+ result.catch((error2) => {
9082
+ console.error(`[ActionEngine] Error during async cleanup:`, error2);
9083
+ })
9084
+ );
9085
+ }
9179
9086
  } catch (error2) {
9180
9087
  console.error(`[ActionEngine] Error during cleanup:`, error2);
9181
9088
  }
9182
9089
  }
9183
9090
  }
9184
9091
  activeActions.clear();
9092
+ if (cleanupPromises.length > 0) {
9093
+ await Promise.all(cleanupPromises);
9094
+ }
9185
9095
  }
9186
9096
  return {
9187
9097
  apply,
@@ -9595,8 +9505,8 @@ function evaluateCondition(condition, evalContext) {
9595
9505
  return true;
9596
9506
  }
9597
9507
  case "session_metric": {
9598
- if (!state) return false;
9599
- const metricValue = state.getSessionMetric(condition.key);
9508
+ const metricValue = evalContext.sessionMetrics ? evalContext.sessionMetrics.get(condition.key) : state == null ? void 0 : state.getSessionMetric(condition.key);
9509
+ if (metricValue === void 0) return false;
9600
9510
  const { operator, threshold } = condition;
9601
9511
  switch (operator) {
9602
9512
  case "gte":
@@ -9731,6 +9641,10 @@ function createEvaluationContext(context, options) {
9731
9641
  return (_a2 = state.session.get(key)) != null ? _a2 : state.user.get(key);
9732
9642
  }
9733
9643
  } : void 0,
9644
+ sessionMetrics: sessionMetrics ? { get: (key) => {
9645
+ var _a2;
9646
+ return (_a2 = sessionMetrics.get(key)) != null ? _a2 : 0;
9647
+ } } : void 0,
9734
9648
  events: events ? {
9735
9649
  hasRecentEvent: (eventName, withinMs) => events.hasRecentEvent(eventName, withinMs)
9736
9650
  } : void 0,
@@ -10701,13 +10615,13 @@ function getSlotZIndex(slot) {
10701
10615
  }
10702
10616
 
10703
10617
  // src/hostPatcher/core/sanitizer.ts
10704
- function sanitizeWithFallback(html) {
10618
+ function sanitizeWithFallback(html2) {
10705
10619
  var _a2;
10706
10620
  const hasNative = typeof window.Sanitizer === "function";
10707
10621
  if (hasNative) {
10708
10622
  try {
10709
10623
  const s = new window.Sanitizer({});
10710
- const frag = s.sanitizeToFragment(html);
10624
+ const frag = s.sanitizeToFragment(html2);
10711
10625
  const div = document.createElement("div");
10712
10626
  div.append(frag);
10713
10627
  return div.innerHTML;
@@ -10715,7 +10629,7 @@ function sanitizeWithFallback(html) {
10715
10629
  }
10716
10630
  }
10717
10631
  const tpl = document.createElement("template");
10718
- tpl.innerHTML = html;
10632
+ tpl.innerHTML = html2;
10719
10633
  const root = tpl.content;
10720
10634
  const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, null);
10721
10635
  const allowed = /* @__PURE__ */ new Set([
@@ -10742,8 +10656,8 @@ function sanitizeWithFallback(html) {
10742
10656
  const toRemove = [];
10743
10657
  while (walker.nextNode()) {
10744
10658
  const el = walker.currentNode;
10745
- const tag2 = el.tagName.toLowerCase();
10746
- if (!allowed.has(tag2)) {
10659
+ const tag = el.tagName.toLowerCase();
10660
+ if (!allowed.has(tag)) {
10747
10661
  toRemove.push(el);
10748
10662
  continue;
10749
10663
  }
@@ -11364,12 +11278,15 @@ function createSmartCanvasRuntime(options = {}) {
11364
11278
  runtime: {
11365
11279
  evaluateSync: (strategy) => decisionEngine.evaluateSync(strategy, context.get()),
11366
11280
  context,
11367
- accumulator
11281
+ accumulator,
11282
+ sessionMetrics,
11283
+ events: events ? { subscribe: (cb) => events.subscribe(() => cb()) } : void 0
11368
11284
  }
11369
11285
  });
11370
11286
  let unsubPageViews;
11371
11287
  if (sessionMetrics) {
11372
- sessionMetrics.increment("page_views");
11288
+ const sm = sessionMetrics;
11289
+ sm.increment("page_views");
11373
11290
  let lastCountedPath = typeof window !== "undefined" ? window.location.pathname : "/";
11374
11291
  unsubPageViews = navigation.subscribe((url, method) => {
11375
11292
  if (method === "replaceState") return;
@@ -11377,12 +11294,38 @@ function createSmartCanvasRuntime(options = {}) {
11377
11294
  const newPath = new URL(url).pathname;
11378
11295
  if (newPath !== lastCountedPath) {
11379
11296
  lastCountedPath = newPath;
11380
- sessionMetrics.increment("page_views");
11297
+ sm.increment("page_views");
11298
+ timeOnPageSeconds = 0;
11299
+ sm.set("time_on_page", 0);
11300
+ sm.set("scroll_depth", 0);
11381
11301
  }
11382
11302
  } catch {
11383
11303
  }
11384
11304
  });
11385
11305
  }
11306
+ let timeOnPageSeconds = 0;
11307
+ let timeOnPageTickInterval;
11308
+ let timeOnPageFlushInterval;
11309
+ if (sessionMetrics) {
11310
+ const sm = sessionMetrics;
11311
+ timeOnPageTickInterval = setInterval(() => {
11312
+ timeOnPageSeconds++;
11313
+ }, 1e3);
11314
+ timeOnPageFlushInterval = setInterval(() => {
11315
+ sm.set("time_on_page", timeOnPageSeconds);
11316
+ }, 5e3);
11317
+ }
11318
+ let unsubScroll;
11319
+ if (sessionMetrics && events) {
11320
+ const sm = sessionMetrics;
11321
+ unsubScroll = events.subscribe({ names: ["ui.scroll"] }, (event) => {
11322
+ var _a3;
11323
+ const pct = (_a3 = event.props) == null ? void 0 : _a3.scrollPercentage;
11324
+ if (typeof pct === "number" && pct > sm.get("scroll_depth")) {
11325
+ sm.set("scroll_depth", pct);
11326
+ }
11327
+ });
11328
+ }
11386
11329
  const runtime3 = {
11387
11330
  telemetry,
11388
11331
  context,
@@ -11443,6 +11386,9 @@ function createSmartCanvasRuntime(options = {}) {
11443
11386
  console.error("[Runtime] Error unbinding apps registry:", err);
11444
11387
  });
11445
11388
  unsubPageViews == null ? void 0 : unsubPageViews();
11389
+ unsubScroll == null ? void 0 : unsubScroll();
11390
+ if (timeOnPageTickInterval) clearInterval(timeOnPageTickInterval);
11391
+ if (timeOnPageFlushInterval) clearInterval(timeOnPageFlushInterval);
11446
11392
  anchorResolverService.destroy();
11447
11393
  accumulator.destroy();
11448
11394
  navigation.destroy();
@@ -11526,7 +11472,7 @@ function extractSegmentFlags(allFlags) {
11526
11472
  return segmentFlags;
11527
11473
  }
11528
11474
  function collectBrowserMetadata() {
11529
- var _a2;
11475
+ var _a2, _b;
11530
11476
  if (typeof window === "undefined") return {};
11531
11477
  const attrs = {};
11532
11478
  try {
@@ -11578,6 +11524,19 @@ function collectBrowserMetadata() {
11578
11524
  if (window.location.search) attrs.page_query = window.location.search;
11579
11525
  } catch {
11580
11526
  }
11527
+ try {
11528
+ const tg = (_b = window.Telegram) == null ? void 0 : _b.WebApp;
11529
+ if (tg) {
11530
+ attrs.surface_type = "telegram";
11531
+ attrs.surface_host = tg.platform || "unknown";
11532
+ } else {
11533
+ attrs.surface_type = "web";
11534
+ attrs.surface_host = "web";
11535
+ }
11536
+ } catch {
11537
+ attrs.surface_type = "web";
11538
+ attrs.surface_host = "web";
11539
+ }
11581
11540
  return attrs;
11582
11541
  }
11583
11542
  var GEO_CACHE_KEY = "syntro_geo";
@@ -11673,9 +11632,9 @@ var CdnFetcher = class {
11673
11632
  if (!response.ok) {
11674
11633
  throw new Error(`[SmartCanvas] Failed to fetch config from CDN (${response.status})`);
11675
11634
  }
11676
- const text2 = await response.text();
11635
+ const text = await response.text();
11677
11636
  if (this.integrity) {
11678
- const hash = await computeSha384(text2);
11637
+ const hash = await computeSha384(text);
11679
11638
  const expected = this.integrity.replace("sha384-", "");
11680
11639
  if (hash !== expected) {
11681
11640
  throw new Error(
@@ -11683,7 +11642,7 @@ var CdnFetcher = class {
11683
11642
  );
11684
11643
  }
11685
11644
  }
11686
- const config = JSON.parse(text2);
11645
+ const config = JSON.parse(text);
11687
11646
  const fetchTimeMs = performance.now() - start;
11688
11647
  const cacheControl = response.headers.get("cache-control");
11689
11648
  const age = response.headers.get("age");
@@ -11719,9 +11678,8 @@ var ExperimentsFetcher = class {
11719
11678
  __publicField(this, "featureKey");
11720
11679
  __publicField(this, "manifestKey");
11721
11680
  __publicField(this, "variantFlagPrefix");
11722
- var _a2;
11723
11681
  this.client = options.client;
11724
- this.featureKey = (_a2 = options.featureKey) != null ? _a2 : "smart-canvas-config";
11682
+ this.featureKey = options.featureKey;
11725
11683
  this.manifestKey = options.manifestKey;
11726
11684
  this.variantFlagPrefix = options.variantFlagPrefix;
11727
11685
  }
@@ -11868,7 +11826,7 @@ function createTelemetryClient(provider, config) {
11868
11826
 
11869
11827
  // src/bootstrap-runtime.ts
11870
11828
  async function _initCore(options) {
11871
- var _a2, _b, _c, _d, _e, _f, _g;
11829
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
11872
11830
  initLogger();
11873
11831
  debug("Syntro Bootstrap", "====== INIT ======");
11874
11832
  debug("Syntro Bootstrap", "Options:", {
@@ -11936,10 +11894,46 @@ async function _initCore(options) {
11936
11894
  const geoHost = (payload == null ? void 0 : payload.g) || getEnvVar("NEXT_PUBLIC_SYNTRO_GEO_HOST") || getEnvVar("VITE_SYNTRO_GEO_HOST") || GEO_DEFAULT_HOST;
11937
11895
  const cachedSegmentAttrs = loadCachedSegmentAttributes();
11938
11896
  const browserMetadata = collectBrowserMetadata();
11939
- const phaseOneAttrs = { ...browserMetadata, ...cachedSegmentAttrs };
11897
+ const appSignalsInit = (_c = options.appSignalsInit) != null ? _c : {};
11898
+ const phaseOneAttrs = { ...browserMetadata, ...cachedSegmentAttrs, ...appSignalsInit };
11940
11899
  debug("Syntro Bootstrap", "Phase 1: Browser metadata:", browserMetadata);
11941
11900
  debug("Syntro Bootstrap", "Phase 1: Cached segment attributes:", cachedSegmentAttrs);
11901
+ if (Object.keys(appSignalsInit).length > 0) {
11902
+ debug("Syntro Bootstrap", "Phase 1: App signals:", appSignalsInit);
11903
+ }
11942
11904
  const geoPromise = fetchGeo(geoHost);
11905
+ const mcpPromise = (() => {
11906
+ try {
11907
+ if (typeof window === "undefined" || window.self === window.top) return Promise.resolve(null);
11908
+ } catch {
11909
+ }
11910
+ return new Promise((resolve) => {
11911
+ const timer = setTimeout(() => {
11912
+ window.removeEventListener("message", handler);
11913
+ resolve(null);
11914
+ }, 500);
11915
+ function handler(event) {
11916
+ var _a3;
11917
+ const data = event.data;
11918
+ if ((data == null ? void 0 : data.jsonrpc) === "2.0" && (data == null ? void 0 : data.id) === 1 && ((_a3 = data == null ? void 0 : data.result) == null ? void 0 : _a3.hostInfo)) {
11919
+ clearTimeout(timer);
11920
+ window.removeEventListener("message", handler);
11921
+ resolve(data.result.hostInfo);
11922
+ }
11923
+ }
11924
+ window.addEventListener("message", handler);
11925
+ try {
11926
+ window.parent.postMessage(
11927
+ { jsonrpc: "2.0", id: 1, method: "ui/initialize", params: { capabilities: {} } },
11928
+ "*"
11929
+ );
11930
+ } catch {
11931
+ clearTimeout(timer);
11932
+ window.removeEventListener("message", handler);
11933
+ resolve(null);
11934
+ }
11935
+ });
11936
+ })();
11943
11937
  let experiments;
11944
11938
  const isDebugOrTest = options.debug || options.testMode;
11945
11939
  const events = createEventBus({
@@ -11994,7 +11988,12 @@ async function _initCore(options) {
11994
11988
  cacheSegmentAttributes(segmentFlags);
11995
11989
  if (experiments) {
11996
11990
  const sessionAttrs = (_b2 = (_a3 = sessionMetrics == null ? void 0 : sessionMetrics.getAll) == null ? void 0 : _a3.call(sessionMetrics)) != null ? _b2 : {};
11997
- const updatedAttrs = { ...browserMetadata, ...sessionAttrs, ...segmentFlags };
11991
+ const updatedAttrs = {
11992
+ ...browserMetadata,
11993
+ ...sessionAttrs,
11994
+ ...segmentFlags,
11995
+ ...appSignalsInit
11996
+ };
11998
11997
  debug("Syntro Bootstrap", "Updating GrowthBook with attributes:", updatedAttrs);
11999
11998
  (_c2 = experiments.setAttributes) == null ? void 0 : _c2.call(experiments, updatedAttrs);
12000
11999
  }
@@ -12008,9 +12007,7 @@ async function _initCore(options) {
12008
12007
  // undefined falls back to adapter default
12009
12008
  // Enable PostHog feature flags for segment membership
12010
12009
  enableFeatureFlags: true,
12011
- // Disable session recording in debug/dev mode (mock telemetry doesn't
12012
- // support the PostHog recorder extension, causing console errors)
12013
- sessionRecording: !payload.d,
12010
+ sessionRecording: true,
12014
12011
  // Wire up callback for when flags are loaded (Phase 2)
12015
12012
  onFeatureFlagsLoaded,
12016
12013
  // Wire up event capture to feed into event processor
@@ -12023,6 +12020,10 @@ async function _initCore(options) {
12023
12020
  }
12024
12021
  });
12025
12022
  console.log(`[Syntro Bootstrap] Telemetry client created (${provider}) with EventBus wiring`);
12023
+ if (Object.keys(appSignalsInit).length > 0) {
12024
+ (_d = telemetry.track) == null ? void 0 : _d.call(telemetry, "app_signals_init", appSignalsInit);
12025
+ debug("Syntro Bootstrap", "Tracked app signals event:", appSignalsInit);
12026
+ }
12026
12027
  const telemetryForCapture = telemetry;
12027
12028
  events.setPosthogCapture((name, props) => {
12028
12029
  var _a3;
@@ -12093,7 +12094,7 @@ async function _initCore(options) {
12093
12094
  };
12094
12095
  debug("Syntro Bootstrap", "Global SynOS object exposed");
12095
12096
  }
12096
- const registeredApps = (_e = (_d = (_c = runtime3.apps).list) == null ? void 0 : _d.call(_c)) != null ? _e : [];
12097
+ const registeredApps = (_g = (_f = (_e = runtime3.apps).list) == null ? void 0 : _f.call(_e)) != null ? _g : [];
12097
12098
  console.log(
12098
12099
  `[DIAG] Activation loop: ${registeredApps.length} apps in registry:`,
12099
12100
  registeredApps.map((a) => `${a.manifest.id}(${a.state})`).join(", ")
@@ -12122,15 +12123,22 @@ async function _initCore(options) {
12122
12123
  }
12123
12124
  const geoData = await geoPromise;
12124
12125
  if (experiments && Object.keys(geoData).length > 0) {
12125
- const mergedAttrs = { ...browserMetadata, ...geoData };
12126
+ const mergedAttrs = { ...browserMetadata, ...geoData, ...appSignalsInit };
12126
12127
  debug("Syntro Bootstrap", "Merging geo data into GrowthBook attributes:", geoData);
12127
- (_f = experiments.setAttributes) == null ? void 0 : _f.call(experiments, mergedAttrs);
12128
+ (_h = experiments.setAttributes) == null ? void 0 : _h.call(experiments, mergedAttrs);
12129
+ }
12130
+ const mcpHost = await mcpPromise;
12131
+ if (mcpHost && experiments) {
12132
+ browserMetadata.surface_type = "mcp-app";
12133
+ browserMetadata.surface_host = mcpHost.name;
12134
+ (_i = experiments.setAttributes) == null ? void 0 : _i.call(experiments, { ...browserMetadata, ...geoData });
12135
+ debug("Syntro Bootstrap", "MCP App detected:", mcpHost.name);
12128
12136
  }
12129
12137
  let baseFetcher;
12130
12138
  if (options.fetcher) {
12131
12139
  baseFetcher = options.fetcher;
12132
12140
  } else if (payload == null ? void 0 : payload.f) {
12133
- const configFetcher = createConfigFetcher(payload.f, (_g = payload.o) != null ? _g : {});
12141
+ const configFetcher = createConfigFetcher(payload.f, (_j = payload.o) != null ? _j : {});
12134
12142
  baseFetcher = async () => {
12135
12143
  var _a3;
12136
12144
  const result = await configFetcher.fetch();
@@ -12144,7 +12152,7 @@ async function _initCore(options) {
12144
12152
  }
12145
12153
  const warnedAppFailures = /* @__PURE__ */ new Set();
12146
12154
  const appLoadingFetcher = baseFetcher ? async () => {
12147
- var _a3, _b2, _c2, _d2, _e2, _f2, _g2, _h, _i, _j, _k, _l;
12155
+ var _a3, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k, _l;
12148
12156
  const config = await baseFetcher();
12149
12157
  const tileCount = (_b2 = (_a3 = config.tiles) == null ? void 0 : _a3.length) != null ? _b2 : 0;
12150
12158
  const actionCount = (_d2 = (_c2 = config.actions) == null ? void 0 : _c2.length) != null ? _d2 : 0;
@@ -12169,8 +12177,8 @@ async function _initCore(options) {
12169
12177
  console.log(
12170
12178
  "[Syntro Bootstrap] Config fetched:",
12171
12179
  `tiles=${(_g2 = (_f2 = config.tiles) == null ? void 0 : _f2.length) != null ? _g2 : 0},`,
12172
- `actions=${(_i = (_h = config.actions) == null ? void 0 : _h.length) != null ? _i : 0},`,
12173
- `theme=${(_k = (_j = config.theme) == null ? void 0 : _j.name) != null ? _k : "none"}`
12180
+ `actions=${(_i2 = (_h2 = config.actions) == null ? void 0 : _h2.length) != null ? _i2 : 0},`,
12181
+ `theme=${(_k = (_j2 = config.theme) == null ? void 0 : _j2.name) != null ? _k : "none"}`
12174
12182
  );
12175
12183
  if (((_l = config.actions) == null ? void 0 : _l.length) > 0) {
12176
12184
  console.log(
@@ -12269,10 +12277,6 @@ if (typeof window !== "undefined") {
12269
12277
 
12270
12278
  export {
12271
12279
  runtime,
12272
- base,
12273
- slateGrey,
12274
- red,
12275
- purple,
12276
12280
  runtime2,
12277
12281
  createAppContext,
12278
12282
  cleanupAppContext,
@@ -12374,4 +12378,4 @@ export {
12374
12378
  encodeToken,
12375
12379
  Syntro
12376
12380
  };
12377
- //# sourceMappingURL=chunk-GF364MMB.js.map
12381
+ //# sourceMappingURL=chunk-CVMZW3II.js.map