@syntrologie/runtime-sdk 2.4.1 → 2.6.0-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CAPABILITIES.md +66 -1
- package/dist/SmartCanvasApp.d.ts +5 -3
- package/dist/actions/executors/index.d.ts +1 -2
- package/dist/actions/index.d.ts +2 -2
- package/dist/actions/schema.d.ts +19111 -20709
- package/dist/actions/schema.js +5 -2
- package/dist/actions/types.d.ts +45 -48
- package/dist/anchor/AnchorResolver.d.ts +18 -0
- package/dist/anchor/index.d.ts +2 -0
- package/dist/api.d.ts +3 -8
- package/dist/apps/examples/gamification-app.example.d.ts +8 -8
- package/dist/{chunk-4NYS7GAW.js → chunk-BU4Z6PD7.js} +45 -7
- package/dist/chunk-BU4Z6PD7.js.map +7 -0
- package/dist/{chunk-QGWATS3Z.js → chunk-Q4WGXNKC.js} +2775 -1052
- package/dist/chunk-Q4WGXNKC.js.map +7 -0
- package/dist/{chunk-OGTCFYR3.js → chunk-R5DNAIRI.js} +45 -34
- package/dist/chunk-R5DNAIRI.js.map +7 -0
- package/dist/chunk-XDYJ64IN.js +178 -0
- package/dist/chunk-XDYJ64IN.js.map +7 -0
- package/dist/components/ShadowCanvasOverlay.d.ts +2 -20
- package/dist/components/TileIcon.d.ts +14 -0
- package/dist/config/schema.d.ts +5529 -3620
- package/dist/config/schema.js +21 -61
- package/dist/config/schema.js.map +3 -3
- package/dist/context/schema.d.ts +16 -16
- package/dist/decisions/schema.d.ts +357 -2789
- package/dist/decisions/schema.js +7 -1
- package/dist/decisions/types.d.ts +24 -2
- package/dist/events/registerConfigPredicates.d.ts +7 -10
- package/dist/events/schema.d.ts +12 -12
- package/dist/experiments/adapters/growthbook.d.ts +2 -0
- package/dist/experiments/types.d.ts +7 -0
- package/dist/hooks/useShadowCanvasConfig.d.ts +6 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +154 -186
- package/dist/index.js.map +3 -3
- package/dist/overlays/schema.d.ts +70 -70
- package/dist/react.js +4 -3
- package/dist/react.js.map +1 -1
- package/dist/runtime.d.ts +3 -0
- package/dist/smart-canvas.esm.js +123 -84
- package/dist/smart-canvas.esm.js.map +4 -4
- package/dist/smart-canvas.js +3271 -1210
- package/dist/smart-canvas.js.map +4 -4
- package/dist/smart-canvas.min.js +123 -84
- package/dist/smart-canvas.min.js.map +4 -4
- package/dist/surfaces/types.d.ts +2 -1
- package/dist/theme/ThemeProvider.d.ts +11 -16
- package/dist/theme/defaultTheme.d.ts +6 -1
- package/dist/theme/index.d.ts +3 -4
- package/dist/theme/types.d.ts +11 -0
- package/dist/version.d.ts +1 -1
- package/dist/widgets/WidgetRegistry.d.ts +1 -0
- package/package.json +9 -8
- package/schema/canvas-config.schema.json +10583 -1049
- package/scripts/validate-config.mjs +180 -0
- package/dist/actions/executors/tour.d.ts +0 -18
- package/dist/chunk-4NYS7GAW.js.map +0 -7
- package/dist/chunk-OGTCFYR3.js.map +0 -7
- package/dist/chunk-QGWATS3Z.js.map +0 -7
- package/dist/hooks/useHostPatches.d.ts +0 -9
- package/dist/theme/extractHostTheme.d.ts +0 -14
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
__privateGet,
|
|
4
4
|
__privateSet,
|
|
5
5
|
__publicField
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-BU4Z6PD7.js";
|
|
7
7
|
|
|
8
8
|
// ../adaptives/adaptive-content/dist/reconciliation-guard.js
|
|
9
9
|
function guardAgainstReconciliation(container, anchor, reinsertFn, opts) {
|
|
@@ -124,13 +124,30 @@ function sanitizeHtml(html) {
|
|
|
124
124
|
|
|
125
125
|
// ../adaptives/adaptive-content/dist/runtime.js
|
|
126
126
|
var executeInsertHtml = async (action, context) => {
|
|
127
|
-
|
|
127
|
+
var _a2;
|
|
128
|
+
let anchorEl = context.resolveAnchor(action.anchorId);
|
|
129
|
+
if (!anchorEl && context.waitForAnchor) {
|
|
130
|
+
anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
|
|
131
|
+
}
|
|
128
132
|
if (!anchorEl) {
|
|
129
|
-
|
|
133
|
+
console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
|
|
134
|
+
return { cleanup: () => {
|
|
135
|
+
} };
|
|
130
136
|
}
|
|
131
137
|
const sanitizedHtml = sanitizeHtml(action.html);
|
|
138
|
+
const dedupAttr = "data-syntro-insert-label";
|
|
139
|
+
const label = action.label;
|
|
140
|
+
if (label) {
|
|
141
|
+
const escapedLabel = CSS.escape(label);
|
|
142
|
+
const searchRoot = (_a2 = anchorEl.parentElement) != null ? _a2 : anchorEl;
|
|
143
|
+
const existing = searchRoot.querySelector(`[${dedupAttr}="${escapedLabel}"]`);
|
|
144
|
+
if (existing)
|
|
145
|
+
existing.remove();
|
|
146
|
+
}
|
|
132
147
|
const container = document.createElement("div");
|
|
133
148
|
container.setAttribute("data-syntro-action-id", context.generateId());
|
|
149
|
+
if (label)
|
|
150
|
+
container.setAttribute(dedupAttr, label);
|
|
134
151
|
container.innerHTML = sanitizedHtml;
|
|
135
152
|
let originalContent = null;
|
|
136
153
|
switch (action.position) {
|
|
@@ -151,6 +168,20 @@ var executeInsertHtml = async (action, context) => {
|
|
|
151
168
|
anchorEl.replaceWith(container);
|
|
152
169
|
break;
|
|
153
170
|
}
|
|
171
|
+
let deepLinkHandler = null;
|
|
172
|
+
if (action.deepLink) {
|
|
173
|
+
const { tileId, itemId } = action.deepLink;
|
|
174
|
+
deepLinkHandler = () => {
|
|
175
|
+
var _a3, _b, _c;
|
|
176
|
+
const handle = (_a3 = window.SynOS) == null ? void 0 : _a3.handle;
|
|
177
|
+
if (handle) {
|
|
178
|
+
handle.open();
|
|
179
|
+
(_c = (_b = handle.runtime) == null ? void 0 : _b.events) == null ? void 0 : _c.publish("notification.deep_link", { tileId, itemId });
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
container.style.cursor = "pointer";
|
|
183
|
+
container.addEventListener("click", deepLinkHandler);
|
|
184
|
+
}
|
|
154
185
|
context.publishEvent("action.applied", {
|
|
155
186
|
id: context.generateId(),
|
|
156
187
|
kind: "content:insertHtml",
|
|
@@ -178,6 +209,9 @@ var executeInsertHtml = async (action, context) => {
|
|
|
178
209
|
const guardCleanup = guardAgainstReconciliation(container, anchorEl, reinsertFn);
|
|
179
210
|
return {
|
|
180
211
|
cleanup: () => {
|
|
212
|
+
if (deepLinkHandler) {
|
|
213
|
+
container.removeEventListener("click", deepLinkHandler);
|
|
214
|
+
}
|
|
181
215
|
guardCleanup();
|
|
182
216
|
if (action.position === "replace" && originalContent !== null) {
|
|
183
217
|
const restoredEl = document.createElement(anchorEl.tagName);
|
|
@@ -199,9 +233,14 @@ var executeInsertHtml = async (action, context) => {
|
|
|
199
233
|
};
|
|
200
234
|
var executeSetText = async (action, context) => {
|
|
201
235
|
var _a2;
|
|
202
|
-
|
|
236
|
+
let anchorEl = context.resolveAnchor(action.anchorId);
|
|
237
|
+
if (!anchorEl && context.waitForAnchor) {
|
|
238
|
+
anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
|
|
239
|
+
}
|
|
203
240
|
if (!anchorEl) {
|
|
204
|
-
|
|
241
|
+
console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
|
|
242
|
+
return { cleanup: () => {
|
|
243
|
+
} };
|
|
205
244
|
}
|
|
206
245
|
const originalText = (_a2 = anchorEl.textContent) != null ? _a2 : "";
|
|
207
246
|
anchorEl.textContent = action.text;
|
|
@@ -222,9 +261,14 @@ var executeSetText = async (action, context) => {
|
|
|
222
261
|
};
|
|
223
262
|
};
|
|
224
263
|
var executeSetAttr = async (action, context) => {
|
|
225
|
-
|
|
264
|
+
let anchorEl = context.resolveAnchor(action.anchorId);
|
|
265
|
+
if (!anchorEl && context.waitForAnchor) {
|
|
266
|
+
anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
|
|
267
|
+
}
|
|
226
268
|
if (!anchorEl) {
|
|
227
|
-
|
|
269
|
+
console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
|
|
270
|
+
return { cleanup: () => {
|
|
271
|
+
} };
|
|
228
272
|
}
|
|
229
273
|
const lowerAttr = action.attr.toLowerCase();
|
|
230
274
|
if (lowerAttr.startsWith("on")) {
|
|
@@ -262,9 +306,14 @@ var executeSetAttr = async (action, context) => {
|
|
|
262
306
|
};
|
|
263
307
|
};
|
|
264
308
|
var executeAddClass = async (action, context) => {
|
|
265
|
-
|
|
309
|
+
let anchorEl = context.resolveAnchor(action.anchorId);
|
|
310
|
+
if (!anchorEl && context.waitForAnchor) {
|
|
311
|
+
anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
|
|
312
|
+
}
|
|
266
313
|
if (!anchorEl) {
|
|
267
|
-
|
|
314
|
+
console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
|
|
315
|
+
return { cleanup: () => {
|
|
316
|
+
} };
|
|
268
317
|
}
|
|
269
318
|
const hadClass = anchorEl.classList.contains(action.className);
|
|
270
319
|
anchorEl.classList.add(action.className);
|
|
@@ -283,9 +332,14 @@ var executeAddClass = async (action, context) => {
|
|
|
283
332
|
};
|
|
284
333
|
};
|
|
285
334
|
var executeRemoveClass = async (action, context) => {
|
|
286
|
-
|
|
335
|
+
let anchorEl = context.resolveAnchor(action.anchorId);
|
|
336
|
+
if (!anchorEl && context.waitForAnchor) {
|
|
337
|
+
anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
|
|
338
|
+
}
|
|
287
339
|
if (!anchorEl) {
|
|
288
|
-
|
|
340
|
+
console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
|
|
341
|
+
return { cleanup: () => {
|
|
342
|
+
} };
|
|
289
343
|
}
|
|
290
344
|
const hadClass = anchorEl.classList.contains(action.className);
|
|
291
345
|
anchorEl.classList.remove(action.className);
|
|
@@ -304,9 +358,14 @@ var executeRemoveClass = async (action, context) => {
|
|
|
304
358
|
};
|
|
305
359
|
};
|
|
306
360
|
var executeSetStyle = async (action, context) => {
|
|
307
|
-
|
|
361
|
+
let anchorEl = context.resolveAnchor(action.anchorId);
|
|
362
|
+
if (!anchorEl && context.waitForAnchor) {
|
|
363
|
+
anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
|
|
364
|
+
}
|
|
308
365
|
if (!anchorEl) {
|
|
309
|
-
|
|
366
|
+
console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
|
|
367
|
+
return { cleanup: () => {
|
|
368
|
+
} };
|
|
310
369
|
}
|
|
311
370
|
const originalStyles = /* @__PURE__ */ new Map();
|
|
312
371
|
for (const prop of Object.keys(action.styles)) {
|
|
@@ -357,6 +416,701 @@ var runtime = {
|
|
|
357
416
|
executors
|
|
358
417
|
};
|
|
359
418
|
|
|
419
|
+
// ../adaptives/adaptive-overlays/dist/celebrations/effects/confetti.js
|
|
420
|
+
var INTENSITY_COUNTS = { light: 50, medium: 100, heavy: 200 };
|
|
421
|
+
var DEFAULT_COLORS = [
|
|
422
|
+
"#ff0000",
|
|
423
|
+
"#00ff00",
|
|
424
|
+
"#0000ff",
|
|
425
|
+
"#ffff00",
|
|
426
|
+
"#ff00ff",
|
|
427
|
+
"#00ffff",
|
|
428
|
+
"#ff8800",
|
|
429
|
+
"#8800ff"
|
|
430
|
+
];
|
|
431
|
+
var confettiEffect = {
|
|
432
|
+
init(width, height, config) {
|
|
433
|
+
const count = INTENSITY_COUNTS[config.intensity];
|
|
434
|
+
const colors = config.colors.length > 0 ? config.colors : DEFAULT_COLORS;
|
|
435
|
+
const particles = [];
|
|
436
|
+
for (let i = 0; i < count; i++) {
|
|
437
|
+
particles.push({
|
|
438
|
+
x: Math.random() * width,
|
|
439
|
+
y: Math.random() * -height * 0.3,
|
|
440
|
+
vx: (Math.random() - 0.5) * 4,
|
|
441
|
+
vy: Math.random() * 2 + 1,
|
|
442
|
+
rotation: Math.random() * Math.PI * 2,
|
|
443
|
+
rotationSpeed: (Math.random() - 0.5) * 0.2,
|
|
444
|
+
size: Math.random() * 6 + 4,
|
|
445
|
+
color: colors[Math.floor(Math.random() * colors.length)],
|
|
446
|
+
opacity: 1,
|
|
447
|
+
shape: Math.random() > 0.5 ? "rect" : "circle"
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
return particles;
|
|
451
|
+
},
|
|
452
|
+
update(particles, _dt, _elapsed) {
|
|
453
|
+
let anyVisible = false;
|
|
454
|
+
for (const p of particles) {
|
|
455
|
+
p.vy += 0.15;
|
|
456
|
+
p.vx *= 0.99;
|
|
457
|
+
p.x += p.vx;
|
|
458
|
+
p.y += p.vy;
|
|
459
|
+
p.rotation += p.rotationSpeed;
|
|
460
|
+
if (p.y > 0 && p.opacity > 0) {
|
|
461
|
+
if (p.y > 500) {
|
|
462
|
+
p.opacity -= 0.02;
|
|
463
|
+
if (p.opacity < 0)
|
|
464
|
+
p.opacity = 0;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
if (p.opacity > 0.01) {
|
|
468
|
+
anyVisible = true;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return anyVisible;
|
|
472
|
+
},
|
|
473
|
+
render(ctx, particles) {
|
|
474
|
+
for (const p of particles) {
|
|
475
|
+
if (p.opacity < 0.01)
|
|
476
|
+
continue;
|
|
477
|
+
ctx.save();
|
|
478
|
+
ctx.globalAlpha = p.opacity;
|
|
479
|
+
ctx.fillStyle = p.color;
|
|
480
|
+
ctx.translate(p.x, p.y);
|
|
481
|
+
ctx.rotate(p.rotation);
|
|
482
|
+
if (p.shape === "circle") {
|
|
483
|
+
ctx.beginPath();
|
|
484
|
+
ctx.arc(0, 0, p.size / 2, 0, Math.PI * 2);
|
|
485
|
+
ctx.fill();
|
|
486
|
+
} else {
|
|
487
|
+
ctx.fillRect(-p.size / 2, -p.size / 2, p.size, p.size * 0.6);
|
|
488
|
+
}
|
|
489
|
+
ctx.restore();
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
// ../adaptives/adaptive-overlays/dist/celebrations/effects/emoji-rain.js
|
|
495
|
+
var INTENSITY_COUNTS2 = { light: 20, medium: 40, heavy: 80 };
|
|
496
|
+
var DEFAULT_EMOJI = "\u{1F389}";
|
|
497
|
+
var emojiRainEffect = {
|
|
498
|
+
init(width, _height, config) {
|
|
499
|
+
var _a2;
|
|
500
|
+
const count = INTENSITY_COUNTS2[config.intensity];
|
|
501
|
+
const emoji = typeof ((_a2 = config.props) == null ? void 0 : _a2.emoji) === "string" ? config.props.emoji : DEFAULT_EMOJI;
|
|
502
|
+
const particles = [];
|
|
503
|
+
for (let i = 0; i < count; i++) {
|
|
504
|
+
particles.push({
|
|
505
|
+
x: Math.random() * width,
|
|
506
|
+
y: Math.random() * -200,
|
|
507
|
+
vx: 0,
|
|
508
|
+
vy: Math.random() * 1.5 + 1,
|
|
509
|
+
rotation: 0,
|
|
510
|
+
rotationSpeed: 0,
|
|
511
|
+
size: Math.random() * 12 + 16,
|
|
512
|
+
color: "#000000",
|
|
513
|
+
opacity: 1,
|
|
514
|
+
shape: "emoji",
|
|
515
|
+
emoji,
|
|
516
|
+
data: {
|
|
517
|
+
/** Phase offset for horizontal wobble */
|
|
518
|
+
wobblePhase: Math.random() * Math.PI * 2,
|
|
519
|
+
/** Amplitude of horizontal wobble */
|
|
520
|
+
wobbleAmp: Math.random() * 1.5 + 0.5,
|
|
521
|
+
/** Original x for wobble base */
|
|
522
|
+
originX: 0
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
for (const p of particles) {
|
|
527
|
+
if (p.data)
|
|
528
|
+
p.data.originX = p.x;
|
|
529
|
+
}
|
|
530
|
+
return particles;
|
|
531
|
+
},
|
|
532
|
+
update(particles, _dt, elapsed) {
|
|
533
|
+
var _a2, _b, _c, _d, _e, _f;
|
|
534
|
+
let anyVisible = false;
|
|
535
|
+
for (const p of particles) {
|
|
536
|
+
p.y += p.vy;
|
|
537
|
+
const phase = (_b = (_a2 = p.data) == null ? void 0 : _a2.wobblePhase) != null ? _b : 0;
|
|
538
|
+
const amp = (_d = (_c = p.data) == null ? void 0 : _c.wobbleAmp) != null ? _d : 1;
|
|
539
|
+
const originX = (_f = (_e = p.data) == null ? void 0 : _e.originX) != null ? _f : p.x;
|
|
540
|
+
p.x = originX + Math.sin(elapsed * 3e-3 + phase) * amp * 20;
|
|
541
|
+
if (p.y > 600) {
|
|
542
|
+
p.opacity -= 0.02;
|
|
543
|
+
if (p.opacity < 0)
|
|
544
|
+
p.opacity = 0;
|
|
545
|
+
}
|
|
546
|
+
if (p.opacity > 0.01) {
|
|
547
|
+
anyVisible = true;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return anyVisible;
|
|
551
|
+
},
|
|
552
|
+
render(ctx, particles) {
|
|
553
|
+
for (const p of particles) {
|
|
554
|
+
if (p.opacity < 0.01 || !p.emoji)
|
|
555
|
+
continue;
|
|
556
|
+
ctx.save();
|
|
557
|
+
ctx.globalAlpha = p.opacity;
|
|
558
|
+
ctx.font = `${p.size}px serif`;
|
|
559
|
+
ctx.textAlign = "center";
|
|
560
|
+
ctx.textBaseline = "middle";
|
|
561
|
+
ctx.fillText(p.emoji, p.x, p.y);
|
|
562
|
+
ctx.restore();
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
// ../adaptives/adaptive-overlays/dist/celebrations/effects/fireworks.js
|
|
568
|
+
var PARTICLES_PER_BURST = { light: 20, medium: 40, heavy: 80 };
|
|
569
|
+
var BURST_COUNTS = { light: 3, medium: 4, heavy: 5 };
|
|
570
|
+
var fireworksEffect = {
|
|
571
|
+
init(width, height, config) {
|
|
572
|
+
const perBurst = PARTICLES_PER_BURST[config.intensity];
|
|
573
|
+
const burstCount = BURST_COUNTS[config.intensity];
|
|
574
|
+
const colors = config.colors.length > 0 ? config.colors : ["#ff4444", "#44ff44", "#4444ff"];
|
|
575
|
+
const particles = [];
|
|
576
|
+
for (let b = 0; b < burstCount; b++) {
|
|
577
|
+
const cx = Math.random() * width * 0.8 + width * 0.1;
|
|
578
|
+
const cy = Math.random() * height * 0.6;
|
|
579
|
+
const burstColor = colors[Math.floor(Math.random() * colors.length)];
|
|
580
|
+
for (let i = 0; i < perBurst; i++) {
|
|
581
|
+
const angle = Math.PI * 2 * i / perBurst + (Math.random() - 0.5) * 0.3;
|
|
582
|
+
const speed = Math.random() * 3 + 2;
|
|
583
|
+
particles.push({
|
|
584
|
+
x: cx,
|
|
585
|
+
y: cy,
|
|
586
|
+
vx: Math.cos(angle) * speed,
|
|
587
|
+
vy: Math.sin(angle) * speed,
|
|
588
|
+
rotation: 0,
|
|
589
|
+
rotationSpeed: 0,
|
|
590
|
+
size: Math.random() * 3 + 2,
|
|
591
|
+
color: burstColor,
|
|
592
|
+
opacity: 1,
|
|
593
|
+
shape: "circle",
|
|
594
|
+
data: { centerX: cx, centerY: cy }
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
return particles;
|
|
599
|
+
},
|
|
600
|
+
update(particles, _dt, _elapsed) {
|
|
601
|
+
let anyVisible = false;
|
|
602
|
+
for (const p of particles) {
|
|
603
|
+
p.vx *= 0.97;
|
|
604
|
+
p.vy *= 0.97;
|
|
605
|
+
p.vy += 0.03;
|
|
606
|
+
p.x += p.vx;
|
|
607
|
+
p.y += p.vy;
|
|
608
|
+
p.opacity -= 8e-3;
|
|
609
|
+
if (p.opacity < 0)
|
|
610
|
+
p.opacity = 0;
|
|
611
|
+
if (p.opacity > 0.01) {
|
|
612
|
+
anyVisible = true;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
return anyVisible;
|
|
616
|
+
},
|
|
617
|
+
render(ctx, particles) {
|
|
618
|
+
for (const p of particles) {
|
|
619
|
+
if (p.opacity < 0.01)
|
|
620
|
+
continue;
|
|
621
|
+
ctx.save();
|
|
622
|
+
ctx.globalAlpha = p.opacity;
|
|
623
|
+
ctx.fillStyle = p.color;
|
|
624
|
+
ctx.shadowBlur = 12;
|
|
625
|
+
ctx.shadowColor = p.color;
|
|
626
|
+
ctx.beginPath();
|
|
627
|
+
ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
|
|
628
|
+
ctx.fill();
|
|
629
|
+
ctx.restore();
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
// ../adaptives/adaptive-overlays/dist/celebrations/effects/sparkles.js
|
|
635
|
+
var INTENSITY_COUNTS3 = { light: 30, medium: 60, heavy: 120 };
|
|
636
|
+
var sparklesEffect = {
|
|
637
|
+
init(width, height, config) {
|
|
638
|
+
const count = INTENSITY_COUNTS3[config.intensity];
|
|
639
|
+
const colors = config.colors.length > 0 ? config.colors : ["#ffd700", "#ffffff", "#fffacd"];
|
|
640
|
+
const particles = [];
|
|
641
|
+
for (let i = 0; i < count; i++) {
|
|
642
|
+
particles.push({
|
|
643
|
+
x: Math.random() * width,
|
|
644
|
+
y: Math.random() * height,
|
|
645
|
+
vx: (Math.random() - 0.5) * 0.3,
|
|
646
|
+
vy: -(Math.random() * 0.5 + 0.2),
|
|
647
|
+
rotation: Math.random() * Math.PI * 2,
|
|
648
|
+
rotationSpeed: (Math.random() - 0.5) * 0.1,
|
|
649
|
+
size: Math.random() * 4 + 2,
|
|
650
|
+
color: colors[Math.floor(Math.random() * colors.length)],
|
|
651
|
+
opacity: Math.random() * 0.5 + 0.5,
|
|
652
|
+
shape: "circle",
|
|
653
|
+
data: {
|
|
654
|
+
/** Phase offset for sine-wave twinkle */
|
|
655
|
+
phase: Math.random() * Math.PI * 2,
|
|
656
|
+
/** Base opacity before twinkle modulation */
|
|
657
|
+
baseOpacity: Math.random() * 0.5 + 0.5
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
return particles;
|
|
662
|
+
},
|
|
663
|
+
update(particles, _dt, elapsed) {
|
|
664
|
+
var _a2, _b, _c, _d, _e;
|
|
665
|
+
let anyVisible = false;
|
|
666
|
+
for (const p of particles) {
|
|
667
|
+
p.x += p.vx;
|
|
668
|
+
p.y += p.vy;
|
|
669
|
+
p.rotation += p.rotationSpeed;
|
|
670
|
+
if (p.data) {
|
|
671
|
+
p.data.baseOpacity = ((_a2 = p.data.baseOpacity) != null ? _a2 : 1) - 1e-3;
|
|
672
|
+
if (p.data.baseOpacity < 0)
|
|
673
|
+
p.data.baseOpacity = 0;
|
|
674
|
+
}
|
|
675
|
+
const phase = (_c = (_b = p.data) == null ? void 0 : _b.phase) != null ? _c : 0;
|
|
676
|
+
const baseOpacity = (_e = (_d = p.data) == null ? void 0 : _d.baseOpacity) != null ? _e : 1;
|
|
677
|
+
if (baseOpacity <= 0.01) {
|
|
678
|
+
p.opacity = 0;
|
|
679
|
+
} else {
|
|
680
|
+
const twinkle = Math.sin(elapsed * 5e-3 + phase) * 0.4 + 0.6;
|
|
681
|
+
p.opacity = baseOpacity * twinkle;
|
|
682
|
+
}
|
|
683
|
+
if (p.opacity > 0.01) {
|
|
684
|
+
anyVisible = true;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
return anyVisible;
|
|
688
|
+
},
|
|
689
|
+
render(ctx, particles) {
|
|
690
|
+
for (const p of particles) {
|
|
691
|
+
if (p.opacity < 0.01)
|
|
692
|
+
continue;
|
|
693
|
+
ctx.save();
|
|
694
|
+
ctx.globalAlpha = p.opacity;
|
|
695
|
+
ctx.fillStyle = p.color;
|
|
696
|
+
ctx.translate(p.x, p.y);
|
|
697
|
+
ctx.rotate(p.rotation);
|
|
698
|
+
const s = p.size;
|
|
699
|
+
ctx.beginPath();
|
|
700
|
+
ctx.moveTo(0, -s);
|
|
701
|
+
ctx.lineTo(s * 0.3, -s * 0.3);
|
|
702
|
+
ctx.lineTo(s, 0);
|
|
703
|
+
ctx.lineTo(s * 0.3, s * 0.3);
|
|
704
|
+
ctx.lineTo(0, s);
|
|
705
|
+
ctx.lineTo(-s * 0.3, s * 0.3);
|
|
706
|
+
ctx.lineTo(-s, 0);
|
|
707
|
+
ctx.lineTo(-s * 0.3, -s * 0.3);
|
|
708
|
+
ctx.closePath();
|
|
709
|
+
ctx.fill();
|
|
710
|
+
ctx.restore();
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
// ../adaptives/adaptive-overlays/dist/celebrations/engine.js
|
|
716
|
+
var CelebrationEngine = class {
|
|
717
|
+
constructor() {
|
|
718
|
+
this.canvas = null;
|
|
719
|
+
this.ctx = null;
|
|
720
|
+
this.rafId = null;
|
|
721
|
+
this.particles = [];
|
|
722
|
+
this.startTime = 0;
|
|
723
|
+
this.lastFrame = 0;
|
|
724
|
+
this.duration = 0;
|
|
725
|
+
this.effect = null;
|
|
726
|
+
this.container = null;
|
|
727
|
+
}
|
|
728
|
+
start(container, effect, config) {
|
|
729
|
+
this.container = container;
|
|
730
|
+
this.effect = effect;
|
|
731
|
+
this.duration = config.duration;
|
|
732
|
+
const canvas = document.createElement("canvas");
|
|
733
|
+
canvas.setAttribute("data-syntro-celebrate", "");
|
|
734
|
+
Object.assign(canvas.style, {
|
|
735
|
+
position: "fixed",
|
|
736
|
+
inset: "0",
|
|
737
|
+
pointerEvents: "none",
|
|
738
|
+
zIndex: "2147483646"
|
|
739
|
+
});
|
|
740
|
+
const dpr = window.devicePixelRatio || 1;
|
|
741
|
+
const width = window.innerWidth;
|
|
742
|
+
const height = window.innerHeight;
|
|
743
|
+
canvas.width = width * dpr;
|
|
744
|
+
canvas.height = height * dpr;
|
|
745
|
+
canvas.style.width = `${width}px`;
|
|
746
|
+
canvas.style.height = `${height}px`;
|
|
747
|
+
const ctx = canvas.getContext("2d");
|
|
748
|
+
if (!ctx) {
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
ctx.scale(dpr, dpr);
|
|
752
|
+
this.canvas = canvas;
|
|
753
|
+
this.ctx = ctx;
|
|
754
|
+
container.appendChild(canvas);
|
|
755
|
+
this.particles = effect.init(width, height, config);
|
|
756
|
+
this.startTime = performance.now();
|
|
757
|
+
this.lastFrame = this.startTime;
|
|
758
|
+
this.tick = this.tick.bind(this);
|
|
759
|
+
this.rafId = requestAnimationFrame(this.tick);
|
|
760
|
+
}
|
|
761
|
+
stop() {
|
|
762
|
+
if (this.rafId !== null) {
|
|
763
|
+
cancelAnimationFrame(this.rafId);
|
|
764
|
+
this.rafId = null;
|
|
765
|
+
}
|
|
766
|
+
if (this.canvas && this.container) {
|
|
767
|
+
this.canvas.remove();
|
|
768
|
+
this.canvas = null;
|
|
769
|
+
}
|
|
770
|
+
this.ctx = null;
|
|
771
|
+
this.effect = null;
|
|
772
|
+
this.container = null;
|
|
773
|
+
this.particles = [];
|
|
774
|
+
}
|
|
775
|
+
tick(now) {
|
|
776
|
+
if (!this.ctx || !this.canvas || !this.effect)
|
|
777
|
+
return;
|
|
778
|
+
const elapsed = now - this.startTime;
|
|
779
|
+
const dt = now - this.lastFrame;
|
|
780
|
+
this.lastFrame = now;
|
|
781
|
+
if (elapsed >= this.duration) {
|
|
782
|
+
this.stop();
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
const width = this.canvas.width / (window.devicePixelRatio || 1);
|
|
786
|
+
const height = this.canvas.height / (window.devicePixelRatio || 1);
|
|
787
|
+
this.ctx.clearRect(0, 0, width, height);
|
|
788
|
+
const alive = this.effect.update(this.particles, dt, elapsed);
|
|
789
|
+
if (!alive) {
|
|
790
|
+
this.stop();
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
this.effect.render(this.ctx, this.particles);
|
|
794
|
+
this.rafId = requestAnimationFrame(this.tick);
|
|
795
|
+
}
|
|
796
|
+
};
|
|
797
|
+
|
|
798
|
+
// ../adaptives/adaptive-overlays/dist/celebrations/index.js
|
|
799
|
+
var FALLBACK_COLORS = [
|
|
800
|
+
"#ff0000",
|
|
801
|
+
"#00ff00",
|
|
802
|
+
"#0000ff",
|
|
803
|
+
"#ffff00",
|
|
804
|
+
"#ff00ff",
|
|
805
|
+
"#00ffff",
|
|
806
|
+
"#ff8800",
|
|
807
|
+
"#8800ff"
|
|
808
|
+
];
|
|
809
|
+
function buildThemePalette(primary, hover) {
|
|
810
|
+
return [primary, hover, `${primary}cc`, `${hover}cc`, "#ffffff", `${primary}80`];
|
|
811
|
+
}
|
|
812
|
+
function readThemeColors(overlayRoot) {
|
|
813
|
+
var _a2, _b;
|
|
814
|
+
try {
|
|
815
|
+
const styles = getComputedStyle(overlayRoot);
|
|
816
|
+
const primary = (_a2 = styles.getPropertyValue("--sc-color-primary")) == null ? void 0 : _a2.trim();
|
|
817
|
+
const hover = (_b = styles.getPropertyValue("--sc-color-primary-hover")) == null ? void 0 : _b.trim();
|
|
818
|
+
if ((primary == null ? void 0 : primary.startsWith("#")) && primary.length >= 7) {
|
|
819
|
+
return buildThemePalette(primary, hover || primary);
|
|
820
|
+
}
|
|
821
|
+
} catch {
|
|
822
|
+
}
|
|
823
|
+
return null;
|
|
824
|
+
}
|
|
825
|
+
var effectRegistry = /* @__PURE__ */ new Map([
|
|
826
|
+
["confetti", confettiEffect],
|
|
827
|
+
["fireworks", fireworksEffect],
|
|
828
|
+
["sparkles", sparklesEffect],
|
|
829
|
+
["emoji-rain", emojiRainEffect]
|
|
830
|
+
]);
|
|
831
|
+
var executeCelebrate = async (action, context) => {
|
|
832
|
+
var _a2, _b, _c, _d;
|
|
833
|
+
const effect = effectRegistry.get(action.effect);
|
|
834
|
+
if (!effect) {
|
|
835
|
+
console.warn(`[adaptive-overlays] Unknown celebration effect: "${action.effect}". Available: ${[...effectRegistry.keys()].join(", ")}`);
|
|
836
|
+
return { cleanup: () => {
|
|
837
|
+
} };
|
|
838
|
+
}
|
|
839
|
+
const colors = (_b = (_a2 = action.colors) != null ? _a2 : readThemeColors(context.overlayRoot)) != null ? _b : FALLBACK_COLORS;
|
|
840
|
+
const config = {
|
|
841
|
+
duration: (_c = action.duration) != null ? _c : 3e3,
|
|
842
|
+
intensity: (_d = action.intensity) != null ? _d : "medium",
|
|
843
|
+
colors,
|
|
844
|
+
props: action.props
|
|
845
|
+
};
|
|
846
|
+
const engine = new CelebrationEngine();
|
|
847
|
+
engine.start(context.overlayRoot, effect, config);
|
|
848
|
+
context.publishEvent("action.applied", {
|
|
849
|
+
id: context.generateId(),
|
|
850
|
+
kind: "overlays:celebrate",
|
|
851
|
+
effect: action.effect
|
|
852
|
+
});
|
|
853
|
+
return {
|
|
854
|
+
cleanup: () => {
|
|
855
|
+
engine.stop();
|
|
856
|
+
}
|
|
857
|
+
};
|
|
858
|
+
};
|
|
859
|
+
|
|
860
|
+
// ../adaptives/adaptive-overlays/dist/executors/tour.js
|
|
861
|
+
var ACTIVE_TOUR_KEY = "syntro_active_tour";
|
|
862
|
+
var activeTours = /* @__PURE__ */ new Map();
|
|
863
|
+
function getTourState(tourId) {
|
|
864
|
+
try {
|
|
865
|
+
const data = localStorage.getItem(ACTIVE_TOUR_KEY);
|
|
866
|
+
if (!data)
|
|
867
|
+
return null;
|
|
868
|
+
const state = JSON.parse(data);
|
|
869
|
+
if (state.tourId !== tourId)
|
|
870
|
+
return null;
|
|
871
|
+
return state;
|
|
872
|
+
} catch {
|
|
873
|
+
return null;
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
function saveTourState(state) {
|
|
877
|
+
try {
|
|
878
|
+
localStorage.setItem(ACTIVE_TOUR_KEY, JSON.stringify(state));
|
|
879
|
+
} catch {
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
function clearTourState() {
|
|
883
|
+
try {
|
|
884
|
+
localStorage.removeItem(ACTIVE_TOUR_KEY);
|
|
885
|
+
} catch {
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
function getCurrentRoute() {
|
|
889
|
+
return window.location.pathname;
|
|
890
|
+
}
|
|
891
|
+
function stepMatchesRoute(step) {
|
|
892
|
+
if (!step.route)
|
|
893
|
+
return true;
|
|
894
|
+
const currentRoute = getCurrentRoute();
|
|
895
|
+
if (step.route.includes("*")) {
|
|
896
|
+
const pattern = new RegExp(`^${step.route.replace(/\*/g, ".*")}$`);
|
|
897
|
+
return pattern.test(currentRoute);
|
|
898
|
+
}
|
|
899
|
+
return currentRoute === step.route;
|
|
900
|
+
}
|
|
901
|
+
var executeTour = async (action, context) => {
|
|
902
|
+
const { tourId, steps, startStep, autoStart = true } = action;
|
|
903
|
+
if (steps.length === 0) {
|
|
904
|
+
throw new Error(`Tour "${tourId}" has no steps`);
|
|
905
|
+
}
|
|
906
|
+
if (activeTours.has(tourId)) {
|
|
907
|
+
return {
|
|
908
|
+
cleanup: async () => {
|
|
909
|
+
const existing = activeTours.get(tourId);
|
|
910
|
+
if (existing) {
|
|
911
|
+
await existing.cleanup();
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
if (!context.applyAction) {
|
|
917
|
+
throw new Error("Tour executor requires applyAction in context");
|
|
918
|
+
}
|
|
919
|
+
let state = getTourState(tourId);
|
|
920
|
+
const isResumingTour = !!state;
|
|
921
|
+
if (!isResumingTour && !autoStart) {
|
|
922
|
+
return {
|
|
923
|
+
cleanup: () => {
|
|
924
|
+
}
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
if (!state) {
|
|
928
|
+
state = {
|
|
929
|
+
tourId,
|
|
930
|
+
currentStepId: startStep || steps[0].id,
|
|
931
|
+
startedAt: Date.now()
|
|
932
|
+
};
|
|
933
|
+
saveTourState(state);
|
|
934
|
+
}
|
|
935
|
+
let currentStepIndex = steps.findIndex((s) => s.id === state.currentStepId);
|
|
936
|
+
if (currentStepIndex === -1) {
|
|
937
|
+
const initialStepId = startStep || steps[0].id;
|
|
938
|
+
currentStepIndex = steps.findIndex((s) => s.id === initialStepId);
|
|
939
|
+
if (currentStepIndex === -1)
|
|
940
|
+
currentStepIndex = 0;
|
|
941
|
+
state.currentStepId = steps[currentStepIndex].id;
|
|
942
|
+
saveTourState(state);
|
|
943
|
+
}
|
|
944
|
+
const currentStep = steps[currentStepIndex];
|
|
945
|
+
if (!stepMatchesRoute(currentStep)) {
|
|
946
|
+
context.publishEvent("tour.waiting_for_route", {
|
|
947
|
+
tourId,
|
|
948
|
+
stepId: currentStep.id,
|
|
949
|
+
expectedRoute: currentStep.route,
|
|
950
|
+
currentRoute: getCurrentRoute()
|
|
951
|
+
});
|
|
952
|
+
return {
|
|
953
|
+
cleanup: () => {
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
let isDestroyed = false;
|
|
958
|
+
let currentActionHandle = null;
|
|
959
|
+
let eventUnsubscribe = null;
|
|
960
|
+
let routeWatcher = null;
|
|
961
|
+
const cleanupCurrentStep = async () => {
|
|
962
|
+
if (eventUnsubscribe) {
|
|
963
|
+
eventUnsubscribe();
|
|
964
|
+
eventUnsubscribe = null;
|
|
965
|
+
}
|
|
966
|
+
if (currentActionHandle == null ? void 0 : currentActionHandle.isApplied()) {
|
|
967
|
+
await currentActionHandle.revert();
|
|
968
|
+
currentActionHandle = null;
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
const advanceToStep = async (nextStepId) => {
|
|
972
|
+
if (isDestroyed)
|
|
973
|
+
return;
|
|
974
|
+
await cleanupCurrentStep();
|
|
975
|
+
if (nextStepId === "end") {
|
|
976
|
+
clearTourState();
|
|
977
|
+
context.publishEvent("tour.completed", {
|
|
978
|
+
tourId,
|
|
979
|
+
totalSteps: steps.length
|
|
980
|
+
});
|
|
981
|
+
isDestroyed = true;
|
|
982
|
+
return;
|
|
983
|
+
}
|
|
984
|
+
const nextStep = steps.find((s) => s.id === nextStepId);
|
|
985
|
+
if (!nextStep) {
|
|
986
|
+
console.error(`[Tour] Step "${nextStepId}" not found`);
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
state.currentStepId = nextStepId;
|
|
990
|
+
saveTourState(state);
|
|
991
|
+
context.publishEvent("tour.step_changed", {
|
|
992
|
+
tourId,
|
|
993
|
+
previousStepId: currentStep.id,
|
|
994
|
+
nextStepId
|
|
995
|
+
});
|
|
996
|
+
if (nextStep.route && nextStep.route !== getCurrentRoute()) {
|
|
997
|
+
context.publishEvent("tour.awaiting_navigation", {
|
|
998
|
+
tourId,
|
|
999
|
+
stepId: nextStepId,
|
|
1000
|
+
targetRoute: nextStep.route
|
|
1001
|
+
});
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
await executeStep(nextStep);
|
|
1005
|
+
};
|
|
1006
|
+
const executeStep = async (step) => {
|
|
1007
|
+
if (isDestroyed)
|
|
1008
|
+
return;
|
|
1009
|
+
context.publishEvent("tour.step_started", {
|
|
1010
|
+
tourId,
|
|
1011
|
+
stepId: step.id,
|
|
1012
|
+
stepIndex: steps.findIndex((s) => s.id === step.id),
|
|
1013
|
+
totalSteps: steps.length
|
|
1014
|
+
});
|
|
1015
|
+
try {
|
|
1016
|
+
currentActionHandle = await context.applyAction(step.action);
|
|
1017
|
+
} catch (error2) {
|
|
1018
|
+
console.error(`[Tour] Failed to execute step "${step.id}":`, error2);
|
|
1019
|
+
context.publishEvent("tour.step_failed", {
|
|
1020
|
+
tourId,
|
|
1021
|
+
stepId: step.id,
|
|
1022
|
+
error: String(error2)
|
|
1023
|
+
});
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
if (step.onAction && context.subscribeEvent) {
|
|
1027
|
+
eventUnsubscribe = context.subscribeEvent("action.modal_cta_clicked", (props) => {
|
|
1028
|
+
const actionId = props == null ? void 0 : props.actionId;
|
|
1029
|
+
if (actionId && step.onAction) {
|
|
1030
|
+
const nextStepId = step.onAction[actionId];
|
|
1031
|
+
if (nextStepId) {
|
|
1032
|
+
advanceToStep(nextStepId);
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
});
|
|
1036
|
+
const tooltipUnsubscribe = context.subscribeEvent("action.tooltip_cta_clicked", (props) => {
|
|
1037
|
+
const actionId = props == null ? void 0 : props.actionId;
|
|
1038
|
+
if (actionId && step.onAction) {
|
|
1039
|
+
const nextStepId = step.onAction[actionId];
|
|
1040
|
+
if (nextStepId) {
|
|
1041
|
+
advanceToStep(nextStepId);
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
});
|
|
1045
|
+
const originalUnsubscribe = eventUnsubscribe;
|
|
1046
|
+
eventUnsubscribe = () => {
|
|
1047
|
+
originalUnsubscribe();
|
|
1048
|
+
tooltipUnsubscribe();
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
};
|
|
1052
|
+
const setupRouteWatcher = () => {
|
|
1053
|
+
let lastPath = getCurrentRoute();
|
|
1054
|
+
const checkRoute = () => {
|
|
1055
|
+
const currentPath = getCurrentRoute();
|
|
1056
|
+
if (currentPath !== lastPath) {
|
|
1057
|
+
lastPath = currentPath;
|
|
1058
|
+
context.publishEvent("tour.route_changed", {
|
|
1059
|
+
tourId,
|
|
1060
|
+
newRoute: currentPath
|
|
1061
|
+
});
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1064
|
+
if (context.subscribeNavigation) {
|
|
1065
|
+
return context.subscribeNavigation(() => checkRoute());
|
|
1066
|
+
}
|
|
1067
|
+
window.addEventListener("popstate", checkRoute);
|
|
1068
|
+
const origPushState = history.pushState.bind(history);
|
|
1069
|
+
const origReplaceState = history.replaceState.bind(history);
|
|
1070
|
+
history.pushState = (...args) => {
|
|
1071
|
+
origPushState(...args);
|
|
1072
|
+
queueMicrotask(checkRoute);
|
|
1073
|
+
};
|
|
1074
|
+
history.replaceState = (...args) => {
|
|
1075
|
+
origReplaceState(...args);
|
|
1076
|
+
queueMicrotask(checkRoute);
|
|
1077
|
+
};
|
|
1078
|
+
return () => {
|
|
1079
|
+
window.removeEventListener("popstate", checkRoute);
|
|
1080
|
+
history.pushState = origPushState;
|
|
1081
|
+
history.replaceState = origReplaceState;
|
|
1082
|
+
};
|
|
1083
|
+
};
|
|
1084
|
+
routeWatcher = setupRouteWatcher();
|
|
1085
|
+
if (!isResumingTour) {
|
|
1086
|
+
context.publishEvent("tour.started", {
|
|
1087
|
+
tourId,
|
|
1088
|
+
totalSteps: steps.length,
|
|
1089
|
+
startStepId: state.currentStepId
|
|
1090
|
+
});
|
|
1091
|
+
} else {
|
|
1092
|
+
context.publishEvent("tour.resumed", {
|
|
1093
|
+
tourId,
|
|
1094
|
+
stepId: state.currentStepId
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
await executeStep(currentStep);
|
|
1098
|
+
const cleanup = async () => {
|
|
1099
|
+
isDestroyed = true;
|
|
1100
|
+
activeTours.delete(tourId);
|
|
1101
|
+
await cleanupCurrentStep();
|
|
1102
|
+
if (routeWatcher) {
|
|
1103
|
+
routeWatcher();
|
|
1104
|
+
}
|
|
1105
|
+
context.publishEvent("tour.paused", {
|
|
1106
|
+
tourId,
|
|
1107
|
+
stepId: state.currentStepId
|
|
1108
|
+
});
|
|
1109
|
+
};
|
|
1110
|
+
activeTours.set(tourId, { cleanup });
|
|
1111
|
+
return { cleanup };
|
|
1112
|
+
};
|
|
1113
|
+
|
|
360
1114
|
// ../design-system/src/tokens/colors.ts
|
|
361
1115
|
var base = {
|
|
362
1116
|
white: "#ffffff",
|
|
@@ -959,6 +1713,13 @@ function sanitizeHtml2(html) {
|
|
|
959
1713
|
}
|
|
960
1714
|
|
|
961
1715
|
// ../adaptives/adaptive-overlays/dist/modal.js
|
|
1716
|
+
var V = {
|
|
1717
|
+
bg: "var(--sc-overlay-background, #ffffff)",
|
|
1718
|
+
title: "var(--sc-overlay-title-color, var(--sc-overlay-text-color, #111827))",
|
|
1719
|
+
text: "var(--sc-overlay-text-color, #4b5563)",
|
|
1720
|
+
accent: "var(--sc-color-primary, #4f46e5)",
|
|
1721
|
+
radius: "var(--sc-border-radius, 12px)"
|
|
1722
|
+
};
|
|
962
1723
|
var executeModal = async (action, context) => {
|
|
963
1724
|
var _a2, _b;
|
|
964
1725
|
const { content, size = "md", blocking = false, scrim, dismiss, ctaButtons } = action;
|
|
@@ -985,8 +1746,8 @@ var executeModal = async (action, context) => {
|
|
|
985
1746
|
transform: translate(-50%, -50%) scale(0.95);
|
|
986
1747
|
max-width: ${sizeMap[size]};
|
|
987
1748
|
width: 90%;
|
|
988
|
-
background: ${
|
|
989
|
-
border-radius:
|
|
1749
|
+
background: ${V.bg};
|
|
1750
|
+
border-radius: ${V.radius};
|
|
990
1751
|
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
991
1752
|
z-index: 2147483646;
|
|
992
1753
|
opacity: 0;
|
|
@@ -995,9 +1756,9 @@ var executeModal = async (action, context) => {
|
|
|
995
1756
|
`;
|
|
996
1757
|
let html = "";
|
|
997
1758
|
if (content.title) {
|
|
998
|
-
html += `<h2 class="syntro-modal-title" style="margin: 0 0 12px 0; font-size: 18px; font-weight: 600; color:
|
|
1759
|
+
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>`;
|
|
999
1760
|
}
|
|
1000
|
-
html += `<div class="syntro-modal-body" style="color:
|
|
1761
|
+
html += `<div class="syntro-modal-body" style="color: ${V.text}; line-height: 1.5;">${sanitizeHtml2(content.body)}</div>`;
|
|
1001
1762
|
if ((dismiss == null ? void 0 : dismiss.closeButton) !== false) {
|
|
1002
1763
|
html += `
|
|
1003
1764
|
<button class="syntro-modal-close" data-syntro-action="dismiss" style="
|
|
@@ -1008,7 +1769,8 @@ var executeModal = async (action, context) => {
|
|
|
1008
1769
|
border: none;
|
|
1009
1770
|
cursor: pointer;
|
|
1010
1771
|
padding: 4px;
|
|
1011
|
-
color:
|
|
1772
|
+
color: ${V.text};
|
|
1773
|
+
opacity: 0.6;
|
|
1012
1774
|
" aria-label="Close">
|
|
1013
1775
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
|
|
1014
1776
|
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/>
|
|
@@ -1031,7 +1793,7 @@ var executeModal = async (action, context) => {
|
|
|
1031
1793
|
font-weight: 500;
|
|
1032
1794
|
cursor: pointer;
|
|
1033
1795
|
transition: background 150ms ease;
|
|
1034
|
-
${isPrimary ?
|
|
1796
|
+
${isPrimary ? `background: ${V.accent}; color: white; border: none;` : `background: transparent; color: ${V.accent}; border: 1px solid currentColor; opacity: 0.7;`}
|
|
1035
1797
|
"
|
|
1036
1798
|
>
|
|
1037
1799
|
${sanitizeHtml2(btn.label)}
|
|
@@ -1297,26 +2059,40 @@ function showTooltip(anchorEl, overlayRoot, opts) {
|
|
|
1297
2059
|
}
|
|
1298
2060
|
const attachTrigger = () => {
|
|
1299
2061
|
if (opts.trigger === "hover") {
|
|
1300
|
-
|
|
2062
|
+
let hideTimeout = null;
|
|
2063
|
+
const show = () => {
|
|
2064
|
+
if (hideTimeout) {
|
|
2065
|
+
clearTimeout(hideTimeout);
|
|
2066
|
+
hideTimeout = null;
|
|
2067
|
+
}
|
|
1301
2068
|
div.style.visibility = "visible";
|
|
1302
2069
|
div.style.opacity = "1";
|
|
1303
2070
|
};
|
|
1304
|
-
const
|
|
1305
|
-
|
|
1306
|
-
|
|
2071
|
+
const scheduleHide = () => {
|
|
2072
|
+
hideTimeout = setTimeout(() => {
|
|
2073
|
+
div.style.visibility = "hidden";
|
|
2074
|
+
div.style.opacity = "0";
|
|
2075
|
+
hideTimeout = null;
|
|
2076
|
+
}, 100);
|
|
1307
2077
|
};
|
|
1308
2078
|
div.style.visibility = "hidden";
|
|
1309
2079
|
div.style.opacity = "0";
|
|
1310
2080
|
div.style.transition = "opacity 200ms ease, visibility 200ms";
|
|
1311
|
-
anchorEl.addEventListener("mouseenter",
|
|
1312
|
-
anchorEl.addEventListener("mouseleave",
|
|
1313
|
-
|
|
1314
|
-
|
|
2081
|
+
anchorEl.addEventListener("mouseenter", show);
|
|
2082
|
+
anchorEl.addEventListener("mouseleave", scheduleHide);
|
|
2083
|
+
div.addEventListener("mouseenter", show);
|
|
2084
|
+
div.addEventListener("mouseleave", scheduleHide);
|
|
2085
|
+
anchorEl.addEventListener("focus", show);
|
|
2086
|
+
anchorEl.addEventListener("blur", scheduleHide);
|
|
1315
2087
|
return () => {
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
anchorEl.removeEventListener("
|
|
1319
|
-
anchorEl.removeEventListener("
|
|
2088
|
+
if (hideTimeout)
|
|
2089
|
+
clearTimeout(hideTimeout);
|
|
2090
|
+
anchorEl.removeEventListener("mouseenter", show);
|
|
2091
|
+
anchorEl.removeEventListener("mouseleave", scheduleHide);
|
|
2092
|
+
div.removeEventListener("mouseenter", show);
|
|
2093
|
+
div.removeEventListener("mouseleave", scheduleHide);
|
|
2094
|
+
anchorEl.removeEventListener("focus", show);
|
|
2095
|
+
anchorEl.removeEventListener("blur", scheduleHide);
|
|
1320
2096
|
};
|
|
1321
2097
|
}
|
|
1322
2098
|
if (opts.trigger === "click") {
|
|
@@ -1366,21 +2142,330 @@ function showTooltip(anchorEl, overlayRoot, opts) {
|
|
|
1366
2142
|
return handle;
|
|
1367
2143
|
}
|
|
1368
2144
|
|
|
2145
|
+
// ../adaptives/adaptive-overlays/dist/WorkflowWidget.js
|
|
2146
|
+
import { jsx as _jsx2 } from "react/jsx-runtime";
|
|
2147
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2148
|
+
import { createRoot } from "react-dom/client";
|
|
2149
|
+
|
|
2150
|
+
// ../adaptives/adaptive-overlays/dist/WorkflowTracker.js
|
|
2151
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2152
|
+
function ProgressBar({ completed, total }) {
|
|
2153
|
+
const percent = total > 0 ? Math.round(completed / total * 100) : 0;
|
|
2154
|
+
return _jsx("div", { className: "se-w-full se-h-1.5 se-rounded-full se-bg-white/[0.08] se-overflow-hidden", children: _jsx("div", { role: "progressbar", "aria-valuenow": percent, "aria-valuemin": 0, "aria-valuemax": 100, className: "se-h-full se-rounded-full se-bg-blue-5 se-transition-all se-duration-300", style: { width: `${percent}%` } }) });
|
|
2155
|
+
}
|
|
2156
|
+
function StepItem({ step, isCompleted, isCurrent, tourId, onStepClick }) {
|
|
2157
|
+
return _jsxs("button", { type: "button", "data-testid": `step-${step.id}`, "data-current": isCurrent ? "true" : void 0, "data-completed": isCompleted ? "true" : void 0, "aria-current": isCurrent ? "step" : void 0, className: `se-flex se-items-center se-gap-2 se-w-full se-py-1.5 se-px-2 se-rounded se-border-none se-bg-transparent se-cursor-pointer se-text-left se-text-xs ${isCurrent ? "se-font-semibold se-text-slate-grey-10" : "se-text-slate-grey-8"}`, onClick: () => onStepClick(tourId, step.id), children: [_jsx("span", { className: "se-shrink-0 se-w-4 se-text-center", children: isCompleted ? _jsx("span", { role: "img", "aria-label": "completed", className: "se-text-green-5", children: "\u2713" }) : isCurrent ? _jsx("span", { className: "se-inline-block se-w-1.5 se-h-1.5 se-rounded-full se-bg-blue-5" }) : _jsx("span", { className: "se-inline-block se-w-1.5 se-h-1.5 se-rounded-full se-bg-white/[0.12]" }) }), _jsx("span", { className: "se-flex-1 se-overflow-hidden se-text-ellipsis se-whitespace-nowrap", children: step.title })] });
|
|
2158
|
+
}
|
|
2159
|
+
function WorkflowCard({ workflow, expanded, onStepClick, onDismiss }) {
|
|
2160
|
+
const completedCount = workflow.completedSteps.length;
|
|
2161
|
+
const totalSteps = workflow.steps.length;
|
|
2162
|
+
return _jsxs("div", { className: "se-p-3 se-rounded-lg se-border se-border-white/[0.08] se-bg-white/[0.02]", children: [_jsxs("div", { className: "se-flex se-items-center se-gap-2 se-mb-2", children: [workflow.meta.icon && _jsx("span", { "data-testid": "workflow-icon", className: "se-shrink-0 se-text-sm", children: workflow.meta.icon }), _jsx("span", { className: "se-flex-1 se-text-[13px] se-font-semibold se-text-slate-grey-10 se-overflow-hidden se-text-ellipsis se-whitespace-nowrap", children: workflow.meta.title }), _jsx("button", { type: "button", "data-testid": `dismiss-${workflow.tourId}`, className: "se-shrink-0 se-py-0.5 se-px-1.5 se-rounded se-border-none se-bg-transparent se-text-slate-grey-7 se-text-xs se-cursor-pointer se-leading-none", onClick: () => onDismiss(workflow.tourId), "aria-label": `Dismiss ${workflow.meta.title}`, children: "\u2715" })] }), _jsxs("div", { className: "se-mb-2", children: [_jsx(ProgressBar, { completed: completedCount, total: totalSteps }), _jsxs("div", { className: "se-text-[10px] se-text-slate-grey-7 se-mt-1", children: [completedCount, " of ", totalSteps, " steps"] })] }), _jsx("div", { className: "se-flex se-flex-col", children: workflow.steps.map((step) => _jsx(StepItem, { step, isCompleted: workflow.completedSteps.includes(step.id), isCurrent: workflow.currentStepId === step.id, tourId: workflow.tourId, onStepClick }, step.id)) }), expanded && workflow.meta.description && _jsx("div", { className: "se-mt-2 se-text-[11px] se-text-slate-grey-7", children: workflow.meta.description })] });
|
|
2163
|
+
}
|
|
2164
|
+
function WorkflowTracker({ workflows, expanded, onStepClick, onDismiss }) {
|
|
2165
|
+
if (workflows.length === 0) {
|
|
2166
|
+
return _jsx("div", { className: "se-flex se-items-center se-justify-center se-py-6 se-text-xs se-text-slate-grey-7", children: "No active workflows" });
|
|
2167
|
+
}
|
|
2168
|
+
return _jsx("div", { className: "se-flex se-flex-col se-gap-2", children: workflows.map((workflow) => _jsx(WorkflowCard, { workflow, expanded, onStepClick, onDismiss }, workflow.tourId)) });
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2171
|
+
// ../adaptives/adaptive-overlays/dist/WorkflowWidget.js
|
|
2172
|
+
function showWorkflowToast(container, notification) {
|
|
2173
|
+
const toast = document.createElement("div");
|
|
2174
|
+
toast.setAttribute("data-testid", "workflow-toast");
|
|
2175
|
+
toast.className = "se-fixed se-bottom-4 se-right-4 se-z-50";
|
|
2176
|
+
Object.assign(toast.style, {
|
|
2177
|
+
position: "fixed",
|
|
2178
|
+
bottom: "16px",
|
|
2179
|
+
right: "16px",
|
|
2180
|
+
zIndex: "2147483646",
|
|
2181
|
+
padding: "12px 16px",
|
|
2182
|
+
borderRadius: "8px",
|
|
2183
|
+
backgroundColor: "var(--se-color-bg-surface, #fff)",
|
|
2184
|
+
color: "var(--se-color-text-primary, #1a1a1a)",
|
|
2185
|
+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
|
2186
|
+
maxWidth: "320px",
|
|
2187
|
+
fontFamily: "var(--se-font-family, system-ui, sans-serif)",
|
|
2188
|
+
fontSize: "14px",
|
|
2189
|
+
lineHeight: "1.4",
|
|
2190
|
+
transition: "opacity 0.3s ease"
|
|
2191
|
+
});
|
|
2192
|
+
const titleEl = document.createElement("div");
|
|
2193
|
+
titleEl.className = "se-font-semibold";
|
|
2194
|
+
titleEl.style.fontWeight = "600";
|
|
2195
|
+
titleEl.textContent = notification.title;
|
|
2196
|
+
toast.appendChild(titleEl);
|
|
2197
|
+
if (notification.body) {
|
|
2198
|
+
const bodyEl = document.createElement("div");
|
|
2199
|
+
bodyEl.className = "se-mt-1 se-text-sm";
|
|
2200
|
+
bodyEl.style.marginTop = "4px";
|
|
2201
|
+
bodyEl.style.fontSize = "13px";
|
|
2202
|
+
bodyEl.style.color = "var(--se-color-text-secondary, #666)";
|
|
2203
|
+
bodyEl.textContent = notification.body;
|
|
2204
|
+
toast.appendChild(bodyEl);
|
|
2205
|
+
}
|
|
2206
|
+
container.appendChild(toast);
|
|
2207
|
+
let removeTimer;
|
|
2208
|
+
const fadeTimer = setTimeout(() => {
|
|
2209
|
+
toast.style.opacity = "0";
|
|
2210
|
+
removeTimer = setTimeout(() => {
|
|
2211
|
+
toast.remove();
|
|
2212
|
+
}, 300);
|
|
2213
|
+
}, 4e3);
|
|
2214
|
+
return () => {
|
|
2215
|
+
clearTimeout(fadeTimer);
|
|
2216
|
+
clearTimeout(removeTimer);
|
|
2217
|
+
toast.remove();
|
|
2218
|
+
};
|
|
2219
|
+
}
|
|
2220
|
+
function extractWorkflowsFromActive(activeActions) {
|
|
2221
|
+
const workflows = /* @__PURE__ */ new Map();
|
|
2222
|
+
for (const entry of activeActions) {
|
|
2223
|
+
const action = entry.action;
|
|
2224
|
+
if (action.kind === "core:tour" && action.workflow && action.tourId) {
|
|
2225
|
+
const meta = action.workflow;
|
|
2226
|
+
const rawSteps = action.steps || [];
|
|
2227
|
+
const steps = rawSteps.map((s) => {
|
|
2228
|
+
var _a2;
|
|
2229
|
+
return {
|
|
2230
|
+
id: s.id,
|
|
2231
|
+
title: ((_a2 = meta.stepTitles) == null ? void 0 : _a2[s.id]) || s.id
|
|
2232
|
+
};
|
|
2233
|
+
});
|
|
2234
|
+
workflows.set(action.tourId, { meta, steps });
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
return workflows;
|
|
2238
|
+
}
|
|
2239
|
+
function WorkflowWidgetInner({ runtime: runtime3 }) {
|
|
2240
|
+
var _a2, _b;
|
|
2241
|
+
const [actionVersion, setActionVersion] = useState(0);
|
|
2242
|
+
const tourWorkflows = useMemo(() => {
|
|
2243
|
+
var _a3, _b2;
|
|
2244
|
+
const active = ((_b2 = (_a3 = runtime3 == null ? void 0 : runtime3.actions) == null ? void 0 : _a3.getActive) == null ? void 0 : _b2.call(_a3)) || [];
|
|
2245
|
+
return extractWorkflowsFromActive(active);
|
|
2246
|
+
}, [runtime3, actionVersion]);
|
|
2247
|
+
const tourWorkflowsRef = useRef(tourWorkflows);
|
|
2248
|
+
tourWorkflowsRef.current = tourWorkflows;
|
|
2249
|
+
useEffect(() => {
|
|
2250
|
+
var _a3;
|
|
2251
|
+
if (!((_a3 = runtime3 == null ? void 0 : runtime3.events) == null ? void 0 : _a3.subscribe))
|
|
2252
|
+
return;
|
|
2253
|
+
return runtime3.events.subscribe({ names: ["tour.started", "tour.resumed"] }, () => setActionVersion((v) => v + 1));
|
|
2254
|
+
}, [runtime3]);
|
|
2255
|
+
const stateNs = useMemo(() => {
|
|
2256
|
+
var _a3, _b2, _c;
|
|
2257
|
+
return (_c = (_b2 = (_a3 = runtime3 == null ? void 0 : runtime3.state) == null ? void 0 : _a3.user) == null ? void 0 : _b2.ns) == null ? void 0 : _c.call(_b2, "workflows");
|
|
2258
|
+
}, [runtime3]);
|
|
2259
|
+
const notifiedRef = useRef(/* @__PURE__ */ new Set());
|
|
2260
|
+
const toastCleanupsRef = useRef([]);
|
|
2261
|
+
const containerRef = useRef(null);
|
|
2262
|
+
const completedMapRef = useRef({});
|
|
2263
|
+
const [workflowEntries, setWorkflowEntries] = useState([]);
|
|
2264
|
+
const persistInitialized = useRef(false);
|
|
2265
|
+
if (!persistInitialized.current && stateNs) {
|
|
2266
|
+
const notified = ((_a2 = stateNs.get) == null ? void 0 : _a2.call(stateNs, "notified")) || [];
|
|
2267
|
+
for (const id of notified) {
|
|
2268
|
+
notifiedRef.current.add(id);
|
|
2269
|
+
}
|
|
2270
|
+
const completed = ((_b = stateNs.get) == null ? void 0 : _b.call(stateNs, "completed")) || {};
|
|
2271
|
+
completedMapRef.current = { ...completed };
|
|
2272
|
+
persistInitialized.current = true;
|
|
2273
|
+
}
|
|
2274
|
+
useEffect(() => {
|
|
2275
|
+
var _a3, _b2, _c;
|
|
2276
|
+
if (tourWorkflows.size === 0)
|
|
2277
|
+
return;
|
|
2278
|
+
const dismissed = ((_a3 = stateNs == null ? void 0 : stateNs.get) == null ? void 0 : _a3.call(stateNs, "dismissed")) || [];
|
|
2279
|
+
const completed = ((_b2 = stateNs == null ? void 0 : stateNs.get) == null ? void 0 : _b2.call(stateNs, "completed")) || {};
|
|
2280
|
+
setWorkflowEntries((prev) => {
|
|
2281
|
+
const existingIds = new Set(prev.map((e) => e.tourId));
|
|
2282
|
+
const newEntries = [];
|
|
2283
|
+
for (const [tourId, { meta, steps }] of tourWorkflows) {
|
|
2284
|
+
if (existingIds.has(tourId))
|
|
2285
|
+
continue;
|
|
2286
|
+
let status = "active";
|
|
2287
|
+
if (dismissed.includes(tourId)) {
|
|
2288
|
+
status = "dismissed";
|
|
2289
|
+
} else if (completed[tourId]) {
|
|
2290
|
+
status = "completed";
|
|
2291
|
+
}
|
|
2292
|
+
newEntries.push({
|
|
2293
|
+
tourId,
|
|
2294
|
+
meta,
|
|
2295
|
+
steps,
|
|
2296
|
+
currentStepId: null,
|
|
2297
|
+
completedSteps: [],
|
|
2298
|
+
status,
|
|
2299
|
+
completedAt: completed[tourId] || void 0
|
|
2300
|
+
});
|
|
2301
|
+
}
|
|
2302
|
+
return newEntries.length > 0 ? [...prev, ...newEntries] : prev;
|
|
2303
|
+
});
|
|
2304
|
+
for (const [tourId, { meta }] of tourWorkflows) {
|
|
2305
|
+
if (!notifiedRef.current.has(tourId) && meta.notification && containerRef.current && !dismissed.includes(tourId) && !completed[tourId]) {
|
|
2306
|
+
notifiedRef.current.add(tourId);
|
|
2307
|
+
(_c = stateNs == null ? void 0 : stateNs.set) == null ? void 0 : _c.call(stateNs, "notified", [...notifiedRef.current]);
|
|
2308
|
+
const cleanup = showWorkflowToast(containerRef.current, meta.notification);
|
|
2309
|
+
toastCleanupsRef.current.push(cleanup);
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
}, [tourWorkflows, stateNs]);
|
|
2313
|
+
useEffect(() => {
|
|
2314
|
+
var _a3;
|
|
2315
|
+
if (!((_a3 = runtime3 == null ? void 0 : runtime3.events) == null ? void 0 : _a3.subscribe))
|
|
2316
|
+
return;
|
|
2317
|
+
const unsubscribe = runtime3.events.subscribe({ patterns: ["^tour\\."] }, (event) => {
|
|
2318
|
+
var _a4;
|
|
2319
|
+
const tourId = (_a4 = event.props) == null ? void 0 : _a4.tourId;
|
|
2320
|
+
if (!tourId)
|
|
2321
|
+
return;
|
|
2322
|
+
const currentWorkflows = tourWorkflowsRef.current;
|
|
2323
|
+
if (!currentWorkflows.has(tourId) && event.name === "tour.started") {
|
|
2324
|
+
setActionVersion((v) => v + 1);
|
|
2325
|
+
return;
|
|
2326
|
+
}
|
|
2327
|
+
if (!currentWorkflows.has(tourId))
|
|
2328
|
+
return;
|
|
2329
|
+
setWorkflowEntries((prev) => {
|
|
2330
|
+
const updated = prev.map((entry) => {
|
|
2331
|
+
var _a5, _b2, _c, _d, _e, _f, _g, _h;
|
|
2332
|
+
if (entry.tourId !== tourId)
|
|
2333
|
+
return entry;
|
|
2334
|
+
switch (event.name) {
|
|
2335
|
+
case "tour.started": {
|
|
2336
|
+
const startStepId = ((_a5 = event.props) == null ? void 0 : _a5.startStepId) || ((_b2 = entry.steps[0]) == null ? void 0 : _b2.id) || null;
|
|
2337
|
+
if (!notifiedRef.current.has(tourId)) {
|
|
2338
|
+
notifiedRef.current.add(tourId);
|
|
2339
|
+
(_c = stateNs == null ? void 0 : stateNs.set) == null ? void 0 : _c.call(stateNs, "notified", [...notifiedRef.current]);
|
|
2340
|
+
const workflow = currentWorkflows.get(tourId);
|
|
2341
|
+
if ((workflow == null ? void 0 : workflow.meta.notification) && containerRef.current) {
|
|
2342
|
+
const cleanup = showWorkflowToast(containerRef.current, workflow.meta.notification);
|
|
2343
|
+
toastCleanupsRef.current.push(cleanup);
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
const activeIds = prev.filter((e) => e.status === "active" || e.tourId === tourId).map((e) => e.tourId);
|
|
2347
|
+
if (!activeIds.includes(tourId)) {
|
|
2348
|
+
activeIds.push(tourId);
|
|
2349
|
+
}
|
|
2350
|
+
(_d = stateNs == null ? void 0 : stateNs.set) == null ? void 0 : _d.call(stateNs, "active", [...new Set(activeIds)]);
|
|
2351
|
+
return {
|
|
2352
|
+
...entry,
|
|
2353
|
+
status: "active",
|
|
2354
|
+
currentStepId: startStepId,
|
|
2355
|
+
completedSteps: entry.status === "active" ? entry.completedSteps : []
|
|
2356
|
+
};
|
|
2357
|
+
}
|
|
2358
|
+
case "tour.step_started": {
|
|
2359
|
+
const stepId = (_e = event.props) == null ? void 0 : _e.stepId;
|
|
2360
|
+
return {
|
|
2361
|
+
...entry,
|
|
2362
|
+
currentStepId: stepId || entry.currentStepId
|
|
2363
|
+
};
|
|
2364
|
+
}
|
|
2365
|
+
case "tour.step_changed": {
|
|
2366
|
+
const previousStepId = (_f = event.props) == null ? void 0 : _f.previousStepId;
|
|
2367
|
+
const nextStepId = (_g = event.props) == null ? void 0 : _g.nextStepId;
|
|
2368
|
+
const completedSteps = previousStepId && !entry.completedSteps.includes(previousStepId) ? [...entry.completedSteps, previousStepId] : entry.completedSteps;
|
|
2369
|
+
return {
|
|
2370
|
+
...entry,
|
|
2371
|
+
currentStepId: nextStepId || entry.currentStepId,
|
|
2372
|
+
completedSteps
|
|
2373
|
+
};
|
|
2374
|
+
}
|
|
2375
|
+
case "tour.completed": {
|
|
2376
|
+
const completedAt = Date.now();
|
|
2377
|
+
completedMapRef.current[tourId] = completedAt;
|
|
2378
|
+
(_h = stateNs == null ? void 0 : stateNs.set) == null ? void 0 : _h.call(stateNs, "completed", { ...completedMapRef.current });
|
|
2379
|
+
return {
|
|
2380
|
+
...entry,
|
|
2381
|
+
status: "completed",
|
|
2382
|
+
currentStepId: null,
|
|
2383
|
+
completedSteps: entry.steps.map((s) => s.id),
|
|
2384
|
+
completedAt
|
|
2385
|
+
};
|
|
2386
|
+
}
|
|
2387
|
+
case "tour.paused": {
|
|
2388
|
+
return entry;
|
|
2389
|
+
}
|
|
2390
|
+
default:
|
|
2391
|
+
return entry;
|
|
2392
|
+
}
|
|
2393
|
+
});
|
|
2394
|
+
return updated;
|
|
2395
|
+
});
|
|
2396
|
+
});
|
|
2397
|
+
return () => {
|
|
2398
|
+
unsubscribe();
|
|
2399
|
+
for (const cleanup of toastCleanupsRef.current) {
|
|
2400
|
+
cleanup();
|
|
2401
|
+
}
|
|
2402
|
+
toastCleanupsRef.current = [];
|
|
2403
|
+
};
|
|
2404
|
+
}, [runtime3, stateNs]);
|
|
2405
|
+
const handleStepClick = useCallback((tourId, stepId) => {
|
|
2406
|
+
var _a3, _b2;
|
|
2407
|
+
(_b2 = (_a3 = runtime3 == null ? void 0 : runtime3.events) == null ? void 0 : _a3.publish) == null ? void 0 : _b2.call(_a3, "workflow:jump_to_step", { tourId, stepId });
|
|
2408
|
+
}, [runtime3]);
|
|
2409
|
+
const handleDismiss = useCallback((tourId) => {
|
|
2410
|
+
setWorkflowEntries((prev) => {
|
|
2411
|
+
var _a3;
|
|
2412
|
+
const updated = prev.map((entry) => entry.tourId === tourId ? { ...entry, status: "dismissed" } : entry);
|
|
2413
|
+
const dismissedIds = updated.filter((e) => e.status === "dismissed").map((e) => e.tourId);
|
|
2414
|
+
(_a3 = stateNs == null ? void 0 : stateNs.set) == null ? void 0 : _a3.call(stateNs, "dismissed", dismissedIds);
|
|
2415
|
+
return updated;
|
|
2416
|
+
});
|
|
2417
|
+
}, [stateNs]);
|
|
2418
|
+
const activeWorkflows = useMemo(() => workflowEntries.filter((w) => w.status === "active"), [workflowEntries]);
|
|
2419
|
+
return _jsx2("div", { ref: containerRef, children: _jsx2(WorkflowTracker, { workflows: activeWorkflows, onStepClick: handleStepClick, onDismiss: handleDismiss }) });
|
|
2420
|
+
}
|
|
2421
|
+
var WorkflowMountableWidget = {
|
|
2422
|
+
mount(container, config) {
|
|
2423
|
+
const runtime3 = (config == null ? void 0 : config.runtime) || null;
|
|
2424
|
+
const root = createRoot(container);
|
|
2425
|
+
root.render(React.createElement(WorkflowWidgetInner, {
|
|
2426
|
+
runtime: runtime3
|
|
2427
|
+
}));
|
|
2428
|
+
return () => {
|
|
2429
|
+
root.unmount();
|
|
2430
|
+
};
|
|
2431
|
+
}
|
|
2432
|
+
};
|
|
2433
|
+
|
|
1369
2434
|
// ../adaptives/adaptive-overlays/dist/runtime.js
|
|
1370
2435
|
var executeHighlight = async (action, context) => {
|
|
1371
|
-
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1372
|
-
|
|
2436
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
2437
|
+
let anchorEl = context.resolveAnchor(action.anchorId);
|
|
2438
|
+
if (!anchorEl && context.waitForAnchor) {
|
|
2439
|
+
anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
|
|
2440
|
+
}
|
|
1373
2441
|
if (!anchorEl) {
|
|
1374
|
-
|
|
2442
|
+
console.warn(`[adaptive-overlays] Anchor not found after waiting: ${action.anchorId.selector}`);
|
|
2443
|
+
return { cleanup: () => {
|
|
2444
|
+
} };
|
|
2445
|
+
}
|
|
2446
|
+
const existing = anchorEl.getAttribute("data-syntro-highlight");
|
|
2447
|
+
if (existing) {
|
|
2448
|
+
const prev = context.overlayRoot.querySelectorAll(".syntro-spotlight-scrim, .syntro-spotlight-ring");
|
|
2449
|
+
prev.forEach((el) => el.remove());
|
|
2450
|
+
}
|
|
2451
|
+
anchorEl.setAttribute("data-syntro-highlight", "true");
|
|
2452
|
+
let ringColor = (_a2 = action.style) == null ? void 0 : _a2.color;
|
|
2453
|
+
if (!ringColor) {
|
|
2454
|
+
try {
|
|
2455
|
+
const primary = (_b = getComputedStyle(context.overlayRoot).getPropertyValue("--sc-color-primary")) == null ? void 0 : _b.trim();
|
|
2456
|
+
if (primary)
|
|
2457
|
+
ringColor = primary;
|
|
2458
|
+
} catch {
|
|
2459
|
+
}
|
|
1375
2460
|
}
|
|
1376
2461
|
const handle = showHighlight(anchorEl, context.overlayRoot, {
|
|
1377
|
-
paddingPx: (
|
|
1378
|
-
radiusPx: (
|
|
1379
|
-
scrimOpacity: (
|
|
1380
|
-
ringColor
|
|
1381
|
-
blocking: (
|
|
1382
|
-
onClickOutside: (
|
|
1383
|
-
onEsc: (
|
|
2462
|
+
paddingPx: (_d = (_c = action.style) == null ? void 0 : _c.paddingPx) != null ? _d : 12,
|
|
2463
|
+
radiusPx: (_f = (_e = action.style) == null ? void 0 : _e.radiusPx) != null ? _f : 12,
|
|
2464
|
+
scrimOpacity: (_h = (_g = action.style) == null ? void 0 : _g.scrimOpacity) != null ? _h : 0.55,
|
|
2465
|
+
ringColor,
|
|
2466
|
+
blocking: (_i = action.blocking) != null ? _i : false,
|
|
2467
|
+
onClickOutside: (_j = action.onClickOutside) != null ? _j : true,
|
|
2468
|
+
onEsc: (_k = action.onEsc) != null ? _k : true
|
|
1384
2469
|
});
|
|
1385
2470
|
context.publishEvent("action.applied", {
|
|
1386
2471
|
id: context.generateId(),
|
|
@@ -1390,33 +2475,82 @@ var executeHighlight = async (action, context) => {
|
|
|
1390
2475
|
return {
|
|
1391
2476
|
cleanup: () => {
|
|
1392
2477
|
handle.destroy();
|
|
2478
|
+
anchorEl.removeAttribute("data-syntro-highlight");
|
|
1393
2479
|
}
|
|
1394
2480
|
};
|
|
1395
2481
|
};
|
|
1396
2482
|
var executePulse = async (action, context) => {
|
|
1397
|
-
var _a2;
|
|
1398
|
-
|
|
2483
|
+
var _a2, _b, _c;
|
|
2484
|
+
let anchorEl = context.resolveAnchor(action.anchorId);
|
|
2485
|
+
if (!anchorEl && context.waitForAnchor) {
|
|
2486
|
+
anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
|
|
2487
|
+
}
|
|
1399
2488
|
if (!anchorEl) {
|
|
1400
|
-
|
|
2489
|
+
console.warn(`[adaptive-overlays] Anchor not found after waiting: ${action.anchorId.selector}`);
|
|
2490
|
+
return { cleanup: () => {
|
|
2491
|
+
} };
|
|
2492
|
+
}
|
|
2493
|
+
const duration = (_a2 = action.duration) != null ? _a2 : 4e3;
|
|
2494
|
+
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
2495
|
+
const parseHex = (hex) => ({
|
|
2496
|
+
r: parseInt(hex.slice(1, 3), 16),
|
|
2497
|
+
g: parseInt(hex.slice(3, 5), 16),
|
|
2498
|
+
b: parseInt(hex.slice(5, 7), 16)
|
|
2499
|
+
});
|
|
2500
|
+
const fallback = { r: 79, g: 70, b: 229 };
|
|
2501
|
+
let primary = fallback;
|
|
2502
|
+
let secondary = null;
|
|
2503
|
+
try {
|
|
2504
|
+
const styles = getComputedStyle(context.overlayRoot);
|
|
2505
|
+
const pHex = (_b = styles.getPropertyValue("--sc-color-primary")) == null ? void 0 : _b.trim();
|
|
2506
|
+
const sHex = (_c = styles.getPropertyValue("--sc-color-primary-hover")) == null ? void 0 : _c.trim();
|
|
2507
|
+
if ((pHex == null ? void 0 : pHex.startsWith("#")) && pHex.length >= 7) {
|
|
2508
|
+
primary = parseHex(pHex);
|
|
2509
|
+
}
|
|
2510
|
+
if ((sHex == null ? void 0 : sHex.startsWith("#")) && sHex.length >= 7) {
|
|
2511
|
+
secondary = parseHex(sHex);
|
|
2512
|
+
}
|
|
2513
|
+
} catch {
|
|
1401
2514
|
}
|
|
1402
|
-
const
|
|
1403
|
-
if (
|
|
1404
|
-
|
|
1405
|
-
|
|
2515
|
+
const existing = document.querySelector("[data-syntro-pulse-styles]");
|
|
2516
|
+
if (existing)
|
|
2517
|
+
existing.remove();
|
|
2518
|
+
const style = document.createElement("style");
|
|
2519
|
+
style.setAttribute("data-syntro-pulse-styles", "");
|
|
2520
|
+
const { r: pr, g: pg, b: pb } = primary;
|
|
2521
|
+
if (secondary) {
|
|
2522
|
+
const { r: sr, g: sg, b: sb } = secondary;
|
|
2523
|
+
style.textContent = `
|
|
2524
|
+
@keyframes syntro-pulse-anim {
|
|
2525
|
+
0%, 100% {
|
|
2526
|
+
box-shadow: 0 0 0 0 rgba(${pr}, ${pg}, ${pb}, 0.35);
|
|
2527
|
+
}
|
|
2528
|
+
25% {
|
|
2529
|
+
box-shadow: 0 0 0 12px rgba(${pr}, ${pg}, ${pb}, 0);
|
|
2530
|
+
}
|
|
2531
|
+
50% {
|
|
2532
|
+
box-shadow: 0 0 0 0 rgba(${sr}, ${sg}, ${sb}, 0.35);
|
|
2533
|
+
}
|
|
2534
|
+
75% {
|
|
2535
|
+
box-shadow: 0 0 0 12px rgba(${sr}, ${sg}, ${sb}, 0);
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
`;
|
|
2539
|
+
} else {
|
|
1406
2540
|
style.textContent = `
|
|
1407
2541
|
@keyframes syntro-pulse-anim {
|
|
1408
2542
|
0%, 100% {
|
|
1409
|
-
box-shadow: 0 0 0 0 rgba(
|
|
2543
|
+
box-shadow: 0 0 0 0 rgba(${pr}, ${pg}, ${pb}, 0.35);
|
|
1410
2544
|
}
|
|
1411
2545
|
50% {
|
|
1412
|
-
box-shadow: 0 0 0
|
|
2546
|
+
box-shadow: 0 0 0 12px rgba(${pr}, ${pg}, ${pb}, 0);
|
|
1413
2547
|
}
|
|
1414
2548
|
}
|
|
1415
2549
|
`;
|
|
1416
|
-
document.head.appendChild(style);
|
|
1417
2550
|
}
|
|
2551
|
+
document.head.appendChild(style);
|
|
1418
2552
|
const originalAnimation = anchorEl.style.animation;
|
|
1419
|
-
anchorEl.style.animation = "syntro-pulse-anim
|
|
2553
|
+
anchorEl.style.animation = "syntro-pulse-anim 2.5s cubic-bezier(0.4, 0, 0.6, 1) infinite";
|
|
1420
2554
|
anchorEl.setAttribute("data-syntro-pulse", "true");
|
|
1421
2555
|
const timeoutId = setTimeout(() => {
|
|
1422
2556
|
anchorEl.style.animation = originalAnimation;
|
|
@@ -1437,14 +2571,27 @@ var executePulse = async (action, context) => {
|
|
|
1437
2571
|
};
|
|
1438
2572
|
};
|
|
1439
2573
|
var executeBadge = async (action, context) => {
|
|
1440
|
-
var _a2;
|
|
1441
|
-
|
|
2574
|
+
var _a2, _b;
|
|
2575
|
+
let anchorEl = context.resolveAnchor(action.anchorId);
|
|
2576
|
+
if (!anchorEl && context.waitForAnchor) {
|
|
2577
|
+
anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
|
|
2578
|
+
}
|
|
1442
2579
|
if (!anchorEl) {
|
|
1443
|
-
|
|
2580
|
+
console.warn(`[adaptive-overlays] Anchor not found after waiting: ${action.anchorId.selector}`);
|
|
2581
|
+
return { cleanup: () => {
|
|
2582
|
+
} };
|
|
2583
|
+
}
|
|
2584
|
+
let badgeColor = "#4f46e5";
|
|
2585
|
+
try {
|
|
2586
|
+
const primary = (_a2 = getComputedStyle(context.overlayRoot).getPropertyValue("--sc-color-primary")) == null ? void 0 : _a2.trim();
|
|
2587
|
+
if ((primary == null ? void 0 : primary.startsWith("#")) && primary.length >= 7) {
|
|
2588
|
+
badgeColor = primary;
|
|
2589
|
+
}
|
|
2590
|
+
} catch {
|
|
1444
2591
|
}
|
|
1445
2592
|
const badge2 = document.createElement("div");
|
|
1446
2593
|
badge2.textContent = action.content;
|
|
1447
|
-
badge2.setAttribute("data-syntro-badge", action.anchorId);
|
|
2594
|
+
badge2.setAttribute("data-syntro-badge", action.anchorId.selector);
|
|
1448
2595
|
Object.assign(badge2.style, {
|
|
1449
2596
|
position: "absolute",
|
|
1450
2597
|
padding: "2px 6px",
|
|
@@ -1452,13 +2599,13 @@ var executeBadge = async (action, context) => {
|
|
|
1452
2599
|
fontWeight: "600",
|
|
1453
2600
|
lineHeight: "1",
|
|
1454
2601
|
color: "white",
|
|
1455
|
-
background:
|
|
2602
|
+
background: badgeColor,
|
|
1456
2603
|
borderRadius: "9999px",
|
|
1457
2604
|
pointerEvents: "none",
|
|
1458
2605
|
zIndex: "2147483646",
|
|
1459
2606
|
whiteSpace: "nowrap"
|
|
1460
2607
|
});
|
|
1461
|
-
const position = (
|
|
2608
|
+
const position = (_b = action.position) != null ? _b : "top-right";
|
|
1462
2609
|
const originalPosition = anchorEl.style.position;
|
|
1463
2610
|
if (getComputedStyle(anchorEl).position === "static") {
|
|
1464
2611
|
anchorEl.style.position = "relative";
|
|
@@ -1501,9 +2648,14 @@ var executeBadge = async (action, context) => {
|
|
|
1501
2648
|
};
|
|
1502
2649
|
var executeTooltip = async (action, context) => {
|
|
1503
2650
|
var _a2, _b, _c, _d;
|
|
1504
|
-
|
|
2651
|
+
let anchorEl = context.resolveAnchor(action.anchorId);
|
|
2652
|
+
if (!anchorEl && context.waitForAnchor) {
|
|
2653
|
+
anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
|
|
2654
|
+
}
|
|
1505
2655
|
if (!anchorEl) {
|
|
1506
|
-
|
|
2656
|
+
console.warn(`[adaptive-overlays] Anchor not found after waiting: ${action.anchorId.selector}`);
|
|
2657
|
+
return { cleanup: () => {
|
|
2658
|
+
} };
|
|
1507
2659
|
}
|
|
1508
2660
|
const { content } = action;
|
|
1509
2661
|
let html = "";
|
|
@@ -1576,14 +2728,27 @@ var executors2 = [
|
|
|
1576
2728
|
{ kind: "overlays:pulse", executor: executePulse },
|
|
1577
2729
|
{ kind: "overlays:badge", executor: executeBadge },
|
|
1578
2730
|
{ kind: "overlays:tooltip", executor: executeTooltip },
|
|
1579
|
-
{ kind: "overlays:modal", executor: executeModal }
|
|
2731
|
+
{ kind: "overlays:modal", executor: executeModal },
|
|
2732
|
+
{ kind: "core:tour", executor: executeTour },
|
|
2733
|
+
{ kind: "overlays:celebrate", executor: executeCelebrate }
|
|
1580
2734
|
];
|
|
1581
2735
|
var runtime2 = {
|
|
1582
2736
|
id: "adaptive-overlays",
|
|
1583
2737
|
version: "1.0.0",
|
|
1584
2738
|
name: "Overlays",
|
|
1585
|
-
description: "Tooltips, highlights, badges, modals,
|
|
1586
|
-
executors: executors2
|
|
2739
|
+
description: "Tooltips, highlights, badges, modals, celebrations, visual overlays, and workflow tracking",
|
|
2740
|
+
executors: executors2,
|
|
2741
|
+
widgets: [
|
|
2742
|
+
{
|
|
2743
|
+
id: "adaptive-overlays:workflow-tracker",
|
|
2744
|
+
component: WorkflowMountableWidget,
|
|
2745
|
+
metadata: {
|
|
2746
|
+
name: "Workflow Tracker",
|
|
2747
|
+
icon: "\u{1F4CB}",
|
|
2748
|
+
description: "Tracks multi-step workflow progress across tours"
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
]
|
|
1587
2752
|
};
|
|
1588
2753
|
|
|
1589
2754
|
// src/apps/AppContext.ts
|
|
@@ -2193,7 +3358,7 @@ function getAntiFlickerSnippet(config = {}) {
|
|
|
2193
3358
|
}
|
|
2194
3359
|
|
|
2195
3360
|
// src/version.ts
|
|
2196
|
-
var SDK_VERSION = "2.
|
|
3361
|
+
var SDK_VERSION = "2.6.0-canary.1";
|
|
2197
3362
|
|
|
2198
3363
|
// src/types.ts
|
|
2199
3364
|
var SDK_SCHEMA_VERSION = "2.0";
|
|
@@ -2434,44 +3599,69 @@ var createCanvasConfigFetcher = ({
|
|
|
2434
3599
|
};
|
|
2435
3600
|
|
|
2436
3601
|
// src/events/registerConfigPredicates.ts
|
|
2437
|
-
|
|
2438
|
-
|
|
3602
|
+
var ELEMENT_CHAIN_FIELDS = /* @__PURE__ */ new Set(["tag_name", "$el_text"]);
|
|
3603
|
+
function isElementChainField(key) {
|
|
3604
|
+
return ELEMENT_CHAIN_FIELDS.has(key) || key.startsWith("attr__");
|
|
3605
|
+
}
|
|
3606
|
+
function checkMatchOp(op, value) {
|
|
3607
|
+
if (op.equals !== void 0) {
|
|
3608
|
+
return value === op.equals;
|
|
3609
|
+
}
|
|
3610
|
+
if (op.contains !== void 0) {
|
|
3611
|
+
return typeof value === "string" && value.includes(op.contains);
|
|
3612
|
+
}
|
|
3613
|
+
return false;
|
|
3614
|
+
}
|
|
3615
|
+
function buildPredicate(counter) {
|
|
3616
|
+
const { events: eventNames, match } = counter;
|
|
3617
|
+
return (event) => {
|
|
3618
|
+
var _a2, _b;
|
|
3619
|
+
if (!eventNames.includes(event.name)) return false;
|
|
3620
|
+
if (match) {
|
|
3621
|
+
for (const [key, op] of Object.entries(match)) {
|
|
3622
|
+
if (isElementChainField(key)) {
|
|
3623
|
+
const elements = (_a2 = event.props) == null ? void 0 : _a2.elements;
|
|
3624
|
+
if (!elements) return false;
|
|
3625
|
+
const anyMatch = elements.some((el) => checkMatchOp(op, el[key]));
|
|
3626
|
+
if (!anyMatch) return false;
|
|
3627
|
+
} else {
|
|
3628
|
+
if (!checkMatchOp(op, (_b = event.props) == null ? void 0 : _b[key])) return false;
|
|
3629
|
+
}
|
|
3630
|
+
}
|
|
3631
|
+
}
|
|
3632
|
+
return true;
|
|
3633
|
+
};
|
|
3634
|
+
}
|
|
3635
|
+
function registerFromTriggerWhen(triggerWhen, accumulator) {
|
|
3636
|
+
for (const rule of triggerWhen.rules) {
|
|
3637
|
+
for (const cond of rule.conditions) {
|
|
3638
|
+
if (cond.type === "event_count" && cond.key) {
|
|
3639
|
+
const counter = cond.counter;
|
|
3640
|
+
const predicate = counter ? buildPredicate(counter) : () => true;
|
|
3641
|
+
accumulator.register(cond.key, predicate);
|
|
3642
|
+
}
|
|
3643
|
+
}
|
|
3644
|
+
}
|
|
3645
|
+
}
|
|
3646
|
+
function registerConfigPredicates(tiles, accumulator, actions) {
|
|
3647
|
+
var _a2, _b;
|
|
2439
3648
|
for (const tile of tiles) {
|
|
2440
3649
|
const props = tile.props;
|
|
2441
3650
|
if (!props) continue;
|
|
2442
|
-
const
|
|
2443
|
-
if (!
|
|
2444
|
-
const
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
for (const action of actions) {
|
|
2448
|
-
if (((_a2 = action.showWhen) == null ? void 0 : _a2.type) === "rules") {
|
|
2449
|
-
for (const rule of action.showWhen.rules) {
|
|
2450
|
-
for (const cond of rule.conditions) {
|
|
2451
|
-
if (cond.type === "event_count" && cond.key) {
|
|
2452
|
-
keys.add(cond.key);
|
|
2453
|
-
}
|
|
2454
|
-
}
|
|
2455
|
-
}
|
|
3651
|
+
const tileActions = props.actions;
|
|
3652
|
+
if (!tileActions) continue;
|
|
3653
|
+
for (const action of tileActions) {
|
|
3654
|
+
if (((_a2 = action.triggerWhen) == null ? void 0 : _a2.type) === "rules") {
|
|
3655
|
+
registerFromTriggerWhen(action.triggerWhen, accumulator);
|
|
2456
3656
|
}
|
|
2457
3657
|
}
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
for (const
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
const pathname = String((_b = (_a3 = event.props) == null ? void 0 : _a3.pathname) != null ? _b : "");
|
|
2466
|
-
if (!pathname.includes(urlContains)) return false;
|
|
2467
|
-
}
|
|
2468
|
-
if (propFilters) {
|
|
2469
|
-
for (const [k, v] of Object.entries(propFilters)) {
|
|
2470
|
-
if (((_c = event.props) == null ? void 0 : _c[k]) !== v) return false;
|
|
2471
|
-
}
|
|
2472
|
-
}
|
|
2473
|
-
return true;
|
|
2474
|
-
});
|
|
3658
|
+
}
|
|
3659
|
+
if (actions) {
|
|
3660
|
+
for (const rawAction of actions) {
|
|
3661
|
+
const action = rawAction;
|
|
3662
|
+
if (((_b = action.triggerWhen) == null ? void 0 : _b.type) === "rules") {
|
|
3663
|
+
registerFromTriggerWhen(action.triggerWhen, accumulator);
|
|
3664
|
+
}
|
|
2475
3665
|
}
|
|
2476
3666
|
}
|
|
2477
3667
|
}
|
|
@@ -2482,9 +3672,15 @@ var SmartCanvasController = class {
|
|
|
2482
3672
|
__publicField(this, "state");
|
|
2483
3673
|
__publicField(this, "listeners", /* @__PURE__ */ new Set());
|
|
2484
3674
|
var _a2;
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
3675
|
+
let open = (_a2 = initial == null ? void 0 : initial.open) != null ? _a2 : false;
|
|
3676
|
+
if ((initial == null ? void 0 : initial.open) === void 0) {
|
|
3677
|
+
try {
|
|
3678
|
+
const stored = sessionStorage == null ? void 0 : sessionStorage.getItem("syntro:editor:panel-open");
|
|
3679
|
+
if (stored !== null) open = JSON.parse(stored);
|
|
3680
|
+
} catch {
|
|
3681
|
+
}
|
|
3682
|
+
}
|
|
3683
|
+
this.state = { open };
|
|
2488
3684
|
}
|
|
2489
3685
|
getState() {
|
|
2490
3686
|
return this.state;
|
|
@@ -2498,6 +3694,10 @@ var SmartCanvasController = class {
|
|
|
2498
3694
|
setOpen(open) {
|
|
2499
3695
|
if (this.state.open === open) return;
|
|
2500
3696
|
this.state = { ...this.state, open };
|
|
3697
|
+
try {
|
|
3698
|
+
sessionStorage == null ? void 0 : sessionStorage.setItem("syntro:editor:panel-open", JSON.stringify(open));
|
|
3699
|
+
} catch {
|
|
3700
|
+
}
|
|
2501
3701
|
this.emit();
|
|
2502
3702
|
}
|
|
2503
3703
|
toggle() {
|
|
@@ -2616,208 +3816,42 @@ function overlayCompleted(recipeId, recipeName) {
|
|
|
2616
3816
|
return createCanvasEvent(StandardEvents.OVERLAY_COMPLETED, {
|
|
2617
3817
|
recipeId,
|
|
2618
3818
|
recipeName
|
|
2619
|
-
});
|
|
2620
|
-
}
|
|
2621
|
-
function overlayDismissed(recipeId, recipeName, stepIndex) {
|
|
2622
|
-
return createCanvasEvent(StandardEvents.OVERLAY_DISMISSED, {
|
|
2623
|
-
recipeId,
|
|
2624
|
-
recipeName,
|
|
2625
|
-
stepIndex
|
|
2626
|
-
});
|
|
2627
|
-
}
|
|
2628
|
-
function overlayStepViewed(recipeId, stepIndex, stepTitle) {
|
|
2629
|
-
return createCanvasEvent(StandardEvents.OVERLAY_STEP_VIEWED, {
|
|
2630
|
-
recipeId,
|
|
2631
|
-
stepIndex,
|
|
2632
|
-
stepTitle
|
|
2633
|
-
});
|
|
2634
|
-
}
|
|
2635
|
-
function customCanvasEvent(name, props) {
|
|
2636
|
-
const eventName = name.startsWith("canvas.") ? name : `canvas.${name}`;
|
|
2637
|
-
return createCanvasEvent(eventName, props);
|
|
2638
|
-
}
|
|
2639
|
-
var CanvasEvents = {
|
|
2640
|
-
canvasOpened,
|
|
2641
|
-
canvasClosed,
|
|
2642
|
-
tileViewed,
|
|
2643
|
-
tileExpanded,
|
|
2644
|
-
tileCollapsed,
|
|
2645
|
-
tileAction,
|
|
2646
|
-
overlayStarted,
|
|
2647
|
-
overlayCompleted,
|
|
2648
|
-
overlayDismissed,
|
|
2649
|
-
overlayStepViewed,
|
|
2650
|
-
custom: customCanvasEvent
|
|
2651
|
-
};
|
|
2652
|
-
|
|
2653
|
-
// src/theme/defaultTheme.ts
|
|
2654
|
-
function withAlpha(hex, alpha) {
|
|
2655
|
-
return `${hex}${Math.round(alpha * 255).toString(16).padStart(2, "0")}`;
|
|
2656
|
-
}
|
|
2657
|
-
var darkTheme = {
|
|
2658
|
-
// Brand colors
|
|
2659
|
-
colorPrimary: brand[3],
|
|
2660
|
-
colorPrimaryHover: brand[4],
|
|
2661
|
-
colorPrimaryMuted: brand[0],
|
|
2662
|
-
// Surface colors (with alpha for glass/vibrancy effects)
|
|
2663
|
-
colorBackground: withAlpha(slateGrey[1], 0.95),
|
|
2664
|
-
colorBackgroundElevated: withAlpha(slateGrey[3], 0.95),
|
|
2665
|
-
colorBackgroundSubtle: withAlpha(slateGrey[0], 0.2),
|
|
2666
|
-
colorSurface: withAlpha(slateGrey[4], 0.8),
|
|
2667
|
-
colorSurfaceHover: withAlpha(slateGrey[5], 0.8),
|
|
2668
|
-
// Text colors
|
|
2669
|
-
colorText: text.primary,
|
|
2670
|
-
colorTextSecondary: text.secondary,
|
|
2671
|
-
colorTextMuted: text.tertiary,
|
|
2672
|
-
colorTextInverse: slateGrey[1],
|
|
2673
|
-
// Border colors
|
|
2674
|
-
colorBorder: border.primary,
|
|
2675
|
-
colorBorderSubtle: border.secondary,
|
|
2676
|
-
// Semantic colors
|
|
2677
|
-
colorSuccess: green[4],
|
|
2678
|
-
colorSuccessMuted: green[0],
|
|
2679
|
-
colorWarning: yellow[4],
|
|
2680
|
-
colorWarningMuted: yellow[0],
|
|
2681
|
-
colorError: red[4],
|
|
2682
|
-
colorErrorMuted: red[0],
|
|
2683
|
-
colorInfo: blue[4],
|
|
2684
|
-
colorInfoMuted: blue[0],
|
|
2685
|
-
// Notification badge
|
|
2686
|
-
colorNotification: brand[4],
|
|
2687
|
-
colorNotificationMuted: withAlpha(brand[4], 0.4),
|
|
2688
|
-
// Glass morphism
|
|
2689
|
-
glassBackground: withAlpha(slateGrey[1], 0.6),
|
|
2690
|
-
glassBackgroundHover: withAlpha(slateGrey[1], 0.7),
|
|
2691
|
-
glassBorder: "rgba(255, 255, 255, 0.08)",
|
|
2692
|
-
glassBlur: "blur(24px)",
|
|
2693
|
-
glassSaturate: "saturate(1.2)",
|
|
2694
|
-
// Typography (SF Pro stack)
|
|
2695
|
-
fontFamily: "-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif",
|
|
2696
|
-
fontFamilyMono: "'SF Mono', 'Fira Code', Consolas, monospace",
|
|
2697
|
-
fontSizeXs: "0.7rem",
|
|
2698
|
-
fontSizeSm: "0.8rem",
|
|
2699
|
-
fontSizeMd: "0.9rem",
|
|
2700
|
-
fontSizeLg: "1rem",
|
|
2701
|
-
fontSizeXl: "1.25rem",
|
|
2702
|
-
fontSizeXxl: "1.5rem",
|
|
2703
|
-
fontWeightNormal: "400",
|
|
2704
|
-
fontWeightMedium: "500",
|
|
2705
|
-
fontWeightSemibold: "600",
|
|
2706
|
-
fontWeightBold: "700",
|
|
2707
|
-
lineHeightTight: "1.25",
|
|
2708
|
-
lineHeightNormal: "1.5",
|
|
2709
|
-
lineHeightRelaxed: "1.75",
|
|
2710
|
-
// Spacing
|
|
2711
|
-
spacingXs: "0.25rem",
|
|
2712
|
-
spacingSm: "0.5rem",
|
|
2713
|
-
spacingMd: "0.75rem",
|
|
2714
|
-
spacingLg: "1rem",
|
|
2715
|
-
spacingXl: "1.5rem",
|
|
2716
|
-
// Border radius
|
|
2717
|
-
borderRadiusSm: "6px",
|
|
2718
|
-
borderRadiusMd: "10px",
|
|
2719
|
-
borderRadiusLg: "14px",
|
|
2720
|
-
borderRadiusXl: "20px",
|
|
2721
|
-
borderRadiusFull: "9999px",
|
|
2722
|
-
// Shadows
|
|
2723
|
-
shadowSm: "0 1px 2px rgba(0, 0, 0, 0.2)",
|
|
2724
|
-
shadowMd: "0 2px 12px rgba(0, 0, 0, 0.3)",
|
|
2725
|
-
shadowLg: "0 8px 24px rgba(0, 0, 0, 0.4)",
|
|
2726
|
-
shadowXl: "0 16px 48px rgba(0, 0, 0, 0.5)",
|
|
2727
|
-
// Backdrop effects
|
|
2728
|
-
backdropBlur: "blur(20px)",
|
|
2729
|
-
backdropSaturate: "saturate(180%)",
|
|
2730
|
-
// Animation
|
|
2731
|
-
transitionFast: "0.1s ease",
|
|
2732
|
-
transitionNormal: "0.25s ease",
|
|
2733
|
-
transitionSlow: "0.4s ease"
|
|
2734
|
-
};
|
|
2735
|
-
var lightTheme = {
|
|
2736
|
-
// Brand colors
|
|
2737
|
-
colorPrimary: brand[3],
|
|
2738
|
-
colorPrimaryHover: brand[2],
|
|
2739
|
-
colorPrimaryMuted: withAlpha(brand[5], 0.1),
|
|
2740
|
-
// Surface colors
|
|
2741
|
-
colorBackground: withAlpha(slateGrey[12], 0.95),
|
|
2742
|
-
colorBackgroundElevated: withAlpha(slateGrey[11], 0.95),
|
|
2743
|
-
colorBackgroundSubtle: withAlpha(slateGrey[0], 0.02),
|
|
2744
|
-
colorSurface: withAlpha(slateGrey[11], 0.6),
|
|
2745
|
-
colorSurfaceHover: withAlpha(slateGrey[10], 0.6),
|
|
2746
|
-
// Text colors
|
|
2747
|
-
colorText: slateGrey[1],
|
|
2748
|
-
colorTextSecondary: slateGrey[6],
|
|
2749
|
-
colorTextMuted: slateGrey[8],
|
|
2750
|
-
colorTextInverse: slateGrey[12],
|
|
2751
|
-
// Border colors
|
|
2752
|
-
colorBorder: withAlpha(slateGrey[0], 0.12),
|
|
2753
|
-
colorBorderSubtle: withAlpha(slateGrey[0], 0.06),
|
|
2754
|
-
// Semantic colors
|
|
2755
|
-
colorSuccess: green[4],
|
|
2756
|
-
colorSuccessMuted: withAlpha(green[4], 0.12),
|
|
2757
|
-
colorWarning: yellow[4],
|
|
2758
|
-
colorWarningMuted: withAlpha(yellow[4], 0.12),
|
|
2759
|
-
colorError: red[4],
|
|
2760
|
-
colorErrorMuted: withAlpha(red[4], 0.12),
|
|
2761
|
-
colorInfo: blue[4],
|
|
2762
|
-
colorInfoMuted: withAlpha(blue[4], 0.12),
|
|
2763
|
-
// Notification badge
|
|
2764
|
-
colorNotification: brand[3],
|
|
2765
|
-
colorNotificationMuted: withAlpha(brand[3], 0.4),
|
|
2766
|
-
// Glass morphism
|
|
2767
|
-
glassBackground: withAlpha(slateGrey[12], 0.7),
|
|
2768
|
-
glassBackgroundHover: withAlpha(slateGrey[12], 0.8),
|
|
2769
|
-
glassBorder: "rgba(0, 0, 0, 0.06)",
|
|
2770
|
-
glassBlur: "blur(24px)",
|
|
2771
|
-
glassSaturate: "saturate(1.2)",
|
|
2772
|
-
// Typography (same as dark)
|
|
2773
|
-
fontFamily: "-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif",
|
|
2774
|
-
fontFamilyMono: "'SF Mono', 'Fira Code', Consolas, monospace",
|
|
2775
|
-
fontSizeXs: "0.7rem",
|
|
2776
|
-
fontSizeSm: "0.8rem",
|
|
2777
|
-
fontSizeMd: "0.9rem",
|
|
2778
|
-
fontSizeLg: "1rem",
|
|
2779
|
-
fontSizeXl: "1.25rem",
|
|
2780
|
-
fontSizeXxl: "1.5rem",
|
|
2781
|
-
fontWeightNormal: "400",
|
|
2782
|
-
fontWeightMedium: "500",
|
|
2783
|
-
fontWeightSemibold: "600",
|
|
2784
|
-
fontWeightBold: "700",
|
|
2785
|
-
lineHeightTight: "1.25",
|
|
2786
|
-
lineHeightNormal: "1.5",
|
|
2787
|
-
lineHeightRelaxed: "1.75",
|
|
2788
|
-
// Spacing (same as dark)
|
|
2789
|
-
spacingXs: "0.25rem",
|
|
2790
|
-
spacingSm: "0.5rem",
|
|
2791
|
-
spacingMd: "0.75rem",
|
|
2792
|
-
spacingLg: "1rem",
|
|
2793
|
-
spacingXl: "1.5rem",
|
|
2794
|
-
// Border radius (same as dark)
|
|
2795
|
-
borderRadiusSm: "6px",
|
|
2796
|
-
borderRadiusMd: "10px",
|
|
2797
|
-
borderRadiusLg: "14px",
|
|
2798
|
-
borderRadiusXl: "20px",
|
|
2799
|
-
borderRadiusFull: "9999px",
|
|
2800
|
-
// Shadows (lighter for light mode)
|
|
2801
|
-
shadowSm: "0 1px 2px rgba(0, 0, 0, 0.08)",
|
|
2802
|
-
shadowMd: "0 2px 12px rgba(0, 0, 0, 0.12)",
|
|
2803
|
-
shadowLg: "0 8px 24px rgba(0, 0, 0, 0.16)",
|
|
2804
|
-
shadowXl: "0 16px 48px rgba(0, 0, 0, 0.2)",
|
|
2805
|
-
// Backdrop effects
|
|
2806
|
-
backdropBlur: "blur(20px)",
|
|
2807
|
-
backdropSaturate: "saturate(180%)",
|
|
2808
|
-
// Animation
|
|
2809
|
-
transitionFast: "0.1s ease",
|
|
2810
|
-
transitionNormal: "0.25s ease",
|
|
2811
|
-
transitionSlow: "0.4s ease"
|
|
3819
|
+
});
|
|
3820
|
+
}
|
|
3821
|
+
function overlayDismissed(recipeId, recipeName, stepIndex) {
|
|
3822
|
+
return createCanvasEvent(StandardEvents.OVERLAY_DISMISSED, {
|
|
3823
|
+
recipeId,
|
|
3824
|
+
recipeName,
|
|
3825
|
+
stepIndex
|
|
3826
|
+
});
|
|
3827
|
+
}
|
|
3828
|
+
function overlayStepViewed(recipeId, stepIndex, stepTitle) {
|
|
3829
|
+
return createCanvasEvent(StandardEvents.OVERLAY_STEP_VIEWED, {
|
|
3830
|
+
recipeId,
|
|
3831
|
+
stepIndex,
|
|
3832
|
+
stepTitle
|
|
3833
|
+
});
|
|
3834
|
+
}
|
|
3835
|
+
function customCanvasEvent(name, props) {
|
|
3836
|
+
const eventName = name.startsWith("canvas.") ? name : `canvas.${name}`;
|
|
3837
|
+
return createCanvasEvent(eventName, props);
|
|
3838
|
+
}
|
|
3839
|
+
var CanvasEvents = {
|
|
3840
|
+
canvasOpened,
|
|
3841
|
+
canvasClosed,
|
|
3842
|
+
tileViewed,
|
|
3843
|
+
tileExpanded,
|
|
3844
|
+
tileCollapsed,
|
|
3845
|
+
tileAction,
|
|
3846
|
+
overlayStarted,
|
|
3847
|
+
overlayCompleted,
|
|
3848
|
+
overlayDismissed,
|
|
3849
|
+
overlayStepViewed,
|
|
3850
|
+
custom: customCanvasEvent
|
|
2812
3851
|
};
|
|
2813
3852
|
|
|
2814
|
-
// src/theme/ThemeProvider.tsx
|
|
2815
|
-
import { createContext as createContext2, useContext as useContext2, useEffect, useMemo, useState } from "react";
|
|
2816
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
2817
|
-
var ThemeContext = createContext2(null);
|
|
2818
|
-
|
|
2819
3853
|
// src/notifications/NotificationToastStack.tsx
|
|
2820
|
-
import { jsx as
|
|
3854
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
2821
3855
|
var TOAST_STYLES_ID = "syntro-toast-styles";
|
|
2822
3856
|
var TOAST_CSS = `
|
|
2823
3857
|
@keyframes syntro-toast-slide-in {
|
|
@@ -2854,7 +3888,7 @@ function NotificationToastStack({
|
|
|
2854
3888
|
const { shadowRoot } = useShadowRoot();
|
|
2855
3889
|
ensureToastStyles(shadowRoot);
|
|
2856
3890
|
if (notifications.length === 0) return null;
|
|
2857
|
-
return /* @__PURE__ */
|
|
3891
|
+
return /* @__PURE__ */ jsx2(
|
|
2858
3892
|
"div",
|
|
2859
3893
|
{
|
|
2860
3894
|
"data-testid": "notification-toast-stack",
|
|
@@ -2878,11 +3912,11 @@ function NotificationToastStack({
|
|
|
2878
3912
|
{
|
|
2879
3913
|
className: "syntro-toast-enter",
|
|
2880
3914
|
style: {
|
|
2881
|
-
background:
|
|
3915
|
+
background: "var(--sc-notification-background)",
|
|
2882
3916
|
backdropFilter: "blur(12px)",
|
|
2883
3917
|
WebkitBackdropFilter: "blur(12px)",
|
|
2884
|
-
border:
|
|
2885
|
-
borderRadius: "
|
|
3918
|
+
border: "var(--sc-notification-border)",
|
|
3919
|
+
borderRadius: "var(--sc-notification-border-radius)",
|
|
2886
3920
|
overflow: "hidden",
|
|
2887
3921
|
cursor: "pointer",
|
|
2888
3922
|
transition: "transform 0.15s ease"
|
|
@@ -2909,14 +3943,14 @@ function NotificationToastStack({
|
|
|
2909
3943
|
padding: "10px 12px"
|
|
2910
3944
|
},
|
|
2911
3945
|
children: [
|
|
2912
|
-
/* @__PURE__ */
|
|
3946
|
+
/* @__PURE__ */ jsx2(
|
|
2913
3947
|
"div",
|
|
2914
3948
|
{
|
|
2915
3949
|
style: {
|
|
2916
3950
|
width: "28px",
|
|
2917
3951
|
height: "28px",
|
|
2918
3952
|
borderRadius: "8px",
|
|
2919
|
-
background:
|
|
3953
|
+
background: "var(--sc-notification-icon-background)",
|
|
2920
3954
|
display: "flex",
|
|
2921
3955
|
alignItems: "center",
|
|
2922
3956
|
justifyContent: "center",
|
|
@@ -2927,13 +3961,13 @@ function NotificationToastStack({
|
|
|
2927
3961
|
}
|
|
2928
3962
|
),
|
|
2929
3963
|
/* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
2930
|
-
/* @__PURE__ */
|
|
3964
|
+
/* @__PURE__ */ jsx2(
|
|
2931
3965
|
"div",
|
|
2932
3966
|
{
|
|
2933
3967
|
style: {
|
|
2934
3968
|
fontSize: "13px",
|
|
2935
3969
|
fontWeight: 600,
|
|
2936
|
-
color: text
|
|
3970
|
+
color: "var(--sc-notification-text-color)",
|
|
2937
3971
|
lineHeight: "1.3",
|
|
2938
3972
|
whiteSpace: "nowrap",
|
|
2939
3973
|
overflow: "hidden",
|
|
@@ -2942,12 +3976,12 @@ function NotificationToastStack({
|
|
|
2942
3976
|
children: notif.title
|
|
2943
3977
|
}
|
|
2944
3978
|
),
|
|
2945
|
-
notif.body && /* @__PURE__ */
|
|
3979
|
+
notif.body && /* @__PURE__ */ jsx2(
|
|
2946
3980
|
"div",
|
|
2947
3981
|
{
|
|
2948
3982
|
style: {
|
|
2949
3983
|
fontSize: "12px",
|
|
2950
|
-
color: text
|
|
3984
|
+
color: "var(--sc-notification-text-secondary-color)",
|
|
2951
3985
|
lineHeight: "1.3",
|
|
2952
3986
|
marginTop: "2px",
|
|
2953
3987
|
whiteSpace: "nowrap",
|
|
@@ -2958,7 +3992,7 @@ function NotificationToastStack({
|
|
|
2958
3992
|
}
|
|
2959
3993
|
)
|
|
2960
3994
|
] }),
|
|
2961
|
-
/* @__PURE__ */
|
|
3995
|
+
/* @__PURE__ */ jsx2(
|
|
2962
3996
|
"button",
|
|
2963
3997
|
{
|
|
2964
3998
|
type: "button",
|
|
@@ -2970,7 +4004,7 @@ function NotificationToastStack({
|
|
|
2970
4004
|
style: {
|
|
2971
4005
|
background: "none",
|
|
2972
4006
|
border: "none",
|
|
2973
|
-
color: text
|
|
4007
|
+
color: "var(--sc-notification-text-secondary-color)",
|
|
2974
4008
|
cursor: "pointer",
|
|
2975
4009
|
padding: "2px",
|
|
2976
4010
|
fontSize: "14px",
|
|
@@ -2983,13 +4017,13 @@ function NotificationToastStack({
|
|
|
2983
4017
|
]
|
|
2984
4018
|
}
|
|
2985
4019
|
),
|
|
2986
|
-
/* @__PURE__ */
|
|
4020
|
+
/* @__PURE__ */ jsx2("div", { style: { height: "2px", background: "rgba(0, 0, 0, 0.08)" }, children: /* @__PURE__ */ jsx2(
|
|
2987
4021
|
"div",
|
|
2988
4022
|
{
|
|
2989
4023
|
className: "syntro-toast-progress",
|
|
2990
4024
|
style: {
|
|
2991
4025
|
height: "100%",
|
|
2992
|
-
background:
|
|
4026
|
+
background: "var(--sc-notification-progress-gradient)",
|
|
2993
4027
|
animationDuration: `${notif.ttl}ms`
|
|
2994
4028
|
}
|
|
2995
4029
|
}
|
|
@@ -3054,12 +4088,12 @@ function matchEvent(event, tiles) {
|
|
|
3054
4088
|
}
|
|
3055
4089
|
|
|
3056
4090
|
// src/notifications/useNotifications.ts
|
|
3057
|
-
import { useCallback, useEffect as useEffect2, useRef, useState as useState2 } from "react";
|
|
4091
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
3058
4092
|
function useNotifications(eventBus, tiles) {
|
|
3059
4093
|
const [notifications, setNotifications] = useState2([]);
|
|
3060
|
-
const cooldownMap =
|
|
3061
|
-
const timerIds =
|
|
3062
|
-
const publishDismissed =
|
|
4094
|
+
const cooldownMap = useRef2(/* @__PURE__ */ new Map());
|
|
4095
|
+
const timerIds = useRef2(/* @__PURE__ */ new Map());
|
|
4096
|
+
const publishDismissed = useCallback2(
|
|
3063
4097
|
(notif) => {
|
|
3064
4098
|
eventBus == null ? void 0 : eventBus.publish(StandardEvents.NOTIFICATION_DISMISSED, {
|
|
3065
4099
|
notificationId: notif.id,
|
|
@@ -3069,7 +4103,7 @@ function useNotifications(eventBus, tiles) {
|
|
|
3069
4103
|
},
|
|
3070
4104
|
[eventBus]
|
|
3071
4105
|
);
|
|
3072
|
-
const scheduleDismiss =
|
|
4106
|
+
const scheduleDismiss = useCallback2(
|
|
3073
4107
|
(notif) => {
|
|
3074
4108
|
const timerId = setTimeout(() => {
|
|
3075
4109
|
setNotifications((prev) => prev.filter((n) => n.id !== notif.id));
|
|
@@ -3080,7 +4114,7 @@ function useNotifications(eventBus, tiles) {
|
|
|
3080
4114
|
},
|
|
3081
4115
|
[publishDismissed]
|
|
3082
4116
|
);
|
|
3083
|
-
const dismiss =
|
|
4117
|
+
const dismiss = useCallback2(
|
|
3084
4118
|
(id) => {
|
|
3085
4119
|
setNotifications((prev) => {
|
|
3086
4120
|
const notif = prev.find((n) => n.id === id);
|
|
@@ -3102,7 +4136,7 @@ function useNotifications(eventBus, tiles) {
|
|
|
3102
4136
|
const match = matchEvent(event, tiles);
|
|
3103
4137
|
if (!match) return;
|
|
3104
4138
|
const { notification: matched, rule: matchedRule } = match;
|
|
3105
|
-
const cooldownKey = `${matched.tileId}:${event.name}`;
|
|
4139
|
+
const cooldownKey = matched.itemId ? `${matched.tileId}:${event.name}:${matched.itemId}` : `${matched.tileId}:${event.name}`;
|
|
3106
4140
|
const lastFired = cooldownMap.current.get(cooldownKey);
|
|
3107
4141
|
const now = Date.now();
|
|
3108
4142
|
const cooldown = (_a2 = matchedRule.cooldown) != null ? _a2 : DEFAULT_COOLDOWN;
|
|
@@ -3146,7 +4180,7 @@ function useNotifications(eventBus, tiles) {
|
|
|
3146
4180
|
}
|
|
3147
4181
|
|
|
3148
4182
|
// src/notifications/useNotifyWatcher.ts
|
|
3149
|
-
import { useEffect as useEffect3, useRef as
|
|
4183
|
+
import { useEffect as useEffect3, useRef as useRef3 } from "react";
|
|
3150
4184
|
function collectEntries(tiles, appRegistry2) {
|
|
3151
4185
|
var _a2, _b;
|
|
3152
4186
|
const entries = [];
|
|
@@ -3161,7 +4195,7 @@ function collectEntries(tiles, appRegistry2) {
|
|
|
3161
4195
|
return entries;
|
|
3162
4196
|
}
|
|
3163
4197
|
function useNotifyWatcher(runtime3, tiles, appRegistry2) {
|
|
3164
|
-
const prevStateRef =
|
|
4198
|
+
const prevStateRef = useRef3(/* @__PURE__ */ new Map());
|
|
3165
4199
|
useEffect3(() => {
|
|
3166
4200
|
if (!(runtime3 == null ? void 0 : runtime3.events) || !appRegistry2) return;
|
|
3167
4201
|
const entries = collectEntries(tiles, appRegistry2);
|
|
@@ -3196,9 +4230,9 @@ function useNotifyWatcher(runtime3, tiles, appRegistry2) {
|
|
|
3196
4230
|
}
|
|
3197
4231
|
|
|
3198
4232
|
// src/RuntimeProvider.tsx
|
|
3199
|
-
import { createContext as
|
|
3200
|
-
import { jsx as
|
|
3201
|
-
var RuntimeReactContext =
|
|
4233
|
+
import { createContext as createContext2, useContext as useContext2, useEffect as useEffect4, useMemo as useMemo2, useState as useState3 } from "react";
|
|
4234
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
4235
|
+
var RuntimeReactContext = createContext2({
|
|
3202
4236
|
runtime: null,
|
|
3203
4237
|
context: null
|
|
3204
4238
|
});
|
|
@@ -3215,14 +4249,14 @@ function RuntimeProvider({ runtime: runtime3, children }) {
|
|
|
3215
4249
|
return unsubscribe;
|
|
3216
4250
|
}, [runtime3]);
|
|
3217
4251
|
const value = useMemo2(() => ({ runtime: runtime3, context }), [runtime3, context]);
|
|
3218
|
-
return /* @__PURE__ */
|
|
4252
|
+
return /* @__PURE__ */ jsx3(RuntimeReactContext.Provider, { value, children });
|
|
3219
4253
|
}
|
|
3220
4254
|
function useRuntime() {
|
|
3221
|
-
const { runtime: runtime3 } =
|
|
4255
|
+
const { runtime: runtime3 } = useContext2(RuntimeReactContext);
|
|
3222
4256
|
return runtime3;
|
|
3223
4257
|
}
|
|
3224
4258
|
function useRuntimeContext() {
|
|
3225
|
-
const { context } =
|
|
4259
|
+
const { context } = useContext2(RuntimeReactContext);
|
|
3226
4260
|
return context;
|
|
3227
4261
|
}
|
|
3228
4262
|
function usePageContext() {
|
|
@@ -3279,15 +4313,60 @@ function useDecision(strategy, defaultValue) {
|
|
|
3279
4313
|
}
|
|
3280
4314
|
|
|
3281
4315
|
// src/components/TileCard.tsx
|
|
3282
|
-
import {
|
|
4316
|
+
import {
|
|
4317
|
+
useCallback as useCallback3,
|
|
4318
|
+
useEffect as useEffect5,
|
|
4319
|
+
useMemo as useMemo3,
|
|
4320
|
+
useReducer,
|
|
4321
|
+
useRef as useRef4,
|
|
4322
|
+
useState as useState4
|
|
4323
|
+
} from "react";
|
|
4324
|
+
|
|
4325
|
+
// src/components/TileIcon.tsx
|
|
4326
|
+
import {
|
|
4327
|
+
Compass,
|
|
4328
|
+
FileText,
|
|
4329
|
+
Gamepad2,
|
|
4330
|
+
HelpCircle,
|
|
4331
|
+
Layers,
|
|
4332
|
+
MessageCircle,
|
|
4333
|
+
Sparkles,
|
|
4334
|
+
Trophy
|
|
4335
|
+
} from "lucide-react";
|
|
4336
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
4337
|
+
var ICON_MAP = {
|
|
4338
|
+
"\u2753": HelpCircle,
|
|
4339
|
+
"\u{1F9ED}": Compass,
|
|
4340
|
+
"\u{1F4DD}": FileText,
|
|
4341
|
+
"\u{1F3AF}": Layers,
|
|
4342
|
+
"\u{1F3C6}": Trophy,
|
|
4343
|
+
"\u2728": Sparkles,
|
|
4344
|
+
"\u{1F4AC}": MessageCircle,
|
|
4345
|
+
"\u{1F3AE}": Gamepad2
|
|
4346
|
+
};
|
|
4347
|
+
function TileIcon({
|
|
4348
|
+
emoji,
|
|
4349
|
+
size = 18,
|
|
4350
|
+
color = "currentColor"
|
|
4351
|
+
}) {
|
|
4352
|
+
const Icon = ICON_MAP[emoji];
|
|
4353
|
+
if (!Icon) {
|
|
4354
|
+
return /* @__PURE__ */ jsx4("span", { children: emoji });
|
|
4355
|
+
}
|
|
4356
|
+
return /* @__PURE__ */ jsx4(Icon, { size, color });
|
|
4357
|
+
}
|
|
4358
|
+
|
|
4359
|
+
// src/components/TileCard.tsx
|
|
3283
4360
|
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
3284
4361
|
function WidgetMount({ widgetId, props }) {
|
|
3285
4362
|
var _a2;
|
|
3286
4363
|
const runtime3 = useRuntime();
|
|
3287
|
-
const
|
|
3288
|
-
const handleRef =
|
|
4364
|
+
const parentRef = useRef4(null);
|
|
4365
|
+
const handleRef = useRef4(null);
|
|
3289
4366
|
const registry = runtime3 == null ? void 0 : runtime3.widgets;
|
|
3290
4367
|
const widgetAvailable = (_a2 = registry == null ? void 0 : registry.has(widgetId)) != null ? _a2 : false;
|
|
4368
|
+
const propsRef = useRef4(props);
|
|
4369
|
+
propsRef.current = props;
|
|
3291
4370
|
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
3292
4371
|
useEffect5(() => {
|
|
3293
4372
|
if (!registry || widgetAvailable) return;
|
|
@@ -3298,14 +4377,27 @@ function WidgetMount({ widgetId, props }) {
|
|
|
3298
4377
|
});
|
|
3299
4378
|
}, [registry, widgetId, widgetAvailable]);
|
|
3300
4379
|
useEffect5(() => {
|
|
3301
|
-
if (!
|
|
3302
|
-
const
|
|
4380
|
+
if (!parentRef.current || !registry || !widgetAvailable) return;
|
|
4381
|
+
const container = document.createElement("div");
|
|
4382
|
+
container.style.width = "100%";
|
|
4383
|
+
container.style.minHeight = "40px";
|
|
4384
|
+
parentRef.current.appendChild(container);
|
|
4385
|
+
const handle = registry.mount(widgetId, container, propsRef.current);
|
|
3303
4386
|
handleRef.current = handle;
|
|
3304
4387
|
return () => {
|
|
3305
4388
|
handle.unmount();
|
|
3306
4389
|
handleRef.current = null;
|
|
4390
|
+
container.remove();
|
|
3307
4391
|
};
|
|
3308
|
-
}, [registry, widgetId,
|
|
4392
|
+
}, [registry, widgetId, widgetAvailable]);
|
|
4393
|
+
const propsJson = JSON.stringify(props);
|
|
4394
|
+
const prevPropsJsonRef = useRef4(propsJson);
|
|
4395
|
+
useEffect5(() => {
|
|
4396
|
+
var _a3;
|
|
4397
|
+
if (prevPropsJsonRef.current === propsJson) return;
|
|
4398
|
+
prevPropsJsonRef.current = propsJson;
|
|
4399
|
+
(_a3 = handleRef.current) == null ? void 0 : _a3.update(propsRef.current);
|
|
4400
|
+
}, [propsJson]);
|
|
3309
4401
|
if (!registry || !registry.has(widgetId)) {
|
|
3310
4402
|
return /* @__PURE__ */ jsxs2(
|
|
3311
4403
|
"div",
|
|
@@ -3313,7 +4405,7 @@ function WidgetMount({ widgetId, props }) {
|
|
|
3313
4405
|
style: {
|
|
3314
4406
|
padding: "0.75rem",
|
|
3315
4407
|
fontSize: "0.8rem",
|
|
3316
|
-
color: text
|
|
4408
|
+
color: "var(--sc-tile-text-color)",
|
|
3317
4409
|
fontStyle: "italic"
|
|
3318
4410
|
},
|
|
3319
4411
|
children: [
|
|
@@ -3323,173 +4415,585 @@ function WidgetMount({ widgetId, props }) {
|
|
|
3323
4415
|
}
|
|
3324
4416
|
);
|
|
3325
4417
|
}
|
|
3326
|
-
return /* @__PURE__ */ jsx5("div", { ref:
|
|
4418
|
+
return /* @__PURE__ */ jsx5("div", { ref: parentRef });
|
|
4419
|
+
}
|
|
4420
|
+
function TileCard({
|
|
4421
|
+
config,
|
|
4422
|
+
surface: _surface,
|
|
4423
|
+
telemetry: _telemetry,
|
|
4424
|
+
style
|
|
4425
|
+
}) {
|
|
4426
|
+
const { title, subtitle, widget, props, icon } = config;
|
|
4427
|
+
const [, setTick] = useState4(0);
|
|
4428
|
+
const runtime3 = useRuntime();
|
|
4429
|
+
useEffect5(() => {
|
|
4430
|
+
if (runtime3) setTick((t) => t + 1);
|
|
4431
|
+
}, [runtime3]);
|
|
4432
|
+
const registration = useMemo3(
|
|
4433
|
+
() => {
|
|
4434
|
+
var _a2, _b;
|
|
4435
|
+
return (_b = (_a2 = runtime3 == null ? void 0 : runtime3.widgets) == null ? void 0 : _a2.getRegistration) == null ? void 0 : _b.call(_a2, widget);
|
|
4436
|
+
},
|
|
4437
|
+
[runtime3 == null ? void 0 : runtime3.widgets, widget]
|
|
4438
|
+
);
|
|
4439
|
+
const resolvedIcon = useMemo3(() => {
|
|
4440
|
+
var _a2, _b;
|
|
4441
|
+
if (icon) return icon;
|
|
4442
|
+
return (_b = (_a2 = registration == null ? void 0 : registration.metadata) == null ? void 0 : _a2.icon) != null ? _b : "+";
|
|
4443
|
+
}, [icon, registration]);
|
|
4444
|
+
const resolvedSubtitle = useMemo3(() => {
|
|
4445
|
+
var _a2;
|
|
4446
|
+
if (subtitle) return subtitle;
|
|
4447
|
+
return (_a2 = registration == null ? void 0 : registration.metadata) == null ? void 0 : _a2.subtitle;
|
|
4448
|
+
}, [subtitle, registration]);
|
|
4449
|
+
const [hovered, setHovered] = useState4(false);
|
|
4450
|
+
const onMouseEnter = useCallback3(() => setHovered(true), []);
|
|
4451
|
+
const onMouseLeave = useCallback3(() => setHovered(false), []);
|
|
4452
|
+
const cardStyle = {
|
|
4453
|
+
display: "flex",
|
|
4454
|
+
flexDirection: "column",
|
|
4455
|
+
borderRadius: "var(--sc-tile-border-radius)",
|
|
4456
|
+
background: hovered ? "var(--sc-tile-background-hover)" : "var(--sc-tile-background)",
|
|
4457
|
+
backdropFilter: "blur(16px) saturate(1.2)",
|
|
4458
|
+
WebkitBackdropFilter: "blur(16px) saturate(1.2)",
|
|
4459
|
+
border: "var(--sc-tile-border)",
|
|
4460
|
+
boxShadow: "var(--sc-tile-shadow)",
|
|
4461
|
+
color: "var(--sc-tile-title-color)",
|
|
4462
|
+
fontFamily: "var(--sc-font-family)",
|
|
4463
|
+
overflow: "hidden",
|
|
4464
|
+
cursor: "default",
|
|
4465
|
+
transition: "all 0.25s ease",
|
|
4466
|
+
transform: hovered ? "scale(1.01)" : "scale(1)",
|
|
4467
|
+
...style
|
|
4468
|
+
};
|
|
4469
|
+
const headerStyle = {
|
|
4470
|
+
display: "flex",
|
|
4471
|
+
alignItems: "center",
|
|
4472
|
+
gap: "var(--sc-tile-gap, 0.25rem)",
|
|
4473
|
+
padding: "var(--sc-tile-header-padding, 0.375rem 0.75rem)",
|
|
4474
|
+
minHeight: "44px"
|
|
4475
|
+
};
|
|
4476
|
+
const iconStyle = {
|
|
4477
|
+
display: "flex",
|
|
4478
|
+
alignItems: "center",
|
|
4479
|
+
justifyContent: "center",
|
|
4480
|
+
flexShrink: 0
|
|
4481
|
+
};
|
|
4482
|
+
return /* @__PURE__ */ jsxs2(
|
|
4483
|
+
"article",
|
|
4484
|
+
{
|
|
4485
|
+
"data-shadow-canvas-id": `tile-${config.id}`,
|
|
4486
|
+
style: cardStyle,
|
|
4487
|
+
onMouseEnter,
|
|
4488
|
+
onMouseLeave,
|
|
4489
|
+
children: [
|
|
4490
|
+
/* @__PURE__ */ jsxs2("div", { style: headerStyle, children: [
|
|
4491
|
+
/* @__PURE__ */ jsx5("div", { style: iconStyle, children: /* @__PURE__ */ jsx5(TileIcon, { emoji: resolvedIcon, size: resolvedSubtitle ? 36 : 24 }) }),
|
|
4492
|
+
/* @__PURE__ */ jsxs2("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
4493
|
+
/* @__PURE__ */ jsx5(
|
|
4494
|
+
"h3",
|
|
4495
|
+
{
|
|
4496
|
+
style: {
|
|
4497
|
+
fontSize: "1.14rem",
|
|
4498
|
+
fontWeight: 600,
|
|
4499
|
+
color: "var(--sc-tile-title-color)",
|
|
4500
|
+
margin: "0.125rem 0 0",
|
|
4501
|
+
whiteSpace: "nowrap",
|
|
4502
|
+
overflow: "hidden",
|
|
4503
|
+
textOverflow: "ellipsis"
|
|
4504
|
+
},
|
|
4505
|
+
children: title != null ? title : widget
|
|
4506
|
+
}
|
|
4507
|
+
),
|
|
4508
|
+
resolvedSubtitle && /* @__PURE__ */ jsx5(
|
|
4509
|
+
"p",
|
|
4510
|
+
{
|
|
4511
|
+
style: {
|
|
4512
|
+
fontSize: "0.8rem",
|
|
4513
|
+
fontWeight: 400,
|
|
4514
|
+
color: "var(--sc-tile-text-color)",
|
|
4515
|
+
margin: "0.125rem 0 0",
|
|
4516
|
+
whiteSpace: "nowrap",
|
|
4517
|
+
overflow: "hidden",
|
|
4518
|
+
textOverflow: "ellipsis"
|
|
4519
|
+
},
|
|
4520
|
+
children: resolvedSubtitle
|
|
4521
|
+
}
|
|
4522
|
+
)
|
|
4523
|
+
] })
|
|
4524
|
+
] }),
|
|
4525
|
+
/* @__PURE__ */ jsx5(
|
|
4526
|
+
"div",
|
|
4527
|
+
{
|
|
4528
|
+
style: {
|
|
4529
|
+
padding: "var(--sc-tile-body-padding, 0 0.75rem 0.5rem)",
|
|
4530
|
+
borderTop: "1px solid rgba(255, 255, 255, 0.06)"
|
|
4531
|
+
},
|
|
4532
|
+
children: /* @__PURE__ */ jsx5("div", { style: { paddingTop: "var(--sc-tile-gap, 0.25rem)" }, children: /* @__PURE__ */ jsx5(WidgetMount, { widgetId: widget, props: { ...props, instanceId: config.id } }) })
|
|
4533
|
+
}
|
|
4534
|
+
)
|
|
4535
|
+
]
|
|
4536
|
+
}
|
|
4537
|
+
);
|
|
4538
|
+
}
|
|
4539
|
+
|
|
4540
|
+
// src/components/ShadowCanvasOverlay.tsx
|
|
4541
|
+
import { useCallback as useCallback4, useEffect as useEffect7, useMemo as useMemo5, useRef as useRef5, useState as useState5 } from "react";
|
|
4542
|
+
import { createPortal } from "react-dom";
|
|
4543
|
+
|
|
4544
|
+
// src/theme/defaultTheme.ts
|
|
4545
|
+
function withAlpha(hex, alpha) {
|
|
4546
|
+
return `${hex}${Math.round(alpha * 255).toString(16).padStart(2, "0")}`;
|
|
4547
|
+
}
|
|
4548
|
+
var darkTheme = {
|
|
4549
|
+
// Brand colors
|
|
4550
|
+
colorPrimary: brand[3],
|
|
4551
|
+
colorPrimaryHover: brand[4],
|
|
4552
|
+
colorPrimaryMuted: brand[0],
|
|
4553
|
+
// Surface colors (with alpha for glass/vibrancy effects)
|
|
4554
|
+
colorBackground: withAlpha(slateGrey[1], 0.95),
|
|
4555
|
+
colorBackgroundElevated: withAlpha(slateGrey[3], 0.95),
|
|
4556
|
+
colorBackgroundSubtle: withAlpha(slateGrey[0], 0.2),
|
|
4557
|
+
colorSurface: withAlpha(slateGrey[4], 0.8),
|
|
4558
|
+
colorSurfaceHover: withAlpha(slateGrey[5], 0.8),
|
|
4559
|
+
// Text colors
|
|
4560
|
+
colorText: text.primary,
|
|
4561
|
+
colorTextSecondary: text.secondary,
|
|
4562
|
+
colorTextMuted: text.tertiary,
|
|
4563
|
+
colorTextInverse: slateGrey[1],
|
|
4564
|
+
// Border colors
|
|
4565
|
+
colorBorder: border.primary,
|
|
4566
|
+
colorBorderSubtle: border.secondary,
|
|
4567
|
+
// Semantic colors
|
|
4568
|
+
colorSuccess: green[4],
|
|
4569
|
+
colorSuccessMuted: green[0],
|
|
4570
|
+
colorWarning: yellow[4],
|
|
4571
|
+
colorWarningMuted: yellow[0],
|
|
4572
|
+
colorError: red[4],
|
|
4573
|
+
colorErrorMuted: red[0],
|
|
4574
|
+
colorInfo: blue[4],
|
|
4575
|
+
colorInfoMuted: blue[0],
|
|
4576
|
+
// Notification badge
|
|
4577
|
+
colorNotification: brand[4],
|
|
4578
|
+
colorNotificationMuted: withAlpha(brand[4], 0.4),
|
|
4579
|
+
// Glass morphism
|
|
4580
|
+
glassBackground: withAlpha(slateGrey[1], 0.6),
|
|
4581
|
+
glassBackgroundHover: withAlpha(slateGrey[1], 0.7),
|
|
4582
|
+
glassBorder: "rgba(255, 255, 255, 0.08)",
|
|
4583
|
+
glassBlur: "blur(24px)",
|
|
4584
|
+
glassSaturate: "saturate(1.2)",
|
|
4585
|
+
// Typography (SF Pro stack)
|
|
4586
|
+
fontFamily: "-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif",
|
|
4587
|
+
fontFamilyMono: "'SF Mono', 'Fira Code', Consolas, monospace",
|
|
4588
|
+
fontSizeXs: "0.7rem",
|
|
4589
|
+
fontSizeSm: "0.8rem",
|
|
4590
|
+
fontSizeMd: "0.9rem",
|
|
4591
|
+
fontSizeLg: "1rem",
|
|
4592
|
+
fontSizeXl: "1.25rem",
|
|
4593
|
+
fontSizeXxl: "1.5rem",
|
|
4594
|
+
fontWeightNormal: "400",
|
|
4595
|
+
fontWeightMedium: "500",
|
|
4596
|
+
fontWeightSemibold: "600",
|
|
4597
|
+
fontWeightBold: "700",
|
|
4598
|
+
lineHeightTight: "1.25",
|
|
4599
|
+
lineHeightNormal: "1.5",
|
|
4600
|
+
lineHeightRelaxed: "1.75",
|
|
4601
|
+
// Spacing
|
|
4602
|
+
spacingXs: "0.25rem",
|
|
4603
|
+
spacingSm: "0.5rem",
|
|
4604
|
+
spacingMd: "0.75rem",
|
|
4605
|
+
spacingLg: "1rem",
|
|
4606
|
+
spacingXl: "1.5rem",
|
|
4607
|
+
// Border radius
|
|
4608
|
+
borderRadiusSm: "6px",
|
|
4609
|
+
borderRadiusMd: "10px",
|
|
4610
|
+
borderRadiusLg: "14px",
|
|
4611
|
+
borderRadiusXl: "20px",
|
|
4612
|
+
borderRadiusFull: "9999px",
|
|
4613
|
+
// Shadows
|
|
4614
|
+
shadowSm: "0 1px 2px rgba(0, 0, 0, 0.2)",
|
|
4615
|
+
shadowMd: "0 2px 12px rgba(0, 0, 0, 0.3)",
|
|
4616
|
+
shadowLg: "0 8px 24px rgba(0, 0, 0, 0.4)",
|
|
4617
|
+
shadowXl: "0 16px 48px rgba(0, 0, 0, 0.5)",
|
|
4618
|
+
// Backdrop effects
|
|
4619
|
+
backdropBlur: "blur(20px)",
|
|
4620
|
+
backdropSaturate: "saturate(180%)",
|
|
4621
|
+
// Animation
|
|
4622
|
+
transitionFast: "0.1s ease",
|
|
4623
|
+
transitionNormal: "0.25s ease",
|
|
4624
|
+
transitionSlow: "0.4s ease"
|
|
4625
|
+
};
|
|
4626
|
+
var lightTheme = {
|
|
4627
|
+
// Brand colors
|
|
4628
|
+
colorPrimary: brand[3],
|
|
4629
|
+
colorPrimaryHover: brand[2],
|
|
4630
|
+
colorPrimaryMuted: withAlpha(brand[5], 0.1),
|
|
4631
|
+
// Surface colors
|
|
4632
|
+
colorBackground: withAlpha(slateGrey[12], 0.95),
|
|
4633
|
+
colorBackgroundElevated: withAlpha(slateGrey[11], 0.95),
|
|
4634
|
+
colorBackgroundSubtle: withAlpha(slateGrey[0], 0.02),
|
|
4635
|
+
colorSurface: withAlpha(slateGrey[11], 0.6),
|
|
4636
|
+
colorSurfaceHover: withAlpha(slateGrey[10], 0.6),
|
|
4637
|
+
// Text colors
|
|
4638
|
+
colorText: slateGrey[1],
|
|
4639
|
+
colorTextSecondary: slateGrey[6],
|
|
4640
|
+
colorTextMuted: slateGrey[8],
|
|
4641
|
+
colorTextInverse: slateGrey[12],
|
|
4642
|
+
// Border colors
|
|
4643
|
+
colorBorder: withAlpha(slateGrey[0], 0.12),
|
|
4644
|
+
colorBorderSubtle: withAlpha(slateGrey[0], 0.06),
|
|
4645
|
+
// Semantic colors
|
|
4646
|
+
colorSuccess: green[4],
|
|
4647
|
+
colorSuccessMuted: withAlpha(green[4], 0.12),
|
|
4648
|
+
colorWarning: yellow[4],
|
|
4649
|
+
colorWarningMuted: withAlpha(yellow[4], 0.12),
|
|
4650
|
+
colorError: red[4],
|
|
4651
|
+
colorErrorMuted: withAlpha(red[4], 0.12),
|
|
4652
|
+
colorInfo: blue[4],
|
|
4653
|
+
colorInfoMuted: withAlpha(blue[4], 0.12),
|
|
4654
|
+
// Notification badge
|
|
4655
|
+
colorNotification: brand[3],
|
|
4656
|
+
colorNotificationMuted: withAlpha(brand[3], 0.4),
|
|
4657
|
+
// Glass morphism
|
|
4658
|
+
glassBackground: withAlpha(slateGrey[12], 0.7),
|
|
4659
|
+
glassBackgroundHover: withAlpha(slateGrey[12], 0.8),
|
|
4660
|
+
glassBorder: "rgba(0, 0, 0, 0.06)",
|
|
4661
|
+
glassBlur: "blur(24px)",
|
|
4662
|
+
glassSaturate: "saturate(1.2)",
|
|
4663
|
+
// Typography (same as dark)
|
|
4664
|
+
fontFamily: "-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif",
|
|
4665
|
+
fontFamilyMono: "'SF Mono', 'Fira Code', Consolas, monospace",
|
|
4666
|
+
fontSizeXs: "0.7rem",
|
|
4667
|
+
fontSizeSm: "0.8rem",
|
|
4668
|
+
fontSizeMd: "0.9rem",
|
|
4669
|
+
fontSizeLg: "1rem",
|
|
4670
|
+
fontSizeXl: "1.25rem",
|
|
4671
|
+
fontSizeXxl: "1.5rem",
|
|
4672
|
+
fontWeightNormal: "400",
|
|
4673
|
+
fontWeightMedium: "500",
|
|
4674
|
+
fontWeightSemibold: "600",
|
|
4675
|
+
fontWeightBold: "700",
|
|
4676
|
+
lineHeightTight: "1.25",
|
|
4677
|
+
lineHeightNormal: "1.5",
|
|
4678
|
+
lineHeightRelaxed: "1.75",
|
|
4679
|
+
// Spacing (same as dark)
|
|
4680
|
+
spacingXs: "0.25rem",
|
|
4681
|
+
spacingSm: "0.5rem",
|
|
4682
|
+
spacingMd: "0.75rem",
|
|
4683
|
+
spacingLg: "1rem",
|
|
4684
|
+
spacingXl: "1.5rem",
|
|
4685
|
+
// Border radius (same as dark)
|
|
4686
|
+
borderRadiusSm: "6px",
|
|
4687
|
+
borderRadiusMd: "10px",
|
|
4688
|
+
borderRadiusLg: "14px",
|
|
4689
|
+
borderRadiusXl: "20px",
|
|
4690
|
+
borderRadiusFull: "9999px",
|
|
4691
|
+
// Shadows (lighter for light mode)
|
|
4692
|
+
shadowSm: "0 1px 2px rgba(0, 0, 0, 0.08)",
|
|
4693
|
+
shadowMd: "0 2px 12px rgba(0, 0, 0, 0.12)",
|
|
4694
|
+
shadowLg: "0 8px 24px rgba(0, 0, 0, 0.16)",
|
|
4695
|
+
shadowXl: "0 16px 48px rgba(0, 0, 0, 0.2)",
|
|
4696
|
+
// Backdrop effects
|
|
4697
|
+
backdropBlur: "blur(20px)",
|
|
4698
|
+
backdropSaturate: "saturate(180%)",
|
|
4699
|
+
// Animation
|
|
4700
|
+
transitionFast: "0.1s ease",
|
|
4701
|
+
transitionNormal: "0.25s ease",
|
|
4702
|
+
transitionSlow: "0.4s ease"
|
|
4703
|
+
};
|
|
4704
|
+
function kebabCase(str) {
|
|
4705
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
3327
4706
|
}
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
4707
|
+
var darkDefaults = {
|
|
4708
|
+
mode: "dark",
|
|
4709
|
+
fontFamily: "-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif",
|
|
4710
|
+
colorPrimary: brand[3],
|
|
4711
|
+
colorPrimaryHover: brand[4],
|
|
4712
|
+
borderRadius: "12px",
|
|
4713
|
+
canvas: {
|
|
4714
|
+
position: "right",
|
|
4715
|
+
layout: "overlay",
|
|
4716
|
+
background: withAlpha(slateGrey[1], 0.6),
|
|
4717
|
+
blur: "blur(24px)",
|
|
4718
|
+
border: "none",
|
|
4719
|
+
width: "clamp(380px, 25vw, 520px)",
|
|
4720
|
+
transitionDuration: "300ms",
|
|
4721
|
+
transitionEasing: "cubic-bezier(0.16, 1, 0.3, 1)",
|
|
4722
|
+
transitionFade: "6%"
|
|
4723
|
+
},
|
|
4724
|
+
launcher: {
|
|
4725
|
+
background: button.primary.backgroundDefault,
|
|
4726
|
+
backgroundHover: button.primary.backgroundHover,
|
|
4727
|
+
color: button.primary.icon,
|
|
4728
|
+
size: "56px",
|
|
4729
|
+
shadow: `0 8px 32px ${withAlpha(slateGrey[0], 0.6)}`,
|
|
4730
|
+
borderRadius: "9999px"
|
|
4731
|
+
},
|
|
4732
|
+
tile: {
|
|
4733
|
+
background: withAlpha(slateGrey[1], 0.6),
|
|
4734
|
+
backgroundHover: withAlpha(slateGrey[1], 0.7),
|
|
3350
4735
|
border: "1px solid rgba(255, 255, 255, 0.08)",
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
4736
|
+
borderRadius: "14px",
|
|
4737
|
+
shadow: "0 2px 12px rgba(0, 0, 0, 0.3)",
|
|
4738
|
+
titleColor: text.primary,
|
|
4739
|
+
textColor: text.secondary,
|
|
4740
|
+
iconBackground: `linear-gradient(135deg, ${brand[3]} 0%, ${brand[3]}cc 100%)`,
|
|
4741
|
+
iconShadow: `0 2px 8px ${brand[3]}40`,
|
|
4742
|
+
headerPadding: "0.375rem 0.75rem",
|
|
4743
|
+
bodyPadding: "0 0.75rem 0.5rem",
|
|
4744
|
+
gap: "0.25rem"
|
|
4745
|
+
},
|
|
4746
|
+
overlay: {
|
|
4747
|
+
background: withAlpha(slateGrey[1], 0.6),
|
|
4748
|
+
textColor: text.primary,
|
|
4749
|
+
titleColor: text.primary,
|
|
4750
|
+
arrowColor: withAlpha(slateGrey[1], 0.6),
|
|
4751
|
+
arrowSize: "8px",
|
|
4752
|
+
border: "none",
|
|
4753
|
+
borderRadius: "0",
|
|
4754
|
+
scrimOpacity: "0",
|
|
4755
|
+
highlightRing: `2px solid ${brand[3]}`
|
|
4756
|
+
},
|
|
4757
|
+
notification: {
|
|
4758
|
+
background: withAlpha(slateGrey[0], 0.95),
|
|
4759
|
+
textColor: text.primary,
|
|
4760
|
+
textSecondaryColor: text.secondary,
|
|
4761
|
+
border: `1px solid ${slateGrey[5]}`,
|
|
4762
|
+
borderRadius: "12px",
|
|
4763
|
+
successColor: green[4],
|
|
4764
|
+
warningColor: yellow[4],
|
|
4765
|
+
errorColor: red[4],
|
|
4766
|
+
iconBackground: withAlpha(brand[3], 0.15),
|
|
4767
|
+
progressGradient: `linear-gradient(90deg, ${brand[3]}, ${brand[4]})`
|
|
4768
|
+
},
|
|
4769
|
+
content: {
|
|
4770
|
+
background: withAlpha(slateGrey[3], 0.8),
|
|
4771
|
+
backgroundHover: withAlpha(slateGrey[5], 0.6),
|
|
4772
|
+
border: `1px solid ${withAlpha(slateGrey[5], 0.5)}`,
|
|
4773
|
+
borderRadius: "8px",
|
|
4774
|
+
textColor: text.primary,
|
|
4775
|
+
textSecondaryColor: text.secondary,
|
|
4776
|
+
itemDivider: "none",
|
|
4777
|
+
itemGap: "6px",
|
|
4778
|
+
itemPadding: "12px 16px",
|
|
4779
|
+
itemFontSize: "15px",
|
|
4780
|
+
bodyPadding: "0 16px 12px 16px",
|
|
4781
|
+
bodyFontSize: "14px",
|
|
4782
|
+
categoryPadding: "8px 4px 4px 4px",
|
|
4783
|
+
categoryGap: "4px",
|
|
4784
|
+
categoryFontSize: "12px",
|
|
4785
|
+
searchBackground: withAlpha(slateGrey[3], 0.8),
|
|
4786
|
+
searchColor: text.primary,
|
|
4787
|
+
chevronColor: "currentColor"
|
|
4788
|
+
}
|
|
4789
|
+
};
|
|
4790
|
+
var lightDefaults = {
|
|
4791
|
+
mode: "light",
|
|
4792
|
+
fontFamily: "-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif",
|
|
4793
|
+
colorPrimary: brand[3],
|
|
4794
|
+
colorPrimaryHover: brand[2],
|
|
4795
|
+
borderRadius: "12px",
|
|
4796
|
+
canvas: {
|
|
4797
|
+
position: "right",
|
|
4798
|
+
layout: "overlay",
|
|
4799
|
+
background: withAlpha(slateGrey[12], 0.7),
|
|
4800
|
+
blur: "blur(24px)",
|
|
4801
|
+
border: "none",
|
|
4802
|
+
width: "clamp(380px, 25vw, 520px)",
|
|
4803
|
+
transitionDuration: "300ms",
|
|
4804
|
+
transitionEasing: "cubic-bezier(0.16, 1, 0.3, 1)",
|
|
4805
|
+
transitionFade: "6%"
|
|
4806
|
+
},
|
|
4807
|
+
launcher: {
|
|
4808
|
+
background: brand[3],
|
|
4809
|
+
backgroundHover: brand[2],
|
|
4810
|
+
color: "#ffffff",
|
|
4811
|
+
size: "56px",
|
|
4812
|
+
shadow: "0 8px 32px rgba(0, 0, 0, 0.15)",
|
|
4813
|
+
borderRadius: "9999px"
|
|
4814
|
+
},
|
|
4815
|
+
tile: {
|
|
4816
|
+
background: withAlpha(slateGrey[12], 0.7),
|
|
4817
|
+
backgroundHover: withAlpha(slateGrey[12], 0.8),
|
|
4818
|
+
border: "1px solid rgba(0, 0, 0, 0.06)",
|
|
4819
|
+
borderRadius: "14px",
|
|
4820
|
+
shadow: "0 2px 12px rgba(0, 0, 0, 0.12)",
|
|
4821
|
+
titleColor: slateGrey[1],
|
|
4822
|
+
textColor: slateGrey[6],
|
|
4823
|
+
iconBackground: `linear-gradient(135deg, ${brand[3]} 0%, ${brand[3]}cc 100%)`,
|
|
4824
|
+
iconShadow: `0 2px 8px ${brand[3]}40`,
|
|
4825
|
+
headerPadding: "0.375rem 0.75rem",
|
|
4826
|
+
bodyPadding: "0 0.75rem 0.5rem",
|
|
4827
|
+
gap: "0.25rem"
|
|
4828
|
+
},
|
|
4829
|
+
overlay: {
|
|
4830
|
+
background: withAlpha(slateGrey[12], 0.7),
|
|
4831
|
+
textColor: slateGrey[1],
|
|
4832
|
+
titleColor: slateGrey[1],
|
|
4833
|
+
arrowColor: withAlpha(slateGrey[12], 0.7),
|
|
4834
|
+
arrowSize: "8px",
|
|
4835
|
+
border: "none",
|
|
4836
|
+
borderRadius: "0",
|
|
4837
|
+
scrimOpacity: "0",
|
|
4838
|
+
highlightRing: `2px solid ${brand[3]}`
|
|
4839
|
+
},
|
|
4840
|
+
notification: {
|
|
4841
|
+
background: withAlpha(slateGrey[12], 0.95),
|
|
4842
|
+
textColor: slateGrey[1],
|
|
4843
|
+
textSecondaryColor: slateGrey[6],
|
|
4844
|
+
border: `1px solid ${withAlpha(slateGrey[0], 0.12)}`,
|
|
4845
|
+
borderRadius: "12px",
|
|
4846
|
+
successColor: green[4],
|
|
4847
|
+
warningColor: yellow[4],
|
|
4848
|
+
errorColor: red[4],
|
|
4849
|
+
iconBackground: withAlpha(brand[3], 0.1),
|
|
4850
|
+
progressGradient: `linear-gradient(90deg, ${brand[3]}, ${brand[2]})`
|
|
4851
|
+
},
|
|
4852
|
+
content: {
|
|
4853
|
+
background: withAlpha(slateGrey[12], 0.8),
|
|
4854
|
+
backgroundHover: withAlpha(slateGrey[11], 0.6),
|
|
4855
|
+
border: `1px solid ${slateGrey[11]}`,
|
|
4856
|
+
borderRadius: "8px",
|
|
4857
|
+
textColor: slateGrey[1],
|
|
4858
|
+
textSecondaryColor: slateGrey[6],
|
|
4859
|
+
itemDivider: "none",
|
|
4860
|
+
itemGap: "6px",
|
|
4861
|
+
itemPadding: "12px 16px",
|
|
4862
|
+
itemFontSize: "15px",
|
|
4863
|
+
bodyPadding: "0 16px 12px 16px",
|
|
4864
|
+
bodyFontSize: "14px",
|
|
4865
|
+
categoryPadding: "8px 4px 4px 4px",
|
|
4866
|
+
categoryGap: "4px",
|
|
4867
|
+
categoryFontSize: "12px",
|
|
4868
|
+
searchBackground: slateGrey[12],
|
|
4869
|
+
searchColor: slateGrey[1],
|
|
4870
|
+
chevronColor: "currentColor"
|
|
4871
|
+
}
|
|
4872
|
+
};
|
|
4873
|
+
function mergeThemeConfig(customer) {
|
|
4874
|
+
var _a2, _b, _c, _d, _e;
|
|
4875
|
+
const base2 = customer.mode === "light" ? lightDefaults : darkDefaults;
|
|
4876
|
+
return {
|
|
4877
|
+
mode: (_a2 = customer.mode) != null ? _a2 : base2.mode,
|
|
4878
|
+
fontFamily: (_b = customer.fontFamily) != null ? _b : base2.fontFamily,
|
|
4879
|
+
colorPrimary: (_c = customer.colorPrimary) != null ? _c : base2.colorPrimary,
|
|
4880
|
+
colorPrimaryHover: (_d = customer.colorPrimaryHover) != null ? _d : base2.colorPrimaryHover,
|
|
4881
|
+
borderRadius: (_e = customer.borderRadius) != null ? _e : base2.borderRadius,
|
|
4882
|
+
canvas: { ...base2.canvas, ...customer.canvas },
|
|
4883
|
+
launcher: { ...base2.launcher, ...customer.launcher },
|
|
4884
|
+
tile: { ...base2.tile, ...customer.tile },
|
|
4885
|
+
overlay: { ...base2.overlay, ...customer.overlay },
|
|
4886
|
+
notification: { ...base2.notification, ...customer.notification },
|
|
4887
|
+
content: { ...base2.content, ...customer.content }
|
|
3366
4888
|
};
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
4889
|
+
}
|
|
4890
|
+
function mergeThemeWithWorkspace(workspaceTheme, configTheme) {
|
|
4891
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
4892
|
+
const mode = (_b = (_a2 = configTheme.mode) != null ? _a2 : workspaceTheme.mode) != null ? _b : "dark";
|
|
4893
|
+
const base2 = mode === "light" ? lightDefaults : darkDefaults;
|
|
4894
|
+
return {
|
|
4895
|
+
mode,
|
|
4896
|
+
fontFamily: (_d = (_c = configTheme.fontFamily) != null ? _c : workspaceTheme.fontFamily) != null ? _d : base2.fontFamily,
|
|
4897
|
+
colorPrimary: (_f = (_e = configTheme.colorPrimary) != null ? _e : workspaceTheme.colorPrimary) != null ? _f : base2.colorPrimary,
|
|
4898
|
+
colorPrimaryHover: (_h = (_g = configTheme.colorPrimaryHover) != null ? _g : workspaceTheme.colorPrimaryHover) != null ? _h : base2.colorPrimaryHover,
|
|
4899
|
+
borderRadius: (_j = (_i = configTheme.borderRadius) != null ? _i : workspaceTheme.borderRadius) != null ? _j : base2.borderRadius,
|
|
4900
|
+
canvas: { ...base2.canvas, ...workspaceTheme.canvas, ...configTheme.canvas },
|
|
4901
|
+
launcher: { ...base2.launcher, ...workspaceTheme.launcher, ...configTheme.launcher },
|
|
4902
|
+
tile: { ...base2.tile, ...workspaceTheme.tile, ...configTheme.tile },
|
|
4903
|
+
overlay: { ...base2.overlay, ...workspaceTheme.overlay, ...configTheme.overlay },
|
|
4904
|
+
notification: {
|
|
4905
|
+
...base2.notification,
|
|
4906
|
+
...workspaceTheme.notification,
|
|
4907
|
+
...configTheme.notification
|
|
4908
|
+
},
|
|
4909
|
+
content: { ...base2.content, ...workspaceTheme.content, ...configTheme.content }
|
|
3378
4910
|
};
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
children: title != null ? title : widget
|
|
3402
|
-
}
|
|
3403
|
-
) })
|
|
3404
|
-
] }),
|
|
3405
|
-
/* @__PURE__ */ jsx5(
|
|
3406
|
-
"div",
|
|
3407
|
-
{
|
|
3408
|
-
style: {
|
|
3409
|
-
padding: "0 1rem 1rem",
|
|
3410
|
-
borderTop: `1px solid ${border.secondary}`
|
|
3411
|
-
},
|
|
3412
|
-
children: /* @__PURE__ */ jsx5("div", { style: { paddingTop: "0.875rem" }, children: /* @__PURE__ */ jsx5(WidgetMount, { widgetId: widget, props }) })
|
|
3413
|
-
}
|
|
3414
|
-
)
|
|
3415
|
-
]
|
|
4911
|
+
}
|
|
4912
|
+
var ELEMENT_SECTIONS = [
|
|
4913
|
+
"canvas",
|
|
4914
|
+
"launcher",
|
|
4915
|
+
"tile",
|
|
4916
|
+
"overlay",
|
|
4917
|
+
"notification",
|
|
4918
|
+
"content"
|
|
4919
|
+
];
|
|
4920
|
+
function flattenThemeConfig(config) {
|
|
4921
|
+
const vars = {};
|
|
4922
|
+
if (config.fontFamily) vars["--sc-font-family"] = config.fontFamily;
|
|
4923
|
+
if (config.colorPrimary) vars["--sc-color-primary"] = config.colorPrimary;
|
|
4924
|
+
if (config.colorPrimaryHover) vars["--sc-color-primary-hover"] = config.colorPrimaryHover;
|
|
4925
|
+
if (config.borderRadius) vars["--sc-border-radius"] = config.borderRadius;
|
|
4926
|
+
for (const section of ELEMENT_SECTIONS) {
|
|
4927
|
+
const sectionConfig = config[section];
|
|
4928
|
+
if (!sectionConfig) continue;
|
|
4929
|
+
for (const [key, value] of Object.entries(sectionConfig)) {
|
|
4930
|
+
if (value !== void 0) {
|
|
4931
|
+
vars[`--sc-${section}-${kebabCase(key)}`] = value;
|
|
4932
|
+
}
|
|
3416
4933
|
}
|
|
4934
|
+
}
|
|
4935
|
+
return vars;
|
|
4936
|
+
}
|
|
4937
|
+
|
|
4938
|
+
// src/theme/ThemeProvider.tsx
|
|
4939
|
+
import { createContext as createContext3, useContext as useContext3, useEffect as useEffect6, useMemo as useMemo4 } from "react";
|
|
4940
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
4941
|
+
var ThemeContext = createContext3(null);
|
|
4942
|
+
function ThemeProvider({
|
|
4943
|
+
children,
|
|
4944
|
+
themeConfig,
|
|
4945
|
+
workspaceTheme,
|
|
4946
|
+
shadowRoot
|
|
4947
|
+
}) {
|
|
4948
|
+
const merged = useMemo4(
|
|
4949
|
+
() => workspaceTheme ? mergeThemeWithWorkspace(workspaceTheme, themeConfig != null ? themeConfig : {}) : mergeThemeConfig(themeConfig != null ? themeConfig : {}),
|
|
4950
|
+
[themeConfig, workspaceTheme]
|
|
3417
4951
|
);
|
|
4952
|
+
const cssVariables = useMemo4(() => flattenThemeConfig(merged), [merged]);
|
|
4953
|
+
useEffect6(() => {
|
|
4954
|
+
if (!shadowRoot) return;
|
|
4955
|
+
let styleEl = shadowRoot.querySelector("#sc-theme-vars");
|
|
4956
|
+
if (!styleEl) {
|
|
4957
|
+
styleEl = document.createElement("style");
|
|
4958
|
+
styleEl.id = "sc-theme-vars";
|
|
4959
|
+
shadowRoot.insertBefore(styleEl, shadowRoot.firstChild);
|
|
4960
|
+
}
|
|
4961
|
+
const cssRules = Object.entries(cssVariables).map(([key, value2]) => ` ${key}: ${value2};`).join("\n");
|
|
4962
|
+
styleEl.textContent = `:host {
|
|
4963
|
+
${cssRules}
|
|
4964
|
+
}`;
|
|
4965
|
+
}, [shadowRoot, cssVariables]);
|
|
4966
|
+
const value = {
|
|
4967
|
+
config: merged,
|
|
4968
|
+
mode: merged.mode,
|
|
4969
|
+
cssVariables
|
|
4970
|
+
};
|
|
4971
|
+
return /* @__PURE__ */ jsx6(ThemeContext.Provider, { value, children });
|
|
4972
|
+
}
|
|
4973
|
+
function useTheme() {
|
|
4974
|
+
const context = useContext3(ThemeContext);
|
|
4975
|
+
if (!context) {
|
|
4976
|
+
throw new Error("useTheme must be used within a ThemeProvider");
|
|
4977
|
+
}
|
|
4978
|
+
return context;
|
|
3418
4979
|
}
|
|
3419
4980
|
|
|
3420
4981
|
// src/components/ShadowCanvasOverlay.tsx
|
|
3421
|
-
import {
|
|
3422
|
-
import { createPortal } from "react-dom";
|
|
3423
|
-
import { Fragment, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
4982
|
+
import { Fragment, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
3424
4983
|
var LAUNCHER_STYLES_ID = "syntro-launcher-styles";
|
|
3425
|
-
|
|
3426
|
-
@keyframes syntro-launcher-pulse {
|
|
3427
|
-
0%, 100% {
|
|
3428
|
-
box-shadow: 0 20px 45px ${slateGrey[0]}59, 0 0 0 0 ${brand[3]}66;
|
|
3429
|
-
}
|
|
3430
|
-
50% {
|
|
3431
|
-
box-shadow: 0 20px 45px ${slateGrey[0]}59, 0 0 0 8px ${brand[3]}00;
|
|
3432
|
-
}
|
|
3433
|
-
}
|
|
3434
|
-
@keyframes syntro-launcher-glow {
|
|
3435
|
-
0%, 100% {
|
|
3436
|
-
border-color: ${slateGrey[5]};
|
|
3437
|
-
}
|
|
3438
|
-
50% {
|
|
3439
|
-
border-color: ${brand[4]}99;
|
|
3440
|
-
}
|
|
3441
|
-
}
|
|
3442
|
-
.syntro-launcher-animate {
|
|
3443
|
-
animation: syntro-launcher-pulse 2s ease-in-out infinite, syntro-launcher-glow 2s ease-in-out infinite;
|
|
3444
|
-
}
|
|
3445
|
-
.syntro-launcher-animate:hover {
|
|
3446
|
-
animation: none;
|
|
3447
|
-
}
|
|
3448
|
-
@keyframes syntro-badge-ping {
|
|
3449
|
-
0% { transform: scale(1); opacity: 1; }
|
|
3450
|
-
75%, 100% { transform: scale(2.2); opacity: 0; }
|
|
3451
|
-
}
|
|
3452
|
-
@keyframes syntro-badge-glow {
|
|
3453
|
-
0%, 100% { box-shadow: 0 0 8px 2px ${withAlpha(brand[4], 0.3)}; }
|
|
3454
|
-
50% { box-shadow: 0 0 20px 6px ${withAlpha(brand[4], 0.5)}; }
|
|
3455
|
-
}
|
|
3456
|
-
@keyframes syntro-badge-bounce {
|
|
3457
|
-
0%, 100% { transform: translateY(0); }
|
|
3458
|
-
25% { transform: translateY(-6px); }
|
|
3459
|
-
50% { transform: translateY(-3px); }
|
|
3460
|
-
}
|
|
3461
|
-
.syntro-badge-ping { animation: syntro-badge-ping 1.5s cubic-bezier(0,0,0.2,1) infinite; }
|
|
3462
|
-
.syntro-badge-glow { animation: syntro-badge-glow 2s ease-in-out infinite; }
|
|
3463
|
-
.syntro-badge-bounce { animation: syntro-badge-bounce 2s ease-in-out infinite; }
|
|
3464
|
-
`;
|
|
3465
|
-
function ensureLauncherStyles(target) {
|
|
4984
|
+
function ensureLauncherStyles(target, css) {
|
|
3466
4985
|
if (target.querySelector(`#${LAUNCHER_STYLES_ID}`)) return;
|
|
3467
4986
|
const style = document.createElement("style");
|
|
3468
4987
|
style.id = LAUNCHER_STYLES_ID;
|
|
3469
|
-
style.textContent =
|
|
4988
|
+
style.textContent = css;
|
|
3470
4989
|
target.appendChild(style);
|
|
3471
4990
|
}
|
|
3472
|
-
var DEFAULT_THEME = {
|
|
3473
|
-
position: "right",
|
|
3474
|
-
baseWidth: "clamp(320px, 16.666vw, 420px)",
|
|
3475
|
-
expandedWidth: "40vw",
|
|
3476
|
-
zIndex: 2147483600,
|
|
3477
|
-
backdropBlur: "18px",
|
|
3478
|
-
mode: "dark",
|
|
3479
|
-
colorPrimary: brand[3],
|
|
3480
|
-
colorBackground: slateGrey[1],
|
|
3481
|
-
colorText: text.primary,
|
|
3482
|
-
colorTextSecondary: text.secondary,
|
|
3483
|
-
borderRadius: "12px",
|
|
3484
|
-
glassBackground: withAlpha(slateGrey[1], 0.6),
|
|
3485
|
-
glassBlur: "blur(24px)",
|
|
3486
|
-
glassSaturate: "saturate(1.2)"
|
|
3487
|
-
};
|
|
3488
4991
|
function ShadowCanvasOverlay({
|
|
3489
4992
|
isOpen,
|
|
3490
4993
|
onToggle,
|
|
3491
4994
|
telemetry,
|
|
3492
4995
|
launcherLabel: _launcherLabel = "Adaptives",
|
|
4996
|
+
launcherIcon,
|
|
3493
4997
|
launcherAnimate = false,
|
|
3494
4998
|
launcherAnimationStyle: _launcherAnimationStyle = "pulse",
|
|
3495
4999
|
notificationCount: _notificationCount,
|
|
@@ -3498,21 +5002,21 @@ function ShadowCanvasOverlay({
|
|
|
3498
5002
|
isLoading,
|
|
3499
5003
|
error: error2,
|
|
3500
5004
|
canvasTitle,
|
|
3501
|
-
displayMode = "standard"
|
|
3502
|
-
theme: themeOverride
|
|
5005
|
+
displayMode = "standard"
|
|
3503
5006
|
}) {
|
|
3504
|
-
var _a2, _b, _c, _d
|
|
5007
|
+
var _a2, _b, _c, _d;
|
|
3505
5008
|
const [mounted, setMounted] = useState5(false);
|
|
3506
5009
|
const [launcherPos, setLauncherPos] = useState5(null);
|
|
3507
|
-
const dragRef =
|
|
5010
|
+
const dragRef = useRef5(null);
|
|
3508
5011
|
const runtime3 = useRuntime();
|
|
3509
5012
|
const { shadowRoot, portalRoot } = useShadowRoot();
|
|
5013
|
+
const { config } = useTheme();
|
|
3510
5014
|
const { notifications, dismiss: dismissNotification } = useNotifications(
|
|
3511
5015
|
(_a2 = runtime3 == null ? void 0 : runtime3.events) != null ? _a2 : null,
|
|
3512
5016
|
tiles
|
|
3513
5017
|
);
|
|
3514
5018
|
useNotifyWatcher(runtime3, tiles, runtime3 == null ? void 0 : runtime3.apps);
|
|
3515
|
-
const handleNotificationClick =
|
|
5019
|
+
const handleNotificationClick = useCallback4(
|
|
3516
5020
|
(notif) => {
|
|
3517
5021
|
if (runtime3) {
|
|
3518
5022
|
runtime3.events.publish(StandardEvents.NOTIFICATION_CLICKED, {
|
|
@@ -3534,8 +5038,44 @@ function ShadowCanvasOverlay({
|
|
|
3534
5038
|
},
|
|
3535
5039
|
[runtime3, isOpen, onToggle, dismissNotification]
|
|
3536
5040
|
);
|
|
3537
|
-
const
|
|
3538
|
-
|
|
5041
|
+
const launcherCss = useMemo5(
|
|
5042
|
+
() => `
|
|
5043
|
+
@keyframes syntro-launcher-pulse {
|
|
5044
|
+
0%, 100% {
|
|
5045
|
+
box-shadow: 0 20px 45px rgba(0,0,0,0.35), 0 0 0 0 ${config.colorPrimary}66;
|
|
5046
|
+
}
|
|
5047
|
+
50% {
|
|
5048
|
+
box-shadow: 0 20px 45px rgba(0,0,0,0.35), 0 0 0 8px ${config.colorPrimary}00;
|
|
5049
|
+
}
|
|
5050
|
+
}
|
|
5051
|
+
@keyframes syntro-launcher-glow {
|
|
5052
|
+
0%, 100% { border-color: rgba(255,255,255,0.1); }
|
|
5053
|
+
50% { border-color: ${config.colorPrimaryHover}99; }
|
|
5054
|
+
}
|
|
5055
|
+
.syntro-launcher-animate {
|
|
5056
|
+
animation: syntro-launcher-pulse 2s ease-in-out infinite, syntro-launcher-glow 2s ease-in-out infinite;
|
|
5057
|
+
}
|
|
5058
|
+
.syntro-launcher-animate:hover { animation: none; }
|
|
5059
|
+
@keyframes syntro-badge-ping {
|
|
5060
|
+
0% { transform: scale(1); opacity: 1; }
|
|
5061
|
+
75%, 100% { transform: scale(2.2); opacity: 0; }
|
|
5062
|
+
}
|
|
5063
|
+
@keyframes syntro-badge-glow {
|
|
5064
|
+
0%, 100% { box-shadow: 0 0 8px 2px ${config.colorPrimaryHover}4d; }
|
|
5065
|
+
50% { box-shadow: 0 0 20px 6px ${config.colorPrimaryHover}80; }
|
|
5066
|
+
}
|
|
5067
|
+
@keyframes syntro-badge-bounce {
|
|
5068
|
+
0%, 100% { transform: translateY(0); }
|
|
5069
|
+
25% { transform: translateY(-6px); }
|
|
5070
|
+
50% { transform: translateY(-3px); }
|
|
5071
|
+
}
|
|
5072
|
+
.syntro-badge-ping { animation: syntro-badge-ping 1.5s cubic-bezier(0,0,0.2,1) infinite; }
|
|
5073
|
+
.syntro-badge-glow { animation: syntro-badge-glow 2s ease-in-out infinite; }
|
|
5074
|
+
.syntro-badge-bounce { animation: syntro-badge-bounce 2s ease-in-out infinite; }
|
|
5075
|
+
`,
|
|
5076
|
+
[config.colorPrimary, config.colorPrimaryHover]
|
|
5077
|
+
);
|
|
5078
|
+
useEffect7(() => {
|
|
3539
5079
|
if (!isOpen) return;
|
|
3540
5080
|
tiles.forEach((tile) => {
|
|
3541
5081
|
telemetry == null ? void 0 : telemetry.trackRectangleViewed(tile.id, "overlay");
|
|
@@ -3545,11 +5085,11 @@ function ShadowCanvasOverlay({
|
|
|
3545
5085
|
}
|
|
3546
5086
|
});
|
|
3547
5087
|
}, [telemetry, runtime3, isOpen, tiles]);
|
|
3548
|
-
|
|
5088
|
+
useEffect7(() => {
|
|
3549
5089
|
setMounted(true);
|
|
3550
|
-
ensureLauncherStyles(shadowRoot);
|
|
3551
|
-
}, [shadowRoot]);
|
|
3552
|
-
const toggle2 =
|
|
5090
|
+
ensureLauncherStyles(shadowRoot, launcherCss);
|
|
5091
|
+
}, [shadowRoot, launcherCss]);
|
|
5092
|
+
const toggle2 = useCallback4(() => {
|
|
3553
5093
|
const next = !isOpen;
|
|
3554
5094
|
if (next) {
|
|
3555
5095
|
telemetry == null ? void 0 : telemetry.trackCanvasOpened("overlay");
|
|
@@ -3562,7 +5102,7 @@ function ShadowCanvasOverlay({
|
|
|
3562
5102
|
}
|
|
3563
5103
|
onToggle();
|
|
3564
5104
|
}, [isOpen, telemetry, runtime3, onToggle]);
|
|
3565
|
-
const onLauncherPointerDown =
|
|
5105
|
+
const onLauncherPointerDown = useCallback4((e) => {
|
|
3566
5106
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
3567
5107
|
dragRef.current = {
|
|
3568
5108
|
startX: e.clientX,
|
|
@@ -3573,7 +5113,7 @@ function ShadowCanvasOverlay({
|
|
|
3573
5113
|
};
|
|
3574
5114
|
e.currentTarget.setPointerCapture(e.pointerId);
|
|
3575
5115
|
}, []);
|
|
3576
|
-
const onLauncherPointerMove =
|
|
5116
|
+
const onLauncherPointerMove = useCallback4((e) => {
|
|
3577
5117
|
const drag = dragRef.current;
|
|
3578
5118
|
if (!drag) return;
|
|
3579
5119
|
const dx = e.clientX - drag.startX;
|
|
@@ -3585,8 +5125,8 @@ function ShadowCanvasOverlay({
|
|
|
3585
5125
|
setLauncherPos({ x: drag.startElX + dx, y: drag.startElY + dy });
|
|
3586
5126
|
}
|
|
3587
5127
|
}, []);
|
|
3588
|
-
const onLauncherPointerUp =
|
|
3589
|
-
(
|
|
5128
|
+
const onLauncherPointerUp = useCallback4(
|
|
5129
|
+
(_e) => {
|
|
3590
5130
|
const drag = dragRef.current;
|
|
3591
5131
|
dragRef.current = null;
|
|
3592
5132
|
if (drag && !drag.dragged) {
|
|
@@ -3596,30 +5136,77 @@ function ShadowCanvasOverlay({
|
|
|
3596
5136
|
[toggle2]
|
|
3597
5137
|
);
|
|
3598
5138
|
const isFocused = displayMode === "focused";
|
|
3599
|
-
const isRight =
|
|
5139
|
+
const isRight = config.canvas.position === "right";
|
|
5140
|
+
const isPush = config.canvas.layout === "push";
|
|
5141
|
+
const canvasBorder = (_b = config.canvas.border) != null ? _b : "none";
|
|
5142
|
+
const containerRef = useRef5(null);
|
|
5143
|
+
const zIndex = 2147483600;
|
|
5144
|
+
useEffect7(() => {
|
|
5145
|
+
var _a3, _b2, _c2, _d2;
|
|
5146
|
+
if (!isPush) return;
|
|
5147
|
+
const root = document.documentElement;
|
|
5148
|
+
const prop = isRight ? "marginRight" : "marginLeft";
|
|
5149
|
+
const duration = (_a3 = config.canvas.transitionDuration) != null ? _a3 : "300ms";
|
|
5150
|
+
const easing = (_b2 = config.canvas.transitionEasing) != null ? _b2 : "cubic-bezier(0.16, 1, 0.3, 1)";
|
|
5151
|
+
const prevTransition = root.style.transition;
|
|
5152
|
+
root.style.transition = `${prop} ${duration} ${easing}`;
|
|
5153
|
+
if (isOpen) {
|
|
5154
|
+
const width = (_d2 = (_c2 = containerRef.current) == null ? void 0 : _c2.offsetWidth) != null ? _d2 : 380;
|
|
5155
|
+
root.style[prop] = `${width}px`;
|
|
5156
|
+
} else {
|
|
5157
|
+
root.style[prop] = "0px";
|
|
5158
|
+
}
|
|
5159
|
+
return () => {
|
|
5160
|
+
root.style[prop] = "";
|
|
5161
|
+
root.style.transition = prevTransition;
|
|
5162
|
+
};
|
|
5163
|
+
}, [isPush, isOpen, isRight, config.canvas.transitionDuration, config.canvas.transitionEasing]);
|
|
5164
|
+
useEffect7(() => {
|
|
5165
|
+
if (!isPush || !isOpen) return;
|
|
5166
|
+
const container = containerRef.current;
|
|
5167
|
+
if (!container) return;
|
|
5168
|
+
const prop = isRight ? "marginRight" : "marginLeft";
|
|
5169
|
+
const observer = new ResizeObserver(([entry]) => {
|
|
5170
|
+
document.documentElement.style[prop] = `${entry.contentRect.width}px`;
|
|
5171
|
+
});
|
|
5172
|
+
observer.observe(container);
|
|
5173
|
+
return () => observer.disconnect();
|
|
5174
|
+
}, [isPush, isOpen, isRight]);
|
|
3600
5175
|
const containerStyle = {
|
|
3601
5176
|
display: "flex",
|
|
3602
5177
|
flexDirection: "column",
|
|
3603
|
-
width: isFocused ?
|
|
5178
|
+
width: isFocused ? "40vw" : config.canvas.width,
|
|
3604
5179
|
minWidth: "320px",
|
|
3605
5180
|
height: "100%",
|
|
3606
5181
|
maxHeight: "100%",
|
|
3607
5182
|
pointerEvents: "auto",
|
|
3608
5183
|
opacity: isOpen ? 1 : 0,
|
|
3609
|
-
transition:
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
5184
|
+
transition: (() => {
|
|
5185
|
+
var _a3, _b2;
|
|
5186
|
+
const dur = (_a3 = config.canvas.transitionDuration) != null ? _a3 : "300ms";
|
|
5187
|
+
const ease = (_b2 = config.canvas.transitionEasing) != null ? _b2 : "cubic-bezier(0.16, 1, 0.3, 1)";
|
|
5188
|
+
return isOpen ? `transform ${dur} ${ease}, opacity ${dur} ease-out` : `transform ${dur} ${ease}, opacity ${dur} ease-in`;
|
|
5189
|
+
})(),
|
|
5190
|
+
color: "var(--sc-overlay-text-color)",
|
|
5191
|
+
background: "var(--sc-canvas-background)",
|
|
5192
|
+
// Standard mode: config blur only. Focused mode: config blur + saturate boost.
|
|
5193
|
+
...(() => {
|
|
5194
|
+
var _a3;
|
|
5195
|
+
const blur = (_a3 = config.canvas.blur) != null ? _a3 : "blur(24px)";
|
|
5196
|
+
const filter = isFocused && blur !== "none" ? `${blur} saturate(1.2)` : blur;
|
|
5197
|
+
return { backdropFilter: filter, WebkitBackdropFilter: filter };
|
|
5198
|
+
})(),
|
|
5199
|
+
// Tight fade mask so blur cuts off sharply at the leading edge.
|
|
5200
|
+
// Disabled when a visible border is configured (mask would fade the border).
|
|
5201
|
+
...(() => {
|
|
5202
|
+
var _a3;
|
|
5203
|
+
if (isFocused || canvasBorder && canvasBorder !== "none") return {};
|
|
5204
|
+
const fade = (_a3 = config.canvas.transitionFade) != null ? _a3 : "6%";
|
|
5205
|
+
const mask = isRight ? `linear-gradient(to right, transparent, black ${fade})` : `linear-gradient(to left, transparent, black ${fade})`;
|
|
5206
|
+
return { maskImage: mask, WebkitMaskImage: mask };
|
|
5207
|
+
})(),
|
|
5208
|
+
border: canvasBorder,
|
|
5209
|
+
borderRadius: "var(--sc-overlay-border-radius, 0)",
|
|
3623
5210
|
boxShadow: "none",
|
|
3624
5211
|
// Transform logic
|
|
3625
5212
|
transform: isOpen ? "translateX(0)" : isRight ? "translateX(120%)" : "translateX(-120%)"
|
|
@@ -3633,7 +5220,7 @@ function ShadowCanvasOverlay({
|
|
|
3633
5220
|
pointerEvents: "none",
|
|
3634
5221
|
padding: "0"
|
|
3635
5222
|
};
|
|
3636
|
-
const content = /* @__PURE__ */
|
|
5223
|
+
const content = /* @__PURE__ */ jsx7(
|
|
3637
5224
|
"div",
|
|
3638
5225
|
{
|
|
3639
5226
|
"data-shadow-canvas-id": "overlay-root",
|
|
@@ -3641,11 +5228,11 @@ function ShadowCanvasOverlay({
|
|
|
3641
5228
|
position: "fixed",
|
|
3642
5229
|
inset: 0,
|
|
3643
5230
|
pointerEvents: isOpen ? "auto" : "none",
|
|
3644
|
-
zIndex
|
|
5231
|
+
zIndex
|
|
3645
5232
|
},
|
|
3646
5233
|
children: /* @__PURE__ */ jsxs3("div", { style: wrapperStyle, children: [
|
|
3647
|
-
/* @__PURE__ */ jsxs3("div", { "data-shadow-canvas-id": "overlay-container", style: containerStyle, children: [
|
|
3648
|
-
isFocused && canvasTitle && /* @__PURE__ */
|
|
5234
|
+
/* @__PURE__ */ jsxs3("div", { ref: containerRef, "data-shadow-canvas-id": "overlay-container", style: containerStyle, children: [
|
|
5235
|
+
isFocused && canvasTitle && /* @__PURE__ */ jsx7("header", { style: { color: "white", padding: "1.5rem 1.5rem 0" }, children: /* @__PURE__ */ jsx7(
|
|
3649
5236
|
"p",
|
|
3650
5237
|
{
|
|
3651
5238
|
style: {
|
|
@@ -3653,17 +5240,32 @@ function ShadowCanvasOverlay({
|
|
|
3653
5240
|
fontSize: "0.7rem",
|
|
3654
5241
|
textTransform: "uppercase",
|
|
3655
5242
|
letterSpacing: "0.5em",
|
|
3656
|
-
color: text
|
|
5243
|
+
color: "var(--sc-notification-text-secondary-color)"
|
|
3657
5244
|
},
|
|
3658
5245
|
children: canvasTitle
|
|
3659
5246
|
}
|
|
3660
5247
|
) }),
|
|
3661
|
-
/* @__PURE__ */
|
|
3662
|
-
"
|
|
3663
|
-
|
|
3664
|
-
|
|
5248
|
+
/* @__PURE__ */ jsx7("div", { style: { flex: 1, overflowY: "auto", padding: isFocused ? "0" : "1rem" }, children: isLoading ? /* @__PURE__ */ jsx7(
|
|
5249
|
+
"div",
|
|
5250
|
+
{
|
|
5251
|
+
style: { color: "var(--sc-overlay-text-color)", padding: isFocused ? "1rem" : "0" },
|
|
5252
|
+
children: "Loading..."
|
|
5253
|
+
}
|
|
5254
|
+
) : error2 ? /* @__PURE__ */ jsxs3(
|
|
5255
|
+
"div",
|
|
5256
|
+
{
|
|
5257
|
+
style: {
|
|
5258
|
+
color: "var(--sc-notification-error-color)",
|
|
5259
|
+
padding: isFocused ? "1rem" : "0"
|
|
5260
|
+
},
|
|
5261
|
+
children: [
|
|
5262
|
+
"Failed to load: ",
|
|
5263
|
+
error2
|
|
5264
|
+
]
|
|
5265
|
+
}
|
|
5266
|
+
) : isFocused ? (
|
|
3665
5267
|
/* Focused Mode: Render first tile full size */
|
|
3666
|
-
tiles.length > 0 ? /* @__PURE__ */
|
|
5268
|
+
tiles.length > 0 ? /* @__PURE__ */ jsx7(
|
|
3667
5269
|
TileCard,
|
|
3668
5270
|
{
|
|
3669
5271
|
config: tiles[0],
|
|
@@ -3674,7 +5276,7 @@ function ShadowCanvasOverlay({
|
|
|
3674
5276
|
) : null
|
|
3675
5277
|
) : (
|
|
3676
5278
|
/* Standard Mode: Stacked cards — widgets always visible */
|
|
3677
|
-
/* @__PURE__ */
|
|
5279
|
+
/* @__PURE__ */ jsx7(
|
|
3678
5280
|
"div",
|
|
3679
5281
|
{
|
|
3680
5282
|
style: {
|
|
@@ -3683,7 +5285,7 @@ function ShadowCanvasOverlay({
|
|
|
3683
5285
|
gap: "0.75rem",
|
|
3684
5286
|
width: "100%"
|
|
3685
5287
|
},
|
|
3686
|
-
children: tiles.map((tile) => /* @__PURE__ */
|
|
5288
|
+
children: tiles.map((tile) => /* @__PURE__ */ jsx7(
|
|
3687
5289
|
TileCard,
|
|
3688
5290
|
{
|
|
3689
5291
|
config: tile,
|
|
@@ -3698,7 +5300,7 @@ function ShadowCanvasOverlay({
|
|
|
3698
5300
|
) }),
|
|
3699
5301
|
footerSlot
|
|
3700
5302
|
] }),
|
|
3701
|
-
/* @__PURE__ */
|
|
5303
|
+
/* @__PURE__ */ jsx7(
|
|
3702
5304
|
"div",
|
|
3703
5305
|
{
|
|
3704
5306
|
onClick: toggle2,
|
|
@@ -3723,16 +5325,16 @@ function ShadowCanvasOverlay({
|
|
|
3723
5325
|
position: "fixed",
|
|
3724
5326
|
inset: 0,
|
|
3725
5327
|
pointerEvents: "none",
|
|
3726
|
-
zIndex:
|
|
5328
|
+
zIndex: zIndex + 47
|
|
3727
5329
|
},
|
|
3728
5330
|
children: [
|
|
3729
|
-
/* @__PURE__ */
|
|
5331
|
+
/* @__PURE__ */ jsx7(
|
|
3730
5332
|
NotificationToastStack,
|
|
3731
5333
|
{
|
|
3732
5334
|
notifications,
|
|
3733
5335
|
onDismiss: dismissNotification,
|
|
3734
5336
|
onClickNotification: handleNotificationClick,
|
|
3735
|
-
position:
|
|
5337
|
+
position: (_c = config.canvas.position) != null ? _c : "right"
|
|
3736
5338
|
}
|
|
3737
5339
|
),
|
|
3738
5340
|
/* @__PURE__ */ jsxs3(
|
|
@@ -3752,36 +5354,36 @@ function ShadowCanvasOverlay({
|
|
|
3752
5354
|
display: "flex",
|
|
3753
5355
|
alignItems: "center",
|
|
3754
5356
|
justifyContent: "center",
|
|
3755
|
-
width: "56px",
|
|
3756
|
-
height: "56px",
|
|
3757
|
-
borderRadius: "9999px",
|
|
3758
|
-
color:
|
|
3759
|
-
boxShadow:
|
|
5357
|
+
width: "var(--sc-launcher-size, 56px)",
|
|
5358
|
+
height: "var(--sc-launcher-size, 56px)",
|
|
5359
|
+
borderRadius: "var(--sc-launcher-border-radius, 9999px)",
|
|
5360
|
+
color: "var(--sc-launcher-color)",
|
|
5361
|
+
boxShadow: "var(--sc-launcher-shadow)",
|
|
3760
5362
|
transition: dragRef.current ? "none" : "transform 0.2s ease, opacity 0.3s ease, background-color 0.2s ease",
|
|
3761
5363
|
outline: "none",
|
|
3762
5364
|
padding: 0,
|
|
3763
5365
|
border: "none",
|
|
3764
|
-
backgroundColor:
|
|
3765
|
-
cursor: ((
|
|
5366
|
+
backgroundColor: "var(--sc-launcher-background)",
|
|
5367
|
+
cursor: ((_d = dragRef.current) == null ? void 0 : _d.dragged) ? "grabbing" : "pointer",
|
|
3766
5368
|
touchAction: "none"
|
|
3767
5369
|
},
|
|
3768
5370
|
onPointerDown: onLauncherPointerDown,
|
|
3769
5371
|
onPointerMove: onLauncherPointerMove,
|
|
3770
5372
|
onPointerUp: onLauncherPointerUp,
|
|
3771
5373
|
onMouseEnter: (e) => {
|
|
3772
|
-
var _a3;
|
|
5374
|
+
var _a3, _b2;
|
|
3773
5375
|
if (!((_a3 = dragRef.current) == null ? void 0 : _a3.dragged)) {
|
|
3774
|
-
e.currentTarget.style.backgroundColor =
|
|
5376
|
+
e.currentTarget.style.backgroundColor = (_b2 = config.launcher.backgroundHover) != null ? _b2 : "var(--sc-launcher-background-hover)";
|
|
3775
5377
|
}
|
|
3776
5378
|
},
|
|
3777
5379
|
onMouseLeave: (e) => {
|
|
3778
|
-
var _a3;
|
|
5380
|
+
var _a3, _b2;
|
|
3779
5381
|
if (!((_a3 = dragRef.current) == null ? void 0 : _a3.dragged)) {
|
|
3780
|
-
e.currentTarget.style.backgroundColor =
|
|
5382
|
+
e.currentTarget.style.backgroundColor = (_b2 = config.launcher.background) != null ? _b2 : "var(--sc-launcher-background)";
|
|
3781
5383
|
}
|
|
3782
5384
|
},
|
|
3783
5385
|
children: [
|
|
3784
|
-
/* @__PURE__ */
|
|
5386
|
+
isOpen ? /* @__PURE__ */ jsxs3(
|
|
3785
5387
|
"svg",
|
|
3786
5388
|
{
|
|
3787
5389
|
width: "24",
|
|
@@ -3795,20 +5397,49 @@ function ShadowCanvasOverlay({
|
|
|
3795
5397
|
"aria-hidden": "true",
|
|
3796
5398
|
focusable: "false",
|
|
3797
5399
|
style: { transition: "transform 200ms ease" },
|
|
3798
|
-
children:
|
|
3799
|
-
/* @__PURE__ */
|
|
3800
|
-
/* @__PURE__ */
|
|
3801
|
-
]
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
5400
|
+
children: [
|
|
5401
|
+
/* @__PURE__ */ jsx7("path", { d: "M18 6L6 18" }),
|
|
5402
|
+
/* @__PURE__ */ jsx7("path", { d: "M6 6l12 12" })
|
|
5403
|
+
]
|
|
5404
|
+
}
|
|
5405
|
+
) : launcherIcon ? /* @__PURE__ */ jsx7(
|
|
5406
|
+
"img",
|
|
5407
|
+
{
|
|
5408
|
+
src: launcherIcon,
|
|
5409
|
+
alt: "",
|
|
5410
|
+
"aria-hidden": "true",
|
|
5411
|
+
style: {
|
|
5412
|
+
width: "60%",
|
|
5413
|
+
height: "60%",
|
|
5414
|
+
objectFit: "contain",
|
|
5415
|
+
pointerEvents: "none"
|
|
5416
|
+
}
|
|
5417
|
+
}
|
|
5418
|
+
) : /* @__PURE__ */ jsxs3(
|
|
5419
|
+
"svg",
|
|
5420
|
+
{
|
|
5421
|
+
width: "24",
|
|
5422
|
+
height: "24",
|
|
5423
|
+
viewBox: "0 0 24 24",
|
|
5424
|
+
fill: "none",
|
|
5425
|
+
stroke: "currentColor",
|
|
5426
|
+
strokeWidth: "2",
|
|
5427
|
+
strokeLinecap: "round",
|
|
5428
|
+
strokeLinejoin: "round",
|
|
5429
|
+
"aria-hidden": "true",
|
|
5430
|
+
focusable: "false",
|
|
5431
|
+
style: { transition: "transform 200ms ease" },
|
|
5432
|
+
children: [
|
|
5433
|
+
/* @__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" }),
|
|
5434
|
+
/* @__PURE__ */ jsx7("path", { d: "M5 3v4" }),
|
|
5435
|
+
/* @__PURE__ */ jsx7("path", { d: "M3 5h4" }),
|
|
5436
|
+
/* @__PURE__ */ jsx7("path", { d: "M19 17v4" }),
|
|
5437
|
+
/* @__PURE__ */ jsx7("path", { d: "M17 19h4" })
|
|
5438
|
+
]
|
|
3808
5439
|
}
|
|
3809
5440
|
),
|
|
3810
5441
|
!isOpen && notifications.length > 0 && /* @__PURE__ */ jsxs3("div", { style: { position: "absolute", top: -2, right: -2, pointerEvents: "none" }, children: [
|
|
3811
|
-
/* @__PURE__ */
|
|
5442
|
+
/* @__PURE__ */ jsx7(
|
|
3812
5443
|
"span",
|
|
3813
5444
|
{
|
|
3814
5445
|
className: "syntro-badge-ping",
|
|
@@ -3816,11 +5447,11 @@ function ShadowCanvasOverlay({
|
|
|
3816
5447
|
position: "absolute",
|
|
3817
5448
|
inset: 0,
|
|
3818
5449
|
borderRadius: "9999px",
|
|
3819
|
-
background:
|
|
5450
|
+
background: `${config.colorPrimaryHover}66`
|
|
3820
5451
|
}
|
|
3821
5452
|
}
|
|
3822
5453
|
),
|
|
3823
|
-
/* @__PURE__ */
|
|
5454
|
+
/* @__PURE__ */ jsx7(
|
|
3824
5455
|
"span",
|
|
3825
5456
|
{
|
|
3826
5457
|
className: "syntro-badge-glow",
|
|
@@ -3831,7 +5462,7 @@ function ShadowCanvasOverlay({
|
|
|
3831
5462
|
}
|
|
3832
5463
|
}
|
|
3833
5464
|
),
|
|
3834
|
-
/* @__PURE__ */
|
|
5465
|
+
/* @__PURE__ */ jsx7(
|
|
3835
5466
|
"span",
|
|
3836
5467
|
{
|
|
3837
5468
|
className: "syntro-badge-bounce",
|
|
@@ -3843,8 +5474,8 @@ function ShadowCanvasOverlay({
|
|
|
3843
5474
|
width: 20,
|
|
3844
5475
|
height: 20,
|
|
3845
5476
|
borderRadius: "9999px",
|
|
3846
|
-
background:
|
|
3847
|
-
color:
|
|
5477
|
+
background: config.colorPrimaryHover,
|
|
5478
|
+
color: "#ffffff",
|
|
3848
5479
|
fontSize: 11,
|
|
3849
5480
|
fontWeight: 700
|
|
3850
5481
|
},
|
|
@@ -3860,33 +5491,46 @@ function ShadowCanvasOverlay({
|
|
|
3860
5491
|
),
|
|
3861
5492
|
portalRoot
|
|
3862
5493
|
),
|
|
3863
|
-
|
|
5494
|
+
createPortal(content, portalRoot)
|
|
3864
5495
|
] });
|
|
3865
5496
|
}
|
|
3866
5497
|
|
|
3867
5498
|
// src/hooks/useShadowCanvasConfig.ts
|
|
3868
|
-
import { useCallback as
|
|
5499
|
+
import { useCallback as useCallback5, useEffect as useEffect8, useMemo as useMemo6, useRef as useRef6, useState as useState6 } from "react";
|
|
3869
5500
|
var sortTiles = (tiles) => [...tiles].sort((a, b) => {
|
|
3870
5501
|
var _a2, _b;
|
|
3871
5502
|
return ((_a2 = b.priority) != null ? _a2 : 0) - ((_b = a.priority) != null ? _b : 0);
|
|
3872
5503
|
});
|
|
3873
5504
|
function useShadowCanvasConfig({
|
|
3874
5505
|
fetcher,
|
|
3875
|
-
pollIntervalMs = 3e4,
|
|
3876
5506
|
experiments,
|
|
3877
5507
|
runtime: runtime3,
|
|
3878
|
-
|
|
5508
|
+
pageUrl,
|
|
5509
|
+
pollIntervalMs
|
|
3879
5510
|
}) {
|
|
3880
5511
|
const [state, setState] = useState6({
|
|
3881
5512
|
tiles: [],
|
|
3882
5513
|
actions: [],
|
|
3883
5514
|
isLoading: true
|
|
3884
5515
|
});
|
|
3885
|
-
const
|
|
5516
|
+
const prevActionsJsonRef = useRef6("[]");
|
|
5517
|
+
const rawConfigRef = useRef6(null);
|
|
5518
|
+
const refilter = useCallback5(async () => {
|
|
5519
|
+
const raw = rawConfigRef.current;
|
|
5520
|
+
if (!raw || !runtime3) return;
|
|
5521
|
+
let tiles = raw.tiles || [];
|
|
5522
|
+
tiles = await runtime3.filterTiles(tiles);
|
|
5523
|
+
if (experiments) {
|
|
5524
|
+
tiles = tiles.filter((tile) => experiments.shouldRenderRectangle(tile));
|
|
5525
|
+
}
|
|
5526
|
+
setState((prev) => ({ ...prev, tiles: sortTiles(tiles) }));
|
|
5527
|
+
}, [runtime3, experiments]);
|
|
5528
|
+
const load = useCallback5(async () => {
|
|
3886
5529
|
try {
|
|
3887
5530
|
setState((prev) => ({ ...prev, isLoading: true, error: void 0 }));
|
|
3888
5531
|
const response = await fetcher();
|
|
3889
5532
|
debug("SmartCanvas Config", "Raw config response", response);
|
|
5533
|
+
rawConfigRef.current = response;
|
|
3890
5534
|
let tiles = response.tiles || [];
|
|
3891
5535
|
if (runtime3) {
|
|
3892
5536
|
tiles = await runtime3.filterTiles(tiles);
|
|
@@ -3897,16 +5541,22 @@ function useShadowCanvasConfig({
|
|
|
3897
5541
|
tiles = tiles.filter((tile) => experiments.shouldRenderRectangle(tile));
|
|
3898
5542
|
}
|
|
3899
5543
|
debug("SmartCanvas Config", `Tile count after filtering: ${tiles.length}`);
|
|
3900
|
-
|
|
5544
|
+
const newActions = response.actions || [];
|
|
5545
|
+
const newActionsJson = JSON.stringify(newActions);
|
|
5546
|
+
const actionsChanged = newActionsJson !== prevActionsJsonRef.current;
|
|
5547
|
+
if (actionsChanged) {
|
|
5548
|
+
prevActionsJsonRef.current = newActionsJson;
|
|
5549
|
+
}
|
|
5550
|
+
setState((prev) => ({
|
|
3901
5551
|
tiles: sortTiles(tiles),
|
|
3902
|
-
actions:
|
|
5552
|
+
actions: actionsChanged ? newActions : prev.actions,
|
|
3903
5553
|
isLoading: false,
|
|
3904
5554
|
fetchedAt: response.fetchedAt,
|
|
3905
5555
|
canvasTitle: response.canvasTitle,
|
|
3906
5556
|
configVersion: response.configVersion,
|
|
3907
5557
|
theme: response.theme,
|
|
3908
5558
|
launcher: response.launcher
|
|
3909
|
-
});
|
|
5559
|
+
}));
|
|
3910
5560
|
} catch (err) {
|
|
3911
5561
|
const message = err instanceof Error ? err.message : "Unknown error";
|
|
3912
5562
|
console.error("[SmartCanvas Config] Failed to fetch/filter config:", message, err);
|
|
@@ -3917,18 +5567,37 @@ function useShadowCanvasConfig({
|
|
|
3917
5567
|
}));
|
|
3918
5568
|
}
|
|
3919
5569
|
}, [experiments, fetcher, runtime3]);
|
|
3920
|
-
|
|
5570
|
+
useEffect8(() => {
|
|
3921
5571
|
load();
|
|
5572
|
+
if (experiments == null ? void 0 : experiments.onFeaturesChanged) {
|
|
5573
|
+
return experiments.onFeaturesChanged(() => load());
|
|
5574
|
+
}
|
|
5575
|
+
}, [load, experiments, pageUrl]);
|
|
5576
|
+
useEffect8(() => {
|
|
5577
|
+
if (!(runtime3 == null ? void 0 : runtime3.accumulator)) return;
|
|
5578
|
+
return runtime3.accumulator.subscribe(() => {
|
|
5579
|
+
refilter();
|
|
5580
|
+
});
|
|
5581
|
+
}, [runtime3, refilter]);
|
|
5582
|
+
useEffect8(() => {
|
|
5583
|
+
if (!(runtime3 == null ? void 0 : runtime3.context)) return;
|
|
5584
|
+
return runtime3.context.subscribe(() => {
|
|
5585
|
+
refilter();
|
|
5586
|
+
});
|
|
5587
|
+
}, [runtime3, refilter]);
|
|
5588
|
+
useEffect8(() => {
|
|
3922
5589
|
if (!pollIntervalMs) return;
|
|
3923
|
-
const id = setInterval(
|
|
5590
|
+
const id = setInterval(() => {
|
|
5591
|
+
load();
|
|
5592
|
+
}, pollIntervalMs);
|
|
3924
5593
|
return () => clearInterval(id);
|
|
3925
|
-
}, [load, pollIntervalMs
|
|
3926
|
-
return
|
|
5594
|
+
}, [load, pollIntervalMs]);
|
|
5595
|
+
return useMemo6(() => state, [state]);
|
|
3927
5596
|
}
|
|
3928
5597
|
|
|
3929
5598
|
// src/SmartCanvasApp.tsx
|
|
3930
|
-
import { useEffect as
|
|
3931
|
-
import { jsx as
|
|
5599
|
+
import { useEffect as useEffect9, useMemo as useMemo7, useRef as useRef7, useState as useState7 } from "react";
|
|
5600
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
3932
5601
|
function SmartCanvasApp({
|
|
3933
5602
|
controller,
|
|
3934
5603
|
fetcher,
|
|
@@ -3947,11 +5616,11 @@ function SmartCanvasApp({
|
|
|
3947
5616
|
footerSlot,
|
|
3948
5617
|
launcherLabel,
|
|
3949
5618
|
canvasHost,
|
|
3950
|
-
|
|
3951
|
-
|
|
5619
|
+
initialBatchHandle,
|
|
5620
|
+
workspaceTheme
|
|
3952
5621
|
}) {
|
|
3953
5622
|
if (runtime3) {
|
|
3954
|
-
return /* @__PURE__ */
|
|
5623
|
+
return /* @__PURE__ */ jsx8(RuntimeProvider, { runtime: runtime3, children: /* @__PURE__ */ jsx8(
|
|
3955
5624
|
SmartCanvasAppInner,
|
|
3956
5625
|
{
|
|
3957
5626
|
controller,
|
|
@@ -3971,12 +5640,12 @@ function SmartCanvasApp({
|
|
|
3971
5640
|
footerSlot,
|
|
3972
5641
|
launcherLabel,
|
|
3973
5642
|
canvasHost,
|
|
3974
|
-
|
|
3975
|
-
|
|
5643
|
+
initialBatchHandle,
|
|
5644
|
+
workspaceTheme
|
|
3976
5645
|
}
|
|
3977
5646
|
) });
|
|
3978
5647
|
}
|
|
3979
|
-
return /* @__PURE__ */
|
|
5648
|
+
return /* @__PURE__ */ jsx8(
|
|
3980
5649
|
SmartCanvasAppInner,
|
|
3981
5650
|
{
|
|
3982
5651
|
controller,
|
|
@@ -3995,8 +5664,8 @@ function SmartCanvasApp({
|
|
|
3995
5664
|
footerSlot,
|
|
3996
5665
|
launcherLabel,
|
|
3997
5666
|
canvasHost,
|
|
3998
|
-
|
|
3999
|
-
|
|
5667
|
+
initialBatchHandle,
|
|
5668
|
+
workspaceTheme
|
|
4000
5669
|
}
|
|
4001
5670
|
);
|
|
4002
5671
|
}
|
|
@@ -4018,38 +5687,40 @@ function SmartCanvasAppInner({
|
|
|
4018
5687
|
footerSlot,
|
|
4019
5688
|
launcherLabel,
|
|
4020
5689
|
canvasHost: _canvasHost,
|
|
4021
|
-
|
|
4022
|
-
|
|
5690
|
+
initialBatchHandle,
|
|
5691
|
+
workspaceTheme
|
|
4023
5692
|
}) {
|
|
4024
|
-
var _a2, _b, _c, _d, _e;
|
|
5693
|
+
var _a2, _b, _c, _d, _e, _f, _g;
|
|
4025
5694
|
const [open, setOpen] = useState7(controller.getState().open);
|
|
4026
5695
|
const pageContext = usePageContext();
|
|
4027
|
-
const [
|
|
4028
|
-
() => typeof window !== "undefined" ? window.location.
|
|
5696
|
+
const [localUrl, setLocalUrl] = useState7(
|
|
5697
|
+
() => typeof window !== "undefined" ? window.location.href : "/"
|
|
4029
5698
|
);
|
|
4030
|
-
const
|
|
4031
|
-
|
|
5699
|
+
const pageUrl = (_a2 = pageContext == null ? void 0 : pageContext.url) != null ? _a2 : localUrl;
|
|
5700
|
+
useEffect9(() => {
|
|
4032
5701
|
if (runtime3) return;
|
|
4033
5702
|
if (typeof window === "undefined") return;
|
|
4034
|
-
const
|
|
4035
|
-
window.addEventListener("popstate",
|
|
5703
|
+
const updateUrl = () => setLocalUrl(window.location.href);
|
|
5704
|
+
window.addEventListener("popstate", updateUrl);
|
|
5705
|
+
window.addEventListener("hashchange", updateUrl);
|
|
4036
5706
|
const originalPushState = history.pushState;
|
|
4037
5707
|
const originalReplaceState = history.replaceState;
|
|
4038
5708
|
history.pushState = function(...args) {
|
|
4039
5709
|
originalPushState.apply(this, args);
|
|
4040
|
-
queueMicrotask(
|
|
5710
|
+
queueMicrotask(updateUrl);
|
|
4041
5711
|
};
|
|
4042
5712
|
history.replaceState = function(...args) {
|
|
4043
5713
|
originalReplaceState.apply(this, args);
|
|
4044
|
-
queueMicrotask(
|
|
5714
|
+
queueMicrotask(updateUrl);
|
|
4045
5715
|
};
|
|
4046
5716
|
return () => {
|
|
4047
|
-
window.removeEventListener("popstate",
|
|
5717
|
+
window.removeEventListener("popstate", updateUrl);
|
|
5718
|
+
window.removeEventListener("hashchange", updateUrl);
|
|
4048
5719
|
history.pushState = originalPushState;
|
|
4049
5720
|
history.replaceState = originalReplaceState;
|
|
4050
5721
|
};
|
|
4051
5722
|
}, [runtime3]);
|
|
4052
|
-
const derivedFetcher =
|
|
5723
|
+
const derivedFetcher = useMemo7(() => {
|
|
4053
5724
|
if (fetcher) return fetcher;
|
|
4054
5725
|
return createCanvasConfigFetcher({
|
|
4055
5726
|
configUri,
|
|
@@ -4061,21 +5732,21 @@ function SmartCanvasAppInner({
|
|
|
4061
5732
|
}, [fetcher, configUri, experiments, configUriFeatureKey, configFeatureKey, fetchCredentials]);
|
|
4062
5733
|
const configState = useShadowCanvasConfig({
|
|
4063
5734
|
fetcher: derivedFetcher,
|
|
4064
|
-
pollIntervalMs,
|
|
4065
5735
|
experiments,
|
|
4066
5736
|
runtime: runtime3,
|
|
4067
|
-
|
|
5737
|
+
pageUrl
|
|
4068
5738
|
});
|
|
4069
5739
|
const hasContent = configState.tiles.length > 0 && !configState.error;
|
|
4070
|
-
|
|
4071
|
-
|
|
5740
|
+
useEffect9(() => controller.subscribe((state) => setOpen(state.open)), [controller]);
|
|
5741
|
+
useEffect9(() => {
|
|
4072
5742
|
if (!configState.isLoading && !hasContent && controller.getState().open) {
|
|
4073
5743
|
controller.setOpen(false);
|
|
4074
5744
|
}
|
|
4075
5745
|
}, [controller, hasContent, configState.isLoading]);
|
|
4076
|
-
const batchHandleRef =
|
|
4077
|
-
const adoptedInitialRef =
|
|
4078
|
-
|
|
5746
|
+
const batchHandleRef = useRef7(initialBatchHandle != null ? initialBatchHandle : null);
|
|
5747
|
+
const adoptedInitialRef = useRef7(!!initialBatchHandle);
|
|
5748
|
+
const runVersionRef = useRef7(0);
|
|
5749
|
+
useEffect9(() => {
|
|
4079
5750
|
if (!(runtime3 == null ? void 0 : runtime3.actions)) return;
|
|
4080
5751
|
if (adoptedInitialRef.current) {
|
|
4081
5752
|
if (configState.actions.length > 0) {
|
|
@@ -4083,10 +5754,10 @@ function SmartCanvasAppInner({
|
|
|
4083
5754
|
}
|
|
4084
5755
|
return;
|
|
4085
5756
|
}
|
|
4086
|
-
|
|
5757
|
+
const version = ++runVersionRef.current;
|
|
5758
|
+
const stale = () => version !== runVersionRef.current;
|
|
4087
5759
|
const run = async () => {
|
|
4088
5760
|
if (batchHandleRef.current) {
|
|
4089
|
-
console.log("[SmartCanvasApp] Reverting previous action batch before re-apply");
|
|
4090
5761
|
try {
|
|
4091
5762
|
await batchHandleRef.current.revertAll();
|
|
4092
5763
|
} catch (err) {
|
|
@@ -4094,92 +5765,76 @@ function SmartCanvasAppInner({
|
|
|
4094
5765
|
}
|
|
4095
5766
|
batchHandleRef.current = null;
|
|
4096
5767
|
}
|
|
4097
|
-
if (
|
|
5768
|
+
if (stale()) return;
|
|
4098
5769
|
if (configState.actions.length > 0) {
|
|
4099
|
-
console.log(
|
|
4100
|
-
`[SmartCanvasApp] Applying ${configState.actions.length} action(s):`,
|
|
4101
|
-
configState.actions.map(
|
|
4102
|
-
(a, i) => `[${i}] ${a.kind}${a.anchorId ? ` anchor="${a.anchorId}"` : ""}${a.label ? ` "${a.label}"` : ""}`
|
|
4103
|
-
).join(", ")
|
|
4104
|
-
);
|
|
4105
5770
|
try {
|
|
4106
5771
|
const handle = await runtime3.actions.applyBatch(configState.actions);
|
|
4107
|
-
if (
|
|
5772
|
+
if (stale()) {
|
|
4108
5773
|
await handle.revertAll();
|
|
4109
5774
|
} else {
|
|
4110
5775
|
batchHandleRef.current = handle;
|
|
4111
|
-
console.log("[SmartCanvasApp] Action batch applied successfully");
|
|
4112
5776
|
}
|
|
4113
5777
|
} catch (err) {
|
|
4114
|
-
if (!
|
|
4115
|
-
console.error(
|
|
4116
|
-
"[SmartCanvasApp] Failed to apply actions:",
|
|
4117
|
-
err,
|
|
4118
|
-
"\nActions that failed:",
|
|
4119
|
-
JSON.stringify(configState.actions, null, 2)
|
|
4120
|
-
);
|
|
5778
|
+
if (!stale()) {
|
|
5779
|
+
console.error("[SmartCanvasApp] Failed to apply actions:", err);
|
|
4121
5780
|
}
|
|
4122
5781
|
}
|
|
4123
5782
|
}
|
|
4124
5783
|
};
|
|
4125
5784
|
run();
|
|
4126
5785
|
return () => {
|
|
4127
|
-
cancelled = true;
|
|
4128
5786
|
if (batchHandleRef.current) {
|
|
4129
|
-
console.log(
|
|
4130
|
-
"[SmartCanvasApp] Cleanup: reverting action batch (actions changed or unmount)"
|
|
4131
|
-
);
|
|
4132
5787
|
batchHandleRef.current.revertAll().catch((err) => {
|
|
4133
5788
|
console.error("[SmartCanvasApp] Failed to revert actions on cleanup:", err);
|
|
4134
5789
|
});
|
|
4135
5790
|
batchHandleRef.current = null;
|
|
4136
5791
|
}
|
|
4137
5792
|
};
|
|
4138
|
-
}, [runtime3, configState.actions]);
|
|
4139
|
-
|
|
5793
|
+
}, [runtime3, configState.actions, pageUrl]);
|
|
5794
|
+
useEffect9(() => {
|
|
4140
5795
|
if (!runtime3) return;
|
|
4141
5796
|
return runtime3.events.subscribe(
|
|
4142
5797
|
{ names: ["canvas.requestOpen"] },
|
|
4143
5798
|
() => controller.setOpen(true)
|
|
4144
5799
|
);
|
|
4145
5800
|
}, [runtime3, controller]);
|
|
4146
|
-
const
|
|
4147
|
-
|
|
4148
|
-
if (!configTheme) return theme;
|
|
4149
|
-
return {
|
|
4150
|
-
...configTheme,
|
|
4151
|
-
// position, mode, colors, borderRadius from config
|
|
4152
|
-
...theme
|
|
4153
|
-
// any direct overrides from theme prop
|
|
4154
|
-
};
|
|
4155
|
-
}, [configState.theme, theme]);
|
|
5801
|
+
const { shadowRoot } = useShadowRoot();
|
|
5802
|
+
const themeConfig = configState.theme;
|
|
4156
5803
|
if (!configState.isLoading && !hasContent) {
|
|
4157
5804
|
return null;
|
|
4158
5805
|
}
|
|
4159
|
-
return /* @__PURE__ */
|
|
4160
|
-
|
|
5806
|
+
return /* @__PURE__ */ jsx8(
|
|
5807
|
+
ThemeProvider,
|
|
4161
5808
|
{
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
5809
|
+
themeConfig,
|
|
5810
|
+
workspaceTheme,
|
|
5811
|
+
shadowRoot,
|
|
5812
|
+
children: /* @__PURE__ */ jsx8(
|
|
5813
|
+
ShadowCanvasOverlay,
|
|
5814
|
+
{
|
|
5815
|
+
tiles: configState.tiles,
|
|
5816
|
+
isLoading: configState.isLoading,
|
|
5817
|
+
error: configState.error,
|
|
5818
|
+
canvasTitle: configState.canvasTitle,
|
|
5819
|
+
telemetry,
|
|
5820
|
+
launcherLabel: launcherLabel != null ? launcherLabel : (_b = configState.launcher) == null ? void 0 : _b.label,
|
|
5821
|
+
launcherIcon: (_c = configState.launcher) == null ? void 0 : _c.icon,
|
|
5822
|
+
launcherAnimate: (_d = configState.launcher) == null ? void 0 : _d.animate,
|
|
5823
|
+
launcherAnimationStyle: (_e = configState.launcher) == null ? void 0 : _e.animationStyle,
|
|
5824
|
+
notificationCount: (_g = (_f = configState.launcher) == null ? void 0 : _f.notificationCount) != null ? _g : configState.tiles.length,
|
|
5825
|
+
footerSlot,
|
|
5826
|
+
isOpen: open,
|
|
5827
|
+
onToggle: () => controller.toggle(),
|
|
5828
|
+
displayMode: configState.displayMode
|
|
5829
|
+
}
|
|
5830
|
+
)
|
|
4176
5831
|
}
|
|
4177
5832
|
);
|
|
4178
5833
|
}
|
|
4179
5834
|
|
|
4180
5835
|
// src/SmartCanvasElement.tsx
|
|
4181
|
-
import { createRoot } from "react-dom/client";
|
|
4182
|
-
import { jsx as
|
|
5836
|
+
import { createRoot as createRoot2 } from "react-dom/client";
|
|
5837
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
4183
5838
|
var TAG_NAME = "smart-canvas";
|
|
4184
5839
|
var BASE_CSS = `
|
|
4185
5840
|
:host {
|
|
@@ -4219,7 +5874,7 @@ var SmartCanvasElement = class extends HTMLElement {
|
|
|
4219
5874
|
Object.assign(__privateGet(this, _overlayContainer).style, {
|
|
4220
5875
|
position: "fixed",
|
|
4221
5876
|
inset: "0",
|
|
4222
|
-
zIndex: "
|
|
5877
|
+
zIndex: "2147483645",
|
|
4223
5878
|
pointerEvents: "none"
|
|
4224
5879
|
});
|
|
4225
5880
|
__privateGet(this, _shadow).appendChild(__privateGet(this, _overlayContainer));
|
|
@@ -4277,16 +5932,16 @@ var SmartCanvasElement = class extends HTMLElement {
|
|
|
4277
5932
|
render() {
|
|
4278
5933
|
if (!this.isConnected || !__privateGet(this, _lastAppProps)) return;
|
|
4279
5934
|
if (!__privateGet(this, _root)) {
|
|
4280
|
-
__privateSet(this, _root,
|
|
5935
|
+
__privateSet(this, _root, createRoot2(__privateGet(this, _mount)));
|
|
4281
5936
|
}
|
|
4282
5937
|
__privateGet(this, _root).render(
|
|
4283
|
-
/* @__PURE__ */
|
|
5938
|
+
/* @__PURE__ */ jsx9(
|
|
4284
5939
|
ShadowRootProvider,
|
|
4285
5940
|
{
|
|
4286
5941
|
shadowRoot: __privateGet(this, _shadow),
|
|
4287
5942
|
portalRoot: __privateGet(this, _portalRoot),
|
|
4288
5943
|
overlayContainer: __privateGet(this, _overlayContainer),
|
|
4289
|
-
children: /* @__PURE__ */
|
|
5944
|
+
children: /* @__PURE__ */ jsx9(SmartCanvasApp, { ...__privateGet(this, _lastAppProps), controller: __privateGet(this, _controller), canvasHost: this })
|
|
4290
5945
|
}
|
|
4291
5946
|
)
|
|
4292
5947
|
);
|
|
@@ -4530,7 +6185,7 @@ function ensureOverlayRoot() {
|
|
|
4530
6185
|
Object.assign(overlayRootEl.style, {
|
|
4531
6186
|
position: "fixed",
|
|
4532
6187
|
inset: "0",
|
|
4533
|
-
zIndex: "
|
|
6188
|
+
zIndex: "2147483645",
|
|
4534
6189
|
pointerEvents: "none"
|
|
4535
6190
|
});
|
|
4536
6191
|
document.body.appendChild(overlayRootEl);
|
|
@@ -4542,20 +6197,23 @@ function injectBaseStyles(target) {
|
|
|
4542
6197
|
if (stylesInjected) return;
|
|
4543
6198
|
const css = `
|
|
4544
6199
|
:host {
|
|
4545
|
-
--syntro-surface: #0f1318;
|
|
4546
|
-
--syntro-fg: #cbd0d7;
|
|
4547
|
-
--syntro-accent: #b72e2a;
|
|
4548
|
-
--syntro-accent-hover: #d44844;
|
|
4549
|
-
--syntro-radius: 12px;
|
|
6200
|
+
--syntro-surface: var(--sc-overlay-background, #0f1318);
|
|
6201
|
+
--syntro-fg: var(--sc-overlay-text-color, #cbd0d7);
|
|
6202
|
+
--syntro-accent: var(--sc-color-primary, #b72e2a);
|
|
6203
|
+
--syntro-accent-hover: var(--sc-color-primary-hover, #d44844);
|
|
6204
|
+
--syntro-radius: var(--sc-border-radius, 12px);
|
|
4550
6205
|
--syntro-shadow: 0 25px 50px -12px rgba(16,24,40,0.25);
|
|
4551
|
-
--syntro-ring: #d44844;
|
|
4552
|
-
--syntro-border: #2b333f;
|
|
6206
|
+
--syntro-ring: var(--sc-overlay-highlight-ring, #d44844);
|
|
6207
|
+
--syntro-border: var(--sc-overlay-border, #2b333f);
|
|
4553
6208
|
--syntro-tooltip-bg: var(--syntro-surface);
|
|
4554
6209
|
--syntro-tooltip-fg: var(--syntro-fg);
|
|
6210
|
+
--syntro-tooltip-title-color: var(--sc-overlay-title-color, var(--syntro-fg));
|
|
6211
|
+
--syntro-tooltip-arrow-bg: var(--sc-overlay-arrow-color, var(--syntro-tooltip-bg));
|
|
6212
|
+
--syntro-tooltip-arrow-size: var(--sc-overlay-arrow-size, 8px);
|
|
4555
6213
|
--syntro-tooltip-radius: var(--syntro-radius);
|
|
4556
6214
|
--syntro-tooltip-padding: 12px 16px;
|
|
4557
6215
|
--syntro-tooltip-shadow: var(--syntro-shadow);
|
|
4558
|
-
--syntro-spotlight-backdrop: rgba(0,0,0,0.70);
|
|
6216
|
+
--syntro-spotlight-backdrop: rgba(0,0,0, var(--sc-overlay-scrim-opacity, 0.70));
|
|
4559
6217
|
}
|
|
4560
6218
|
|
|
4561
6219
|
/* Tooltip container */
|
|
@@ -4578,14 +6236,13 @@ function injectBaseStyles(target) {
|
|
|
4578
6236
|
transform 200ms cubic-bezier(0.16, 1, 0.3, 1);
|
|
4579
6237
|
}
|
|
4580
6238
|
|
|
4581
|
-
/* Tooltip arrow */
|
|
6239
|
+
/* Tooltip arrow \u2014 triangle via clip-path (square box so rotation is symmetric) */
|
|
4582
6240
|
.syntro-tooltip-arrow {
|
|
4583
6241
|
position: absolute;
|
|
4584
|
-
width:
|
|
4585
|
-
height:
|
|
4586
|
-
background:
|
|
4587
|
-
|
|
4588
|
-
z-index: -1;
|
|
6242
|
+
width: var(--syntro-tooltip-arrow-size);
|
|
6243
|
+
height: var(--syntro-tooltip-arrow-size);
|
|
6244
|
+
background: var(--syntro-tooltip-arrow-bg);
|
|
6245
|
+
clip-path: polygon(0 0, 100% 0, 50% 100%);
|
|
4589
6246
|
}
|
|
4590
6247
|
|
|
4591
6248
|
/* Tooltip content */
|
|
@@ -4593,6 +6250,7 @@ function injectBaseStyles(target) {
|
|
|
4593
6250
|
font-weight: 600;
|
|
4594
6251
|
font-size: 15px;
|
|
4595
6252
|
margin-bottom: 6px;
|
|
6253
|
+
color: var(--syntro-tooltip-title-color);
|
|
4596
6254
|
}
|
|
4597
6255
|
|
|
4598
6256
|
.syntro-tt-body {
|
|
@@ -4821,7 +6479,6 @@ var createSmartCanvas = async (config = {}) => {
|
|
|
4821
6479
|
let currentConfig = null;
|
|
4822
6480
|
let currentFetcher = null;
|
|
4823
6481
|
let currentBatchHandle = null;
|
|
4824
|
-
let isEnabled = true;
|
|
4825
6482
|
const { runtime: runtime3 } = config;
|
|
4826
6483
|
async function applyActions(actions) {
|
|
4827
6484
|
if (!(runtime3 == null ? void 0 : runtime3.actions) || actions.length === 0) {
|
|
@@ -4848,13 +6505,13 @@ var createSmartCanvas = async (config = {}) => {
|
|
|
4848
6505
|
"[SmartCanvas] Config fetched:",
|
|
4849
6506
|
`tiles=${(_b = (_a2 = canvasConfig.tiles) == null ? void 0 : _a2.length) != null ? _b : 0},`,
|
|
4850
6507
|
`actions=${(_d = (_c = canvasConfig.actions) == null ? void 0 : _c.length) != null ? _d : 0},`,
|
|
4851
|
-
`theme=${(_f = (_e = canvasConfig.theme) == null ? void 0 : _e.
|
|
6508
|
+
`theme=${(_f = (_e = canvasConfig.theme) == null ? void 0 : _e.mode) != null ? _f : "default"}`
|
|
4852
6509
|
);
|
|
4853
6510
|
if ((_g = canvasConfig.actions) == null ? void 0 : _g.length) {
|
|
4854
6511
|
console.log(
|
|
4855
6512
|
"[SmartCanvas] Actions to apply:",
|
|
4856
6513
|
canvasConfig.actions.map(
|
|
4857
|
-
(a, i) => `[${i}] ${a.kind}${a.anchorId ? ` anchor="${a.anchorId}"` : ""}${a.label ? ` "${a.label}"` : ""}`
|
|
6514
|
+
(a, i) => `[${i}] ${a.kind}${a.anchorId ? ` anchor="${typeof a.anchorId === "string" ? a.anchorId : a.anchorId.selector}"` : ""}${a.label ? ` "${a.label}"` : ""}`
|
|
4858
6515
|
).join(", ")
|
|
4859
6516
|
);
|
|
4860
6517
|
}
|
|
@@ -4863,7 +6520,7 @@ var createSmartCanvas = async (config = {}) => {
|
|
|
4863
6520
|
console.log("[SmartCanvas] Initial actions applied successfully");
|
|
4864
6521
|
}
|
|
4865
6522
|
if (canvasConfig.tiles && (runtime3 == null ? void 0 : runtime3.accumulator)) {
|
|
4866
|
-
registerConfigPredicates(canvasConfig.tiles, runtime3.accumulator);
|
|
6523
|
+
registerConfigPredicates(canvasConfig.tiles, runtime3.accumulator, canvasConfig.actions);
|
|
4867
6524
|
}
|
|
4868
6525
|
} catch (error2) {
|
|
4869
6526
|
console.error("[SmartCanvas] Error fetching/applying initial config:", error2);
|
|
@@ -4921,8 +6578,8 @@ var createSmartCanvas = async (config = {}) => {
|
|
|
4921
6578
|
configUri: config.configUri,
|
|
4922
6579
|
configUriFeatureKey: config.configUriFeatureKey,
|
|
4923
6580
|
fetchCredentials: config.fetchCredentials,
|
|
4924
|
-
|
|
4925
|
-
|
|
6581
|
+
initialBatchHandle: currentBatchHandle,
|
|
6582
|
+
workspaceTheme: config.workspaceTheme
|
|
4926
6583
|
};
|
|
4927
6584
|
host.mountReactApp(appProps);
|
|
4928
6585
|
if (config.defaultOpen) {
|
|
@@ -4953,30 +6610,7 @@ var createSmartCanvas = async (config = {}) => {
|
|
|
4953
6610
|
}
|
|
4954
6611
|
return currentConfig != null ? currentConfig : { tiles: [], actions: [], fetchedAt: "" };
|
|
4955
6612
|
},
|
|
4956
|
-
updateConfig: async (newConfig) => {
|
|
4957
|
-
var _a3, _b2, _c2, _d2;
|
|
4958
|
-
console.log(
|
|
4959
|
-
"[SmartCanvas] updateConfig:",
|
|
4960
|
-
`tiles=${(_b2 = (_a3 = newConfig.tiles) == null ? void 0 : _a3.length) != null ? _b2 : 0},`,
|
|
4961
|
-
`actions=${(_d2 = (_c2 = newConfig.actions) == null ? void 0 : _c2.length) != null ? _d2 : 0},`,
|
|
4962
|
-
`enabled=${isEnabled}`
|
|
4963
|
-
);
|
|
4964
|
-
currentConfig = newConfig;
|
|
4965
|
-
if (newConfig.tiles && (runtime3 == null ? void 0 : runtime3.accumulator)) {
|
|
4966
|
-
registerConfigPredicates(newConfig.tiles, runtime3.accumulator);
|
|
4967
|
-
}
|
|
4968
|
-
if (isEnabled) {
|
|
4969
|
-
try {
|
|
4970
|
-
await applyActions(newConfig.actions);
|
|
4971
|
-
console.log("[SmartCanvas] updateConfig actions applied successfully");
|
|
4972
|
-
} catch (error2) {
|
|
4973
|
-
console.error("[SmartCanvas] updateConfig failed to apply actions:", error2);
|
|
4974
|
-
}
|
|
4975
|
-
}
|
|
4976
|
-
host.setOverrideFetcher(() => Promise.resolve(newConfig));
|
|
4977
|
-
},
|
|
4978
6613
|
setEnabled: async (enabled) => {
|
|
4979
|
-
isEnabled = enabled;
|
|
4980
6614
|
if (enabled) {
|
|
4981
6615
|
if (currentConfig) {
|
|
4982
6616
|
await applyActions(currentConfig.actions);
|
|
@@ -4991,7 +6625,7 @@ var createSmartCanvas = async (config = {}) => {
|
|
|
4991
6625
|
if (runtime3 == null ? void 0 : runtime3.accumulator) {
|
|
4992
6626
|
newFetcher().then((config2) => {
|
|
4993
6627
|
if (config2 == null ? void 0 : config2.tiles) {
|
|
4994
|
-
registerConfigPredicates(config2.tiles, runtime3.accumulator);
|
|
6628
|
+
registerConfigPredicates(config2.tiles, runtime3.accumulator, config2.actions);
|
|
4995
6629
|
}
|
|
4996
6630
|
}).catch(() => {
|
|
4997
6631
|
});
|
|
@@ -5038,6 +6672,7 @@ var DEFAULT_EXPERIMENT_API_HOST = "https://experiment.syntrologie.com";
|
|
|
5038
6672
|
var GrowthBookAdapter = class {
|
|
5039
6673
|
constructor(options = {}) {
|
|
5040
6674
|
__publicField(this, "gb");
|
|
6675
|
+
__publicField(this, "featureListeners", /* @__PURE__ */ new Set());
|
|
5041
6676
|
var _a2, _b;
|
|
5042
6677
|
if (options.client) {
|
|
5043
6678
|
this.gb = options.client;
|
|
@@ -5093,6 +6728,20 @@ var GrowthBookAdapter = class {
|
|
|
5093
6728
|
shouldRenderRectangle(_tile) {
|
|
5094
6729
|
return true;
|
|
5095
6730
|
}
|
|
6731
|
+
onFeaturesChanged(callback) {
|
|
6732
|
+
this.featureListeners.add(callback);
|
|
6733
|
+
if (this.featureListeners.size === 1) {
|
|
6734
|
+
this.gb.setRenderer(() => {
|
|
6735
|
+
for (const cb of this.featureListeners) cb();
|
|
6736
|
+
});
|
|
6737
|
+
}
|
|
6738
|
+
return () => {
|
|
6739
|
+
this.featureListeners.delete(callback);
|
|
6740
|
+
if (this.featureListeners.size === 0) {
|
|
6741
|
+
this.gb.setRenderer(null);
|
|
6742
|
+
}
|
|
6743
|
+
};
|
|
6744
|
+
}
|
|
5096
6745
|
};
|
|
5097
6746
|
function createGrowthBookClient(options = {}) {
|
|
5098
6747
|
return new GrowthBookAdapter(options);
|
|
@@ -5510,315 +7159,67 @@ var executeSequence = async (action, context) => {
|
|
|
5510
7159
|
}
|
|
5511
7160
|
}
|
|
5512
7161
|
}
|
|
5513
|
-
};
|
|
5514
|
-
};
|
|
5515
|
-
var executeParallel = async (action, context) => {
|
|
5516
|
-
const handles = [];
|
|
5517
|
-
if (context.applyAction) {
|
|
5518
|
-
const promises = action.actions.map((childAction) => context.applyAction(childAction));
|
|
5519
|
-
if (action.waitFor === "any") {
|
|
5520
|
-
const firstHandle = await Promise.race(promises);
|
|
5521
|
-
handles.push(firstHandle);
|
|
5522
|
-
const remaining = await Promise.allSettled(promises);
|
|
5523
|
-
for (const result of remaining) {
|
|
5524
|
-
if (result.status === "fulfilled" && result.value !== firstHandle) {
|
|
5525
|
-
handles.push(result.value);
|
|
5526
|
-
}
|
|
5527
|
-
}
|
|
5528
|
-
} else {
|
|
5529
|
-
const allHandles = await Promise.all(promises);
|
|
5530
|
-
handles.push(...allHandles);
|
|
5531
|
-
}
|
|
5532
|
-
}
|
|
5533
|
-
return {
|
|
5534
|
-
cleanup: async () => {
|
|
5535
|
-
for (const handle of handles) {
|
|
5536
|
-
try {
|
|
5537
|
-
await handle.revert();
|
|
5538
|
-
} catch {
|
|
5539
|
-
}
|
|
5540
|
-
}
|
|
5541
|
-
}
|
|
5542
|
-
};
|
|
5543
|
-
};
|
|
5544
|
-
var executeWait = async (action, context) => {
|
|
5545
|
-
let unsubscribe;
|
|
5546
|
-
let timeoutId;
|
|
5547
|
-
let cancelled = false;
|
|
5548
|
-
const result = {
|
|
5549
|
-
cleanup: () => {
|
|
5550
|
-
cancelled = true;
|
|
5551
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
5552
|
-
if (unsubscribe) unsubscribe();
|
|
5553
|
-
}
|
|
5554
|
-
};
|
|
5555
|
-
if (action.event && context.subscribeEvent) {
|
|
5556
|
-
await new Promise((resolve) => {
|
|
5557
|
-
unsubscribe = context.subscribeEvent(action.event, () => {
|
|
5558
|
-
if (!cancelled) resolve();
|
|
5559
|
-
});
|
|
5560
|
-
if (action.durationMs !== void 0) {
|
|
5561
|
-
timeoutId = setTimeout(() => {
|
|
5562
|
-
if (!cancelled) resolve();
|
|
5563
|
-
}, action.durationMs);
|
|
5564
|
-
}
|
|
5565
|
-
});
|
|
5566
|
-
} else if (action.durationMs !== void 0) {
|
|
5567
|
-
await new Promise((resolve) => {
|
|
5568
|
-
timeoutId = setTimeout(() => {
|
|
5569
|
-
if (!cancelled) resolve();
|
|
5570
|
-
}, action.durationMs);
|
|
5571
|
-
});
|
|
5572
|
-
}
|
|
5573
|
-
return result;
|
|
5574
|
-
};
|
|
5575
|
-
|
|
5576
|
-
// src/actions/executors/tour.ts
|
|
5577
|
-
var ACTIVE_TOUR_KEY = "syntro_active_tour";
|
|
5578
|
-
var activeTours = /* @__PURE__ */ new Map();
|
|
5579
|
-
function getTourState(tourId) {
|
|
5580
|
-
try {
|
|
5581
|
-
const data = localStorage.getItem(ACTIVE_TOUR_KEY);
|
|
5582
|
-
if (!data) return null;
|
|
5583
|
-
const state = JSON.parse(data);
|
|
5584
|
-
if (state.tourId !== tourId) return null;
|
|
5585
|
-
return state;
|
|
5586
|
-
} catch {
|
|
5587
|
-
return null;
|
|
5588
|
-
}
|
|
5589
|
-
}
|
|
5590
|
-
function saveTourState(state) {
|
|
5591
|
-
try {
|
|
5592
|
-
localStorage.setItem(ACTIVE_TOUR_KEY, JSON.stringify(state));
|
|
5593
|
-
} catch {
|
|
5594
|
-
}
|
|
5595
|
-
}
|
|
5596
|
-
function clearTourState() {
|
|
5597
|
-
try {
|
|
5598
|
-
localStorage.removeItem(ACTIVE_TOUR_KEY);
|
|
5599
|
-
} catch {
|
|
5600
|
-
}
|
|
5601
|
-
}
|
|
5602
|
-
function getCurrentRoute() {
|
|
5603
|
-
return window.location.pathname;
|
|
5604
|
-
}
|
|
5605
|
-
function stepMatchesRoute(step) {
|
|
5606
|
-
if (!step.route) return true;
|
|
5607
|
-
const currentRoute = getCurrentRoute();
|
|
5608
|
-
if (step.route.includes("*")) {
|
|
5609
|
-
const pattern = new RegExp(`^${step.route.replace(/\*/g, ".*")}$`);
|
|
5610
|
-
return pattern.test(currentRoute);
|
|
5611
|
-
}
|
|
5612
|
-
return currentRoute === step.route;
|
|
5613
|
-
}
|
|
5614
|
-
var executeTour = async (action, context) => {
|
|
5615
|
-
const { tourId, steps, startStep, autoStart = true } = action;
|
|
5616
|
-
if (steps.length === 0) {
|
|
5617
|
-
throw new Error(`Tour "${tourId}" has no steps`);
|
|
5618
|
-
}
|
|
5619
|
-
if (activeTours.has(tourId)) {
|
|
5620
|
-
return {
|
|
5621
|
-
cleanup: async () => {
|
|
5622
|
-
const existing = activeTours.get(tourId);
|
|
5623
|
-
if (existing) {
|
|
5624
|
-
await existing.cleanup();
|
|
5625
|
-
}
|
|
5626
|
-
}
|
|
5627
|
-
};
|
|
5628
|
-
}
|
|
5629
|
-
if (!context.applyAction) {
|
|
5630
|
-
throw new Error("Tour executor requires applyAction in context");
|
|
5631
|
-
}
|
|
5632
|
-
let state = getTourState(tourId);
|
|
5633
|
-
const isResumingTour = !!state;
|
|
5634
|
-
if (!isResumingTour && !autoStart) {
|
|
5635
|
-
return {
|
|
5636
|
-
cleanup: () => {
|
|
5637
|
-
}
|
|
5638
|
-
};
|
|
5639
|
-
}
|
|
5640
|
-
if (!state) {
|
|
5641
|
-
state = {
|
|
5642
|
-
tourId,
|
|
5643
|
-
currentStepId: startStep || steps[0].id,
|
|
5644
|
-
startedAt: Date.now()
|
|
5645
|
-
};
|
|
5646
|
-
saveTourState(state);
|
|
5647
|
-
}
|
|
5648
|
-
let currentStepIndex = steps.findIndex((s) => s.id === state.currentStepId);
|
|
5649
|
-
if (currentStepIndex === -1) {
|
|
5650
|
-
const initialStepId = startStep || steps[0].id;
|
|
5651
|
-
currentStepIndex = steps.findIndex((s) => s.id === initialStepId);
|
|
5652
|
-
if (currentStepIndex === -1) currentStepIndex = 0;
|
|
5653
|
-
state.currentStepId = steps[currentStepIndex].id;
|
|
5654
|
-
saveTourState(state);
|
|
5655
|
-
}
|
|
5656
|
-
const currentStep = steps[currentStepIndex];
|
|
5657
|
-
if (!stepMatchesRoute(currentStep)) {
|
|
5658
|
-
context.publishEvent("tour.waiting_for_route", {
|
|
5659
|
-
tourId,
|
|
5660
|
-
stepId: currentStep.id,
|
|
5661
|
-
expectedRoute: currentStep.route,
|
|
5662
|
-
currentRoute: getCurrentRoute()
|
|
5663
|
-
});
|
|
5664
|
-
return {
|
|
5665
|
-
cleanup: () => {
|
|
5666
|
-
}
|
|
5667
|
-
};
|
|
5668
|
-
}
|
|
5669
|
-
let isDestroyed = false;
|
|
5670
|
-
let currentActionHandle = null;
|
|
5671
|
-
let eventUnsubscribe = null;
|
|
5672
|
-
let routeWatcher = null;
|
|
5673
|
-
const cleanupCurrentStep = async () => {
|
|
5674
|
-
if (eventUnsubscribe) {
|
|
5675
|
-
eventUnsubscribe();
|
|
5676
|
-
eventUnsubscribe = null;
|
|
5677
|
-
}
|
|
5678
|
-
if (currentActionHandle == null ? void 0 : currentActionHandle.isApplied()) {
|
|
5679
|
-
await currentActionHandle.revert();
|
|
5680
|
-
currentActionHandle = null;
|
|
5681
|
-
}
|
|
5682
|
-
};
|
|
5683
|
-
const advanceToStep = async (nextStepId) => {
|
|
5684
|
-
if (isDestroyed) return;
|
|
5685
|
-
await cleanupCurrentStep();
|
|
5686
|
-
if (nextStepId === "end") {
|
|
5687
|
-
clearTourState();
|
|
5688
|
-
context.publishEvent("tour.completed", {
|
|
5689
|
-
tourId,
|
|
5690
|
-
totalSteps: steps.length
|
|
5691
|
-
});
|
|
5692
|
-
isDestroyed = true;
|
|
5693
|
-
return;
|
|
5694
|
-
}
|
|
5695
|
-
const nextStep = steps.find((s) => s.id === nextStepId);
|
|
5696
|
-
if (!nextStep) {
|
|
5697
|
-
console.error(`[Tour] Step "${nextStepId}" not found`);
|
|
5698
|
-
return;
|
|
5699
|
-
}
|
|
5700
|
-
state.currentStepId = nextStepId;
|
|
5701
|
-
saveTourState(state);
|
|
5702
|
-
context.publishEvent("tour.step_changed", {
|
|
5703
|
-
tourId,
|
|
5704
|
-
previousStepId: currentStep.id,
|
|
5705
|
-
nextStepId
|
|
5706
|
-
});
|
|
5707
|
-
if (nextStep.route && nextStep.route !== getCurrentRoute()) {
|
|
5708
|
-
context.publishEvent("tour.awaiting_navigation", {
|
|
5709
|
-
tourId,
|
|
5710
|
-
stepId: nextStepId,
|
|
5711
|
-
targetRoute: nextStep.route
|
|
5712
|
-
});
|
|
5713
|
-
return;
|
|
5714
|
-
}
|
|
5715
|
-
await executeStep(nextStep);
|
|
5716
|
-
};
|
|
5717
|
-
const executeStep = async (step) => {
|
|
5718
|
-
if (isDestroyed) return;
|
|
5719
|
-
context.publishEvent("tour.step_started", {
|
|
5720
|
-
tourId,
|
|
5721
|
-
stepId: step.id,
|
|
5722
|
-
stepIndex: steps.findIndex((s) => s.id === step.id),
|
|
5723
|
-
totalSteps: steps.length
|
|
5724
|
-
});
|
|
5725
|
-
try {
|
|
5726
|
-
currentActionHandle = await context.applyAction(step.action);
|
|
5727
|
-
} catch (error2) {
|
|
5728
|
-
console.error(`[Tour] Failed to execute step "${step.id}":`, error2);
|
|
5729
|
-
context.publishEvent("tour.step_failed", {
|
|
5730
|
-
tourId,
|
|
5731
|
-
stepId: step.id,
|
|
5732
|
-
error: String(error2)
|
|
5733
|
-
});
|
|
5734
|
-
return;
|
|
5735
|
-
}
|
|
5736
|
-
if (step.onAction && context.subscribeEvent) {
|
|
5737
|
-
eventUnsubscribe = context.subscribeEvent("action.modal_cta_clicked", (props) => {
|
|
5738
|
-
const actionId = props == null ? void 0 : props.actionId;
|
|
5739
|
-
if (actionId && step.onAction) {
|
|
5740
|
-
const nextStepId = step.onAction[actionId];
|
|
5741
|
-
if (nextStepId) {
|
|
5742
|
-
advanceToStep(nextStepId);
|
|
5743
|
-
}
|
|
7162
|
+
};
|
|
7163
|
+
};
|
|
7164
|
+
var executeParallel = async (action, context) => {
|
|
7165
|
+
const handles = [];
|
|
7166
|
+
if (context.applyAction) {
|
|
7167
|
+
const promises = action.actions.map((childAction) => context.applyAction(childAction));
|
|
7168
|
+
if (action.waitFor === "any") {
|
|
7169
|
+
const firstHandle = await Promise.race(promises);
|
|
7170
|
+
handles.push(firstHandle);
|
|
7171
|
+
const remaining = await Promise.allSettled(promises);
|
|
7172
|
+
for (const result of remaining) {
|
|
7173
|
+
if (result.status === "fulfilled" && result.value !== firstHandle) {
|
|
7174
|
+
handles.push(result.value);
|
|
5744
7175
|
}
|
|
5745
|
-
}
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
7176
|
+
}
|
|
7177
|
+
} else {
|
|
7178
|
+
const allHandles = await Promise.all(promises);
|
|
7179
|
+
handles.push(...allHandles);
|
|
7180
|
+
}
|
|
7181
|
+
}
|
|
7182
|
+
return {
|
|
7183
|
+
cleanup: async () => {
|
|
7184
|
+
for (const handle of handles) {
|
|
7185
|
+
try {
|
|
7186
|
+
await handle.revert();
|
|
7187
|
+
} catch {
|
|
5753
7188
|
}
|
|
5754
|
-
}
|
|
5755
|
-
const originalUnsubscribe = eventUnsubscribe;
|
|
5756
|
-
eventUnsubscribe = () => {
|
|
5757
|
-
originalUnsubscribe();
|
|
5758
|
-
tooltipUnsubscribe();
|
|
5759
|
-
};
|
|
7189
|
+
}
|
|
5760
7190
|
}
|
|
5761
7191
|
};
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
}
|
|
5773
|
-
};
|
|
5774
|
-
if (context.subscribeNavigation) {
|
|
5775
|
-
return context.subscribeNavigation(() => checkRoute());
|
|
7192
|
+
};
|
|
7193
|
+
var executeWait = async (action, context) => {
|
|
7194
|
+
let unsubscribe;
|
|
7195
|
+
let timeoutId;
|
|
7196
|
+
let cancelled = false;
|
|
7197
|
+
const result = {
|
|
7198
|
+
cleanup: () => {
|
|
7199
|
+
cancelled = true;
|
|
7200
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
7201
|
+
if (unsubscribe) unsubscribe();
|
|
5776
7202
|
}
|
|
5777
|
-
window.addEventListener("popstate", checkRoute);
|
|
5778
|
-
const origPushState = history.pushState.bind(history);
|
|
5779
|
-
const origReplaceState = history.replaceState.bind(history);
|
|
5780
|
-
history.pushState = (...args) => {
|
|
5781
|
-
origPushState(...args);
|
|
5782
|
-
queueMicrotask(checkRoute);
|
|
5783
|
-
};
|
|
5784
|
-
history.replaceState = (...args) => {
|
|
5785
|
-
origReplaceState(...args);
|
|
5786
|
-
queueMicrotask(checkRoute);
|
|
5787
|
-
};
|
|
5788
|
-
return () => {
|
|
5789
|
-
window.removeEventListener("popstate", checkRoute);
|
|
5790
|
-
history.pushState = origPushState;
|
|
5791
|
-
history.replaceState = origReplaceState;
|
|
5792
|
-
};
|
|
5793
7203
|
};
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
7204
|
+
if (action.event && context.subscribeEvent) {
|
|
7205
|
+
await new Promise((resolve) => {
|
|
7206
|
+
unsubscribe = context.subscribeEvent(action.event, () => {
|
|
7207
|
+
if (!cancelled) resolve();
|
|
7208
|
+
});
|
|
7209
|
+
if (action.durationMs !== void 0) {
|
|
7210
|
+
timeoutId = setTimeout(() => {
|
|
7211
|
+
if (!cancelled) resolve();
|
|
7212
|
+
}, action.durationMs);
|
|
7213
|
+
}
|
|
5800
7214
|
});
|
|
5801
|
-
} else {
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
7215
|
+
} else if (action.durationMs !== void 0) {
|
|
7216
|
+
await new Promise((resolve) => {
|
|
7217
|
+
timeoutId = setTimeout(() => {
|
|
7218
|
+
if (!cancelled) resolve();
|
|
7219
|
+
}, action.durationMs);
|
|
5805
7220
|
});
|
|
5806
7221
|
}
|
|
5807
|
-
|
|
5808
|
-
const cleanup = async () => {
|
|
5809
|
-
isDestroyed = true;
|
|
5810
|
-
activeTours.delete(tourId);
|
|
5811
|
-
await cleanupCurrentStep();
|
|
5812
|
-
if (routeWatcher) {
|
|
5813
|
-
routeWatcher();
|
|
5814
|
-
}
|
|
5815
|
-
context.publishEvent("tour.paused", {
|
|
5816
|
-
tourId,
|
|
5817
|
-
stepId: state.currentStepId
|
|
5818
|
-
});
|
|
5819
|
-
};
|
|
5820
|
-
activeTours.set(tourId, { cleanup });
|
|
5821
|
-
return { cleanup };
|
|
7222
|
+
return result;
|
|
5822
7223
|
};
|
|
5823
7224
|
|
|
5824
7225
|
// src/actions/executors/index.ts
|
|
@@ -5842,7 +7243,6 @@ var ExecutorRegistry = class {
|
|
|
5842
7243
|
this.registerCore("core:sequence", executeSequence);
|
|
5843
7244
|
this.registerCore("core:parallel", executeParallel);
|
|
5844
7245
|
this.registerCore("core:wait", executeWait);
|
|
5845
|
-
this.registerCore("core:tour", executeTour);
|
|
5846
7246
|
}
|
|
5847
7247
|
/**
|
|
5848
7248
|
* Register a core executor (synchronous, built-in, cannot be overridden).
|
|
@@ -6121,18 +7521,46 @@ function validateAction(action) {
|
|
|
6121
7521
|
};
|
|
6122
7522
|
}
|
|
6123
7523
|
function validateAnchorAction(action, errors, warnings) {
|
|
6124
|
-
|
|
7524
|
+
const anchorId = action.anchorId;
|
|
7525
|
+
if (!anchorId || typeof anchorId !== "object") {
|
|
6125
7526
|
errors.push({
|
|
6126
7527
|
code: "MISSING_ANCHOR_ID",
|
|
6127
|
-
message: "Action requires an 'anchorId'
|
|
7528
|
+
message: "Action requires an 'anchorId' object with a 'selector' string",
|
|
6128
7529
|
field: "anchorId"
|
|
6129
7530
|
});
|
|
6130
|
-
|
|
7531
|
+
return;
|
|
7532
|
+
}
|
|
7533
|
+
if (!anchorId.selector || typeof anchorId.selector !== "string") {
|
|
7534
|
+
errors.push({
|
|
7535
|
+
code: "MISSING_ANCHOR_SELECTOR",
|
|
7536
|
+
message: "anchorId requires a 'selector' string",
|
|
7537
|
+
field: "anchorId.selector"
|
|
7538
|
+
});
|
|
7539
|
+
} else if (anchorId.selector.length > 200) {
|
|
6131
7540
|
warnings.push({
|
|
6132
7541
|
code: "LONG_ANCHOR_ID",
|
|
6133
|
-
message: "Anchor
|
|
6134
|
-
suggestion: "Consider using a shorter, more descriptive
|
|
7542
|
+
message: "Anchor selector is unusually long",
|
|
7543
|
+
suggestion: "Consider using a shorter, more descriptive selector"
|
|
7544
|
+
});
|
|
7545
|
+
}
|
|
7546
|
+
if (anchorId.route === void 0 || anchorId.route === null) {
|
|
7547
|
+
errors.push({
|
|
7548
|
+
code: "MISSING_ANCHOR_ROUTE",
|
|
7549
|
+
message: `anchorId requires a 'route' (string or array of strings). Use "**" for all routes.`,
|
|
7550
|
+
field: "anchorId.route"
|
|
6135
7551
|
});
|
|
7552
|
+
} else {
|
|
7553
|
+
const routes = Array.isArray(anchorId.route) ? anchorId.route : [anchorId.route];
|
|
7554
|
+
for (const route of routes) {
|
|
7555
|
+
if (typeof route !== "string") {
|
|
7556
|
+
errors.push({
|
|
7557
|
+
code: "INVALID_ANCHOR_ROUTE",
|
|
7558
|
+
message: "anchorId.route must be a string or array of strings",
|
|
7559
|
+
field: "anchorId.route"
|
|
7560
|
+
});
|
|
7561
|
+
break;
|
|
7562
|
+
}
|
|
7563
|
+
}
|
|
6136
7564
|
}
|
|
6137
7565
|
}
|
|
6138
7566
|
function validateBadgeAction(action, errors, warnings) {
|
|
@@ -6581,11 +8009,14 @@ function createActionEngine(options) {
|
|
|
6581
8009
|
eventBus,
|
|
6582
8010
|
surfaces,
|
|
6583
8011
|
anchorResolver,
|
|
8012
|
+
waitForAnchor,
|
|
6584
8013
|
adaptiveId,
|
|
6585
8014
|
executorRegistry: executorRegistry2 = executorRegistry,
|
|
6586
|
-
subscribeNavigation
|
|
8015
|
+
subscribeNavigation,
|
|
8016
|
+
runtime: runtime3
|
|
6587
8017
|
} = options;
|
|
6588
8018
|
const activeActions = /* @__PURE__ */ new Map();
|
|
8019
|
+
const conditionalUnsubs = /* @__PURE__ */ new Map();
|
|
6589
8020
|
function generateId() {
|
|
6590
8021
|
return `action-${++actionIdCounter}`;
|
|
6591
8022
|
}
|
|
@@ -6598,6 +8029,7 @@ function createActionEngine(options) {
|
|
|
6598
8029
|
return {
|
|
6599
8030
|
overlayRoot,
|
|
6600
8031
|
resolveAnchor: anchorResolver,
|
|
8032
|
+
waitForAnchor,
|
|
6601
8033
|
generateId,
|
|
6602
8034
|
publishEvent,
|
|
6603
8035
|
adaptiveId,
|
|
@@ -6648,6 +8080,67 @@ function createActionEngine(options) {
|
|
|
6648
8080
|
}
|
|
6649
8081
|
};
|
|
6650
8082
|
}
|
|
8083
|
+
async function executeAction(action, context) {
|
|
8084
|
+
if (action.kind === "core:mountWidget") {
|
|
8085
|
+
return executeMountWidget(action, context);
|
|
8086
|
+
}
|
|
8087
|
+
const executor = executorRegistry2.get(action.kind);
|
|
8088
|
+
if (!executor) {
|
|
8089
|
+
const registered = "list" in executorRegistry2 ? executorRegistry2.list() : "(list unavailable)";
|
|
8090
|
+
console.error(
|
|
8091
|
+
`[ActionEngine] No executor for kind="${action.kind}".`,
|
|
8092
|
+
`Registered: [${registered}]`
|
|
8093
|
+
);
|
|
8094
|
+
throw new Error(`No executor for action kind: ${action.kind}`);
|
|
8095
|
+
}
|
|
8096
|
+
return executor(action, context);
|
|
8097
|
+
}
|
|
8098
|
+
function subscribeForReeval(id, action, triggerWhen, handle) {
|
|
8099
|
+
if (!runtime3) return;
|
|
8100
|
+
const unsubs = [];
|
|
8101
|
+
const onReeval = async () => {
|
|
8102
|
+
const entry = activeActions.get(id);
|
|
8103
|
+
if (!entry) return;
|
|
8104
|
+
const result = runtime3.evaluateSync(triggerWhen);
|
|
8105
|
+
const shouldApply = result.value;
|
|
8106
|
+
if (entry.state === "applied" && !shouldApply) {
|
|
8107
|
+
try {
|
|
8108
|
+
await entry.cleanup();
|
|
8109
|
+
} catch (error2) {
|
|
8110
|
+
console.error(`[ActionEngine] Error reverting conditional action ${id}:`, error2);
|
|
8111
|
+
}
|
|
8112
|
+
entry.state = "deferred";
|
|
8113
|
+
entry.cleanup = () => {
|
|
8114
|
+
};
|
|
8115
|
+
entry.updateFn = void 0;
|
|
8116
|
+
publishEvent("action.deferred", { id, kind: action.kind });
|
|
8117
|
+
} else if (entry.state === "deferred" && shouldApply) {
|
|
8118
|
+
try {
|
|
8119
|
+
const context = createExecutorContext();
|
|
8120
|
+
const execResult = await executeAction(action, context);
|
|
8121
|
+
entry.state = "applied";
|
|
8122
|
+
entry.cleanup = execResult.cleanup;
|
|
8123
|
+
entry.updateFn = execResult.updateFn;
|
|
8124
|
+
entry.appliedTs = Date.now();
|
|
8125
|
+
publishEvent("action.applied", {
|
|
8126
|
+
id,
|
|
8127
|
+
kind: action.kind,
|
|
8128
|
+
anchorId: "anchorId" in action ? action.anchorId : void 0
|
|
8129
|
+
});
|
|
8130
|
+
} catch (error2) {
|
|
8131
|
+
console.error(`[ActionEngine] Error applying deferred action ${id}:`, error2);
|
|
8132
|
+
entry.state = "failed";
|
|
8133
|
+
}
|
|
8134
|
+
}
|
|
8135
|
+
};
|
|
8136
|
+
if (runtime3.context) {
|
|
8137
|
+
unsubs.push(runtime3.context.subscribe(onReeval));
|
|
8138
|
+
}
|
|
8139
|
+
if (runtime3.accumulator) {
|
|
8140
|
+
unsubs.push(runtime3.accumulator.subscribe(onReeval));
|
|
8141
|
+
}
|
|
8142
|
+
conditionalUnsubs.set(id, unsubs);
|
|
8143
|
+
}
|
|
6651
8144
|
async function apply(action) {
|
|
6652
8145
|
const validation = validateAction(action);
|
|
6653
8146
|
if (!validation.valid) {
|
|
@@ -6660,22 +8153,61 @@ function createActionEngine(options) {
|
|
|
6660
8153
|
throw new Error(`Action validation failed: ${errorMessages}`);
|
|
6661
8154
|
}
|
|
6662
8155
|
const id = generateId();
|
|
6663
|
-
const
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
8156
|
+
const triggerWhen = action.triggerWhen;
|
|
8157
|
+
if (triggerWhen && runtime3) {
|
|
8158
|
+
const evalResult = runtime3.evaluateSync(triggerWhen);
|
|
8159
|
+
if (!evalResult.value) {
|
|
8160
|
+
const entry2 = {
|
|
8161
|
+
id,
|
|
8162
|
+
action,
|
|
8163
|
+
adaptiveId,
|
|
8164
|
+
appliedTs: Date.now(),
|
|
8165
|
+
state: "deferred",
|
|
8166
|
+
cleanup: () => {
|
|
8167
|
+
}
|
|
8168
|
+
};
|
|
8169
|
+
activeActions.set(id, entry2);
|
|
8170
|
+
const handle2 = {
|
|
8171
|
+
id,
|
|
8172
|
+
action,
|
|
8173
|
+
async revert() {
|
|
8174
|
+
const entry3 = activeActions.get(id);
|
|
8175
|
+
if (!entry3) return;
|
|
8176
|
+
const unsubs = conditionalUnsubs.get(id);
|
|
8177
|
+
if (unsubs) {
|
|
8178
|
+
for (const unsub of unsubs) unsub();
|
|
8179
|
+
conditionalUnsubs.delete(id);
|
|
8180
|
+
}
|
|
8181
|
+
entry3.state = "reverted";
|
|
8182
|
+
activeActions.delete(id);
|
|
8183
|
+
},
|
|
8184
|
+
isApplied() {
|
|
8185
|
+
const entry3 = activeActions.get(id);
|
|
8186
|
+
return (entry3 == null ? void 0 : entry3.state) === "applied";
|
|
8187
|
+
},
|
|
8188
|
+
async update(changes) {
|
|
8189
|
+
const entry3 = activeActions.get(id);
|
|
8190
|
+
if (!entry3 || entry3.state !== "applied") {
|
|
8191
|
+
throw new Error("Cannot update action that is not applied");
|
|
8192
|
+
}
|
|
8193
|
+
if (entry3.updateFn) {
|
|
8194
|
+
await entry3.updateFn(changes);
|
|
8195
|
+
} else {
|
|
8196
|
+
throw new Error(`Action kind ${action.kind} does not support updates`);
|
|
8197
|
+
}
|
|
8198
|
+
},
|
|
8199
|
+
getState() {
|
|
8200
|
+
var _a2;
|
|
8201
|
+
const entry3 = activeActions.get(id);
|
|
8202
|
+
return (_a2 = entry3 == null ? void 0 : entry3.state) != null ? _a2 : "reverted";
|
|
8203
|
+
}
|
|
8204
|
+
};
|
|
8205
|
+
subscribeForReeval(id, action, triggerWhen, handle2);
|
|
8206
|
+
return handle2;
|
|
6676
8207
|
}
|
|
6677
|
-
result = await executor(action, context);
|
|
6678
8208
|
}
|
|
8209
|
+
const context = createExecutorContext();
|
|
8210
|
+
const result = await executeAction(action, context);
|
|
6679
8211
|
const entry = {
|
|
6680
8212
|
id,
|
|
6681
8213
|
action,
|
|
@@ -6697,6 +8229,11 @@ function createActionEngine(options) {
|
|
|
6697
8229
|
async revert() {
|
|
6698
8230
|
const entry2 = activeActions.get(id);
|
|
6699
8231
|
if (!entry2 || entry2.state !== "applied") return;
|
|
8232
|
+
const unsubs = conditionalUnsubs.get(id);
|
|
8233
|
+
if (unsubs) {
|
|
8234
|
+
for (const unsub of unsubs) unsub();
|
|
8235
|
+
conditionalUnsubs.delete(id);
|
|
8236
|
+
}
|
|
6700
8237
|
try {
|
|
6701
8238
|
await entry2.cleanup();
|
|
6702
8239
|
entry2.state = "reverted";
|
|
@@ -6734,6 +8271,9 @@ function createActionEngine(options) {
|
|
|
6734
8271
|
return (_a2 = entry2 == null ? void 0 : entry2.state) != null ? _a2 : "reverted";
|
|
6735
8272
|
}
|
|
6736
8273
|
};
|
|
8274
|
+
if (triggerWhen && runtime3) {
|
|
8275
|
+
subscribeForReeval(id, action, triggerWhen, handle);
|
|
8276
|
+
}
|
|
6737
8277
|
return handle;
|
|
6738
8278
|
}
|
|
6739
8279
|
async function applyBatch(actions) {
|
|
@@ -6749,7 +8289,7 @@ function createActionEngine(options) {
|
|
|
6749
8289
|
errorMessages,
|
|
6750
8290
|
"\nActions:",
|
|
6751
8291
|
actions.map(
|
|
6752
|
-
(a, i) => ` [${i}] ${a.kind} ${a.anchorId ? `anchor="${a.anchorId}"` : ""} ${a.label ? `label="${a.label}"` : ""}`
|
|
8292
|
+
(a, i) => ` [${i}] ${a.kind} ${a.anchorId ? `anchor="${typeof a.anchorId === "string" ? a.anchorId : a.anchorId.selector}"` : ""} ${a.label ? `label="${a.label}"` : ""}`
|
|
6753
8293
|
).join("\n")
|
|
6754
8294
|
);
|
|
6755
8295
|
throw new Error(`Batch validation failed: ${errorMessages}`);
|
|
@@ -6808,6 +8348,15 @@ function createActionEngine(options) {
|
|
|
6808
8348
|
}));
|
|
6809
8349
|
}
|
|
6810
8350
|
function destroy() {
|
|
8351
|
+
for (const unsubs of conditionalUnsubs.values()) {
|
|
8352
|
+
for (const unsub of unsubs) {
|
|
8353
|
+
try {
|
|
8354
|
+
unsub();
|
|
8355
|
+
} catch {
|
|
8356
|
+
}
|
|
8357
|
+
}
|
|
8358
|
+
}
|
|
8359
|
+
conditionalUnsubs.clear();
|
|
6811
8360
|
for (const entry of activeActions.values()) {
|
|
6812
8361
|
if (entry.state === "applied") {
|
|
6813
8362
|
try {
|
|
@@ -6828,6 +8377,154 @@ function createActionEngine(options) {
|
|
|
6828
8377
|
};
|
|
6829
8378
|
}
|
|
6830
8379
|
|
|
8380
|
+
// src/anchor/AnchorResolver.ts
|
|
8381
|
+
function createAnchorResolver(opts) {
|
|
8382
|
+
var _a2, _b;
|
|
8383
|
+
const root = (_a2 = opts == null ? void 0 : opts.root) != null ? _a2 : typeof document !== "undefined" ? document.body : null;
|
|
8384
|
+
const defaultTimeoutMs = (_b = opts == null ? void 0 : opts.defaultTimeoutMs) != null ? _b : 5e3;
|
|
8385
|
+
const waiters = /* @__PURE__ */ new Map();
|
|
8386
|
+
const appearWatchers = /* @__PURE__ */ new Map();
|
|
8387
|
+
let observer = null;
|
|
8388
|
+
let destroyed = false;
|
|
8389
|
+
function resolve(selector) {
|
|
8390
|
+
if (!root) return null;
|
|
8391
|
+
try {
|
|
8392
|
+
return root.querySelector(selector);
|
|
8393
|
+
} catch {
|
|
8394
|
+
return null;
|
|
8395
|
+
}
|
|
8396
|
+
}
|
|
8397
|
+
function checkPending() {
|
|
8398
|
+
for (const [selector, set] of waiters) {
|
|
8399
|
+
const el = resolve(selector);
|
|
8400
|
+
if (el) {
|
|
8401
|
+
for (const w of set) {
|
|
8402
|
+
clearTimeout(w.timer);
|
|
8403
|
+
w.resolve(el);
|
|
8404
|
+
}
|
|
8405
|
+
waiters.delete(selector);
|
|
8406
|
+
}
|
|
8407
|
+
}
|
|
8408
|
+
for (const [selector, set] of appearWatchers) {
|
|
8409
|
+
const el = resolve(selector);
|
|
8410
|
+
if (el) {
|
|
8411
|
+
for (const watcher of set) {
|
|
8412
|
+
if (!watcher.cancelled) {
|
|
8413
|
+
watcher.cb(el);
|
|
8414
|
+
}
|
|
8415
|
+
}
|
|
8416
|
+
appearWatchers.delete(selector);
|
|
8417
|
+
}
|
|
8418
|
+
}
|
|
8419
|
+
if (waiters.size === 0 && appearWatchers.size === 0) {
|
|
8420
|
+
disconnectObserver();
|
|
8421
|
+
}
|
|
8422
|
+
}
|
|
8423
|
+
function ensureObserver() {
|
|
8424
|
+
if (observer || destroyed) return;
|
|
8425
|
+
if (typeof MutationObserver === "undefined" || !root) return;
|
|
8426
|
+
observer = new MutationObserver(() => {
|
|
8427
|
+
checkPending();
|
|
8428
|
+
});
|
|
8429
|
+
observer.observe(root, { childList: true, subtree: true });
|
|
8430
|
+
}
|
|
8431
|
+
function disconnectObserver() {
|
|
8432
|
+
if (observer) {
|
|
8433
|
+
observer.disconnect();
|
|
8434
|
+
observer = null;
|
|
8435
|
+
}
|
|
8436
|
+
}
|
|
8437
|
+
function removeWaiter(selector, waiter) {
|
|
8438
|
+
const set = waiters.get(selector);
|
|
8439
|
+
if (set) {
|
|
8440
|
+
set.delete(waiter);
|
|
8441
|
+
if (set.size === 0) {
|
|
8442
|
+
waiters.delete(selector);
|
|
8443
|
+
}
|
|
8444
|
+
}
|
|
8445
|
+
if (waiters.size === 0 && appearWatchers.size === 0) {
|
|
8446
|
+
disconnectObserver();
|
|
8447
|
+
}
|
|
8448
|
+
}
|
|
8449
|
+
function waitFor(selector, timeoutMs) {
|
|
8450
|
+
if (destroyed) {
|
|
8451
|
+
return Promise.reject(new Error("AnchorResolver destroyed"));
|
|
8452
|
+
}
|
|
8453
|
+
const existing = resolve(selector);
|
|
8454
|
+
if (existing) return Promise.resolve(existing);
|
|
8455
|
+
const timeout = timeoutMs != null ? timeoutMs : defaultTimeoutMs;
|
|
8456
|
+
return new Promise((res, rej) => {
|
|
8457
|
+
const waiter = {
|
|
8458
|
+
resolve: res,
|
|
8459
|
+
reject: rej,
|
|
8460
|
+
timer: setTimeout(() => {
|
|
8461
|
+
removeWaiter(selector, waiter);
|
|
8462
|
+
rej(new Error(`waitFor("${selector}") timed out after ${timeout}ms`));
|
|
8463
|
+
}, timeout)
|
|
8464
|
+
};
|
|
8465
|
+
let set = waiters.get(selector);
|
|
8466
|
+
if (!set) {
|
|
8467
|
+
set = /* @__PURE__ */ new Set();
|
|
8468
|
+
waiters.set(selector, set);
|
|
8469
|
+
}
|
|
8470
|
+
set.add(waiter);
|
|
8471
|
+
ensureObserver();
|
|
8472
|
+
});
|
|
8473
|
+
}
|
|
8474
|
+
function onAppear(selector, cb) {
|
|
8475
|
+
if (destroyed) return () => {
|
|
8476
|
+
};
|
|
8477
|
+
const existing = resolve(selector);
|
|
8478
|
+
if (existing) {
|
|
8479
|
+
cb(existing);
|
|
8480
|
+
return () => {
|
|
8481
|
+
};
|
|
8482
|
+
}
|
|
8483
|
+
const watcher = { cb, cancelled: false };
|
|
8484
|
+
let set = appearWatchers.get(selector);
|
|
8485
|
+
if (!set) {
|
|
8486
|
+
set = /* @__PURE__ */ new Set();
|
|
8487
|
+
appearWatchers.set(selector, set);
|
|
8488
|
+
}
|
|
8489
|
+
set.add(watcher);
|
|
8490
|
+
ensureObserver();
|
|
8491
|
+
return () => {
|
|
8492
|
+
watcher.cancelled = true;
|
|
8493
|
+
const s = appearWatchers.get(selector);
|
|
8494
|
+
if (s) {
|
|
8495
|
+
s.delete(watcher);
|
|
8496
|
+
if (s.size === 0) {
|
|
8497
|
+
appearWatchers.delete(selector);
|
|
8498
|
+
}
|
|
8499
|
+
}
|
|
8500
|
+
if (waiters.size === 0 && appearWatchers.size === 0) {
|
|
8501
|
+
disconnectObserver();
|
|
8502
|
+
}
|
|
8503
|
+
};
|
|
8504
|
+
}
|
|
8505
|
+
function pendingCount() {
|
|
8506
|
+
let count = 0;
|
|
8507
|
+
for (const set of waiters.values()) {
|
|
8508
|
+
count += set.size;
|
|
8509
|
+
}
|
|
8510
|
+
return count;
|
|
8511
|
+
}
|
|
8512
|
+
function destroy() {
|
|
8513
|
+
destroyed = true;
|
|
8514
|
+
disconnectObserver();
|
|
8515
|
+
const err = new Error("AnchorResolver destroyed");
|
|
8516
|
+
for (const set of waiters.values()) {
|
|
8517
|
+
for (const w of set) {
|
|
8518
|
+
clearTimeout(w.timer);
|
|
8519
|
+
w.reject(err);
|
|
8520
|
+
}
|
|
8521
|
+
}
|
|
8522
|
+
waiters.clear();
|
|
8523
|
+
appearWatchers.clear();
|
|
8524
|
+
}
|
|
8525
|
+
return { resolve, waitFor, onAppear, pendingCount, destroy };
|
|
8526
|
+
}
|
|
8527
|
+
|
|
6831
8528
|
// src/context/ContextManager.ts
|
|
6832
8529
|
function createDefaultContext() {
|
|
6833
8530
|
const now = Date.now();
|
|
@@ -7059,13 +8756,13 @@ function createContextManager(options = {}) {
|
|
|
7059
8756
|
|
|
7060
8757
|
// src/decisions/strategies/rules.ts
|
|
7061
8758
|
function evaluateCondition(condition, evalContext) {
|
|
7062
|
-
var _a2, _b, _c, _d, _e;
|
|
8759
|
+
var _a2, _b, _c, _d, _e, _f, _g;
|
|
7063
8760
|
const { context, state, events } = evalContext;
|
|
7064
8761
|
switch (condition.type) {
|
|
7065
8762
|
case "page_url": {
|
|
7066
8763
|
const { url } = condition;
|
|
7067
|
-
const currentUrl = context.page.url;
|
|
7068
|
-
const pattern = url.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(
|
|
8764
|
+
const currentUrl = context.page.url.split("?")[0].split("#")[0];
|
|
8765
|
+
const pattern = url.replace(/\*\*/g, "\0GLOBSTAR\0").replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, "[^/]*").replace(/\0GLOBSTAR\0/g, ".*");
|
|
7069
8766
|
const regex = new RegExp(`^${pattern}$`);
|
|
7070
8767
|
return regex.test(currentUrl);
|
|
7071
8768
|
}
|
|
@@ -7073,7 +8770,8 @@ function evaluateCondition(condition, evalContext) {
|
|
|
7073
8770
|
return context.page.routeId === condition.routeId;
|
|
7074
8771
|
}
|
|
7075
8772
|
case "anchor_visible": {
|
|
7076
|
-
const
|
|
8773
|
+
const condSelector = typeof condition.anchorId === "string" ? condition.anchorId : (_b = (_a2 = condition.anchorId) == null ? void 0 : _a2.selector) != null ? _b : "";
|
|
8774
|
+
const anchor = (_c = context.anchors) == null ? void 0 : _c.find((a) => a.anchorId === condSelector);
|
|
7077
8775
|
switch (condition.state) {
|
|
7078
8776
|
case "visible":
|
|
7079
8777
|
return (anchor == null ? void 0 : anchor.visible) === true;
|
|
@@ -7087,7 +8785,7 @@ function evaluateCondition(condition, evalContext) {
|
|
|
7087
8785
|
}
|
|
7088
8786
|
case "event_occurred": {
|
|
7089
8787
|
if (!events) return false;
|
|
7090
|
-
const withinMs = (
|
|
8788
|
+
const withinMs = (_d = condition.withinMs) != null ? _d : 6e4;
|
|
7091
8789
|
return events.hasRecentEvent(condition.eventName, withinMs);
|
|
7092
8790
|
}
|
|
7093
8791
|
case "state_equals": {
|
|
@@ -7122,17 +8820,17 @@ function evaluateCondition(condition, evalContext) {
|
|
|
7122
8820
|
}
|
|
7123
8821
|
}
|
|
7124
8822
|
case "dismissed": {
|
|
7125
|
-
if (!state) return (
|
|
8823
|
+
if (!state) return (_e = condition.inverted) != null ? _e : false;
|
|
7126
8824
|
const isDismissed = state.isDismissed(condition.key);
|
|
7127
8825
|
return condition.inverted ? !isDismissed : isDismissed;
|
|
7128
8826
|
}
|
|
7129
8827
|
case "cooldown_active": {
|
|
7130
|
-
if (!state) return (
|
|
8828
|
+
if (!state) return (_f = condition.inverted) != null ? _f : false;
|
|
7131
8829
|
const isActive = state.isCooldownActive(condition.key);
|
|
7132
8830
|
return condition.inverted ? !isActive : isActive;
|
|
7133
8831
|
}
|
|
7134
8832
|
case "frequency_limit": {
|
|
7135
|
-
if (!state) return (
|
|
8833
|
+
if (!state) return (_g = condition.inverted) != null ? _g : false;
|
|
7136
8834
|
const count = state.getFrequencyCount(condition.key);
|
|
7137
8835
|
const limitReached = count >= condition.limit;
|
|
7138
8836
|
return condition.inverted ? !limitReached : limitReached;
|
|
@@ -8323,7 +10021,7 @@ function createSurfaces(options) {
|
|
|
8323
10021
|
if (!anchorResolver) {
|
|
8324
10022
|
throw new Error("Anchor resolver required for inline slots");
|
|
8325
10023
|
}
|
|
8326
|
-
const anchorEl = anchorResolver(anchorId);
|
|
10024
|
+
const anchorEl = anchorResolver({ selector: anchorId, route: "**" });
|
|
8327
10025
|
if (!anchorEl) {
|
|
8328
10026
|
throw new Error(`Anchor not found for inline slot: ${anchorId}`);
|
|
8329
10027
|
}
|
|
@@ -8336,7 +10034,7 @@ function createSurfaces(options) {
|
|
|
8336
10034
|
if (!anchorResolver) {
|
|
8337
10035
|
throw new Error("Anchor resolver required for adjacent slots");
|
|
8338
10036
|
}
|
|
8339
|
-
const anchorEl = anchorResolver(anchorId);
|
|
10037
|
+
const anchorEl = anchorResolver({ selector: anchorId, route: "**" });
|
|
8340
10038
|
if (!anchorEl) {
|
|
8341
10039
|
throw new Error(`Anchor not found for adjacent slot: ${anchorId}`);
|
|
8342
10040
|
}
|
|
@@ -8739,16 +10437,15 @@ function matchesRouteFilter(url, filter) {
|
|
|
8739
10437
|
function matchRoutePattern(pathname, pattern) {
|
|
8740
10438
|
const normalizedPattern = pattern.replace(/\/$/, "") || "/";
|
|
8741
10439
|
if (pathname === normalizedPattern) return true;
|
|
8742
|
-
const regexPattern = normalizedPattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(
|
|
10440
|
+
const regexPattern = normalizedPattern.replace(/\*\*/g, "\0GLOBSTAR\0").replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, "[^/]*").replace(/\0GLOBSTAR\0/g, ".*").replace(/:[^/]+/g, "[^/]+");
|
|
8743
10441
|
const regex = new RegExp(`^${regexPattern}$`);
|
|
8744
10442
|
return regex.test(pathname);
|
|
8745
10443
|
}
|
|
8746
|
-
function
|
|
8747
|
-
|
|
8748
|
-
|
|
8749
|
-
|
|
8750
|
-
|
|
8751
|
-
}
|
|
10444
|
+
function matchesAnchorRoute(anchorId) {
|
|
10445
|
+
const pathname = typeof window !== "undefined" ? window.location.pathname : "/";
|
|
10446
|
+
const normalizedPath = pathname.replace(/\/$/, "") || "/";
|
|
10447
|
+
const routes = Array.isArray(anchorId.route) ? anchorId.route : [anchorId.route];
|
|
10448
|
+
return routes.some((pattern) => matchRoutePattern(normalizedPath, pattern));
|
|
8752
10449
|
}
|
|
8753
10450
|
function createSmartCanvasRuntime(options = {}) {
|
|
8754
10451
|
var _a2, _b, _c, _d;
|
|
@@ -8777,7 +10474,19 @@ function createSmartCanvasRuntime(options = {}) {
|
|
|
8777
10474
|
accumulator
|
|
8778
10475
|
});
|
|
8779
10476
|
const overlayRoot = ensureOverlayRoot();
|
|
8780
|
-
const
|
|
10477
|
+
const anchorResolverService = createAnchorResolver();
|
|
10478
|
+
const anchorResolver = (anchorId) => {
|
|
10479
|
+
if (!matchesAnchorRoute(anchorId)) return null;
|
|
10480
|
+
return anchorResolverService.resolve(anchorId.selector);
|
|
10481
|
+
};
|
|
10482
|
+
const waitForAnchor = async (anchorId, timeoutMs) => {
|
|
10483
|
+
if (!matchesAnchorRoute(anchorId)) return null;
|
|
10484
|
+
try {
|
|
10485
|
+
return await anchorResolverService.waitFor(anchorId.selector, timeoutMs);
|
|
10486
|
+
} catch {
|
|
10487
|
+
return null;
|
|
10488
|
+
}
|
|
10489
|
+
};
|
|
8781
10490
|
const surfaces = createSurfaces({
|
|
8782
10491
|
overlayRoot,
|
|
8783
10492
|
eventBus: events,
|
|
@@ -8789,8 +10498,14 @@ function createSmartCanvasRuntime(options = {}) {
|
|
|
8789
10498
|
eventBus: events,
|
|
8790
10499
|
surfaces,
|
|
8791
10500
|
anchorResolver,
|
|
10501
|
+
waitForAnchor,
|
|
8792
10502
|
executorRegistry: executors3,
|
|
8793
|
-
subscribeNavigation: (callback) => navigation.subscribe(callback)
|
|
10503
|
+
subscribeNavigation: (callback) => navigation.subscribe(callback),
|
|
10504
|
+
runtime: {
|
|
10505
|
+
evaluateSync: (strategy) => decisionEngine.evaluateSync(strategy, context.get()),
|
|
10506
|
+
context,
|
|
10507
|
+
accumulator
|
|
10508
|
+
}
|
|
8794
10509
|
});
|
|
8795
10510
|
const runtime3 = {
|
|
8796
10511
|
telemetry,
|
|
@@ -8804,6 +10519,7 @@ function createSmartCanvasRuntime(options = {}) {
|
|
|
8804
10519
|
executors: executors3,
|
|
8805
10520
|
apps,
|
|
8806
10521
|
accumulator,
|
|
10522
|
+
anchorResolver: anchorResolverService,
|
|
8807
10523
|
navigation,
|
|
8808
10524
|
version: RUNTIME_VERSION,
|
|
8809
10525
|
mode,
|
|
@@ -8814,6 +10530,7 @@ function createSmartCanvasRuntime(options = {}) {
|
|
|
8814
10530
|
return decisionEngine.evaluateSync(strategy, context.get());
|
|
8815
10531
|
},
|
|
8816
10532
|
async filterTiles(tiles) {
|
|
10533
|
+
var _a3, _b2;
|
|
8817
10534
|
const currentUrl = context.get().page.url;
|
|
8818
10535
|
const results = [];
|
|
8819
10536
|
for (const tile of tiles) {
|
|
@@ -8825,14 +10542,20 @@ function createSmartCanvasRuntime(options = {}) {
|
|
|
8825
10542
|
if (!matchesRouteFilter(currentUrl, activation.routes)) {
|
|
8826
10543
|
continue;
|
|
8827
10544
|
}
|
|
8828
|
-
if (
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
8834
|
-
|
|
10545
|
+
if (activation.onlyIfPopulated) {
|
|
10546
|
+
const actions2 = (_b2 = (_a3 = tile.props) == null ? void 0 : _a3.actions) != null ? _b2 : [];
|
|
10547
|
+
if (actions2.length > 0) {
|
|
10548
|
+
const hasVisible = actions2.some((a) => {
|
|
10549
|
+
if (!a.triggerWhen) return true;
|
|
10550
|
+
return decisionEngine.evaluateSync(
|
|
10551
|
+
a.triggerWhen,
|
|
10552
|
+
context.get()
|
|
10553
|
+
).value;
|
|
10554
|
+
});
|
|
10555
|
+
if (!hasVisible) continue;
|
|
10556
|
+
}
|
|
8835
10557
|
}
|
|
10558
|
+
results.push(tile);
|
|
8836
10559
|
}
|
|
8837
10560
|
return results;
|
|
8838
10561
|
},
|
|
@@ -8843,6 +10566,7 @@ function createSmartCanvasRuntime(options = {}) {
|
|
|
8843
10566
|
apps.unbind().catch((err) => {
|
|
8844
10567
|
console.error("[Runtime] Error unbinding apps registry:", err);
|
|
8845
10568
|
});
|
|
10569
|
+
anchorResolverService.destroy();
|
|
8846
10570
|
accumulator.destroy();
|
|
8847
10571
|
navigation.destroy();
|
|
8848
10572
|
context.destroy();
|
|
@@ -9433,7 +11157,7 @@ async function init(options) {
|
|
|
9433
11157
|
console.log(
|
|
9434
11158
|
"[Syntro Bootstrap] Actions in config:",
|
|
9435
11159
|
config.actions.map(
|
|
9436
|
-
(a, i) => `[${i}] ${a.kind}${a.anchorId ? ` anchor="${a.anchorId}"` : ""}${a.label ? ` "${a.label}"` : ""}`
|
|
11160
|
+
(a, i) => `[${i}] ${a.kind}${a.anchorId ? ` anchor="${typeof a.anchorId === "string" ? a.anchorId : a.anchorId.selector}"` : ""}${a.label ? ` "${a.label}"` : ""}`
|
|
9437
11161
|
).join(", ")
|
|
9438
11162
|
);
|
|
9439
11163
|
}
|
|
@@ -9504,11 +11228,9 @@ if (typeof window !== "undefined") {
|
|
|
9504
11228
|
export {
|
|
9505
11229
|
runtime,
|
|
9506
11230
|
base,
|
|
9507
|
-
brand,
|
|
9508
11231
|
slateGrey,
|
|
9509
11232
|
red,
|
|
9510
11233
|
purple,
|
|
9511
|
-
border,
|
|
9512
11234
|
runtime2,
|
|
9513
11235
|
createAppContext,
|
|
9514
11236
|
cleanupAppContext,
|
|
@@ -9567,6 +11289,7 @@ export {
|
|
|
9567
11289
|
validateAction,
|
|
9568
11290
|
validateActions,
|
|
9569
11291
|
createActionEngine,
|
|
11292
|
+
createAnchorResolver,
|
|
9570
11293
|
ContextManager,
|
|
9571
11294
|
createContextManager,
|
|
9572
11295
|
evaluateCondition,
|
|
@@ -9605,4 +11328,4 @@ export {
|
|
|
9605
11328
|
encodeToken,
|
|
9606
11329
|
Syntro
|
|
9607
11330
|
};
|
|
9608
|
-
//# sourceMappingURL=chunk-
|
|
11331
|
+
//# sourceMappingURL=chunk-Q4WGXNKC.js.map
|