@syntrologie/runtime-sdk 2.4.0-canary.23 → 2.4.0-canary.25

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.
@@ -3,7 +3,7 @@ import {
3
3
  __privateGet,
4
4
  __privateSet,
5
5
  __publicField
6
- } from "./chunk-P5G4KT2U.js";
6
+ } from "./chunk-BU4Z6PD7.js";
7
7
 
8
8
  // ../adaptives/adaptive-content/dist/reconciliation-guard.js
9
9
  function guardAgainstReconciliation(container, anchor, reinsertFn, opts) {
@@ -784,7 +784,7 @@ var CelebrationEngine = class {
784
784
  };
785
785
 
786
786
  // ../adaptives/adaptive-overlays/dist/celebrations/index.js
787
- var DEFAULT_COLORS2 = [
787
+ var FALLBACK_COLORS = [
788
788
  "#ff0000",
789
789
  "#00ff00",
790
790
  "#0000ff",
@@ -794,6 +794,22 @@ var DEFAULT_COLORS2 = [
794
794
  "#ff8800",
795
795
  "#8800ff"
796
796
  ];
797
+ function buildThemePalette(primary, hover) {
798
+ return [primary, hover, `${primary}cc`, `${hover}cc`, "#ffffff", `${primary}80`];
799
+ }
800
+ function readThemeColors(overlayRoot) {
801
+ var _a2, _b;
802
+ try {
803
+ const styles = getComputedStyle(overlayRoot);
804
+ const primary = (_a2 = styles.getPropertyValue("--sc-color-primary")) == null ? void 0 : _a2.trim();
805
+ const hover = (_b = styles.getPropertyValue("--sc-color-primary-hover")) == null ? void 0 : _b.trim();
806
+ if ((primary == null ? void 0 : primary.startsWith("#")) && primary.length >= 7) {
807
+ return buildThemePalette(primary, hover || primary);
808
+ }
809
+ } catch {
810
+ }
811
+ return null;
812
+ }
797
813
  var effectRegistry = /* @__PURE__ */ new Map([
798
814
  ["confetti", confettiEffect],
799
815
  ["fireworks", fireworksEffect],
@@ -801,17 +817,18 @@ var effectRegistry = /* @__PURE__ */ new Map([
801
817
  ["emoji-rain", emojiRainEffect]
802
818
  ]);
803
819
  var executeCelebrate = async (action, context) => {
804
- var _a2, _b, _c;
820
+ var _a2, _b, _c, _d;
805
821
  const effect = effectRegistry.get(action.effect);
806
822
  if (!effect) {
807
823
  console.warn(`[adaptive-overlays] Unknown celebration effect: "${action.effect}". Available: ${[...effectRegistry.keys()].join(", ")}`);
808
824
  return { cleanup: () => {
809
825
  } };
810
826
  }
827
+ const colors = (_b = (_a2 = action.colors) != null ? _a2 : readThemeColors(context.overlayRoot)) != null ? _b : FALLBACK_COLORS;
811
828
  const config = {
812
- duration: (_a2 = action.duration) != null ? _a2 : 3e3,
813
- intensity: (_b = action.intensity) != null ? _b : "medium",
814
- colors: (_c = action.colors) != null ? _c : DEFAULT_COLORS2,
829
+ duration: (_c = action.duration) != null ? _c : 3e3,
830
+ intensity: (_d = action.intensity) != null ? _d : "medium",
831
+ colors,
815
832
  props: action.props
816
833
  };
817
834
  const engine = new CelebrationEngine();
@@ -1684,6 +1701,13 @@ function sanitizeHtml2(html) {
1684
1701
  }
1685
1702
 
1686
1703
  // ../adaptives/adaptive-overlays/dist/modal.js
1704
+ var V = {
1705
+ bg: "var(--sc-overlay-background, #ffffff)",
1706
+ title: "var(--sc-overlay-title-color, var(--sc-overlay-text-color, #111827))",
1707
+ text: "var(--sc-overlay-text-color, #4b5563)",
1708
+ accent: "var(--sc-color-primary, #4f46e5)",
1709
+ radius: "var(--sc-border-radius, 12px)"
1710
+ };
1687
1711
  var executeModal = async (action, context) => {
1688
1712
  var _a2, _b;
1689
1713
  const { content, size = "md", blocking = false, scrim, dismiss, ctaButtons } = action;
@@ -1710,8 +1734,8 @@ var executeModal = async (action, context) => {
1710
1734
  transform: translate(-50%, -50%) scale(0.95);
1711
1735
  max-width: ${sizeMap[size]};
1712
1736
  width: 90%;
1713
- background: ${base.white};
1714
- border-radius: 12px;
1737
+ background: ${V.bg};
1738
+ border-radius: ${V.radius};
1715
1739
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
1716
1740
  z-index: 2147483646;
1717
1741
  opacity: 0;
@@ -1720,9 +1744,9 @@ var executeModal = async (action, context) => {
1720
1744
  `;
1721
1745
  let html = "";
1722
1746
  if (content.title) {
1723
- html += `<h2 class="syntro-modal-title" style="margin: 0 0 12px 0; font-size: 18px; font-weight: 600; color: #111827;">${sanitizeHtml2(content.title)}</h2>`;
1747
+ 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>`;
1724
1748
  }
1725
- html += `<div class="syntro-modal-body" style="color: #4b5563; line-height: 1.5;">${sanitizeHtml2(content.body)}</div>`;
1749
+ html += `<div class="syntro-modal-body" style="color: ${V.text}; line-height: 1.5;">${sanitizeHtml2(content.body)}</div>`;
1726
1750
  if ((dismiss == null ? void 0 : dismiss.closeButton) !== false) {
1727
1751
  html += `
1728
1752
  <button class="syntro-modal-close" data-syntro-action="dismiss" style="
@@ -1733,7 +1757,8 @@ var executeModal = async (action, context) => {
1733
1757
  border: none;
1734
1758
  cursor: pointer;
1735
1759
  padding: 4px;
1736
- color: #6b7280;
1760
+ color: ${V.text};
1761
+ opacity: 0.6;
1737
1762
  " aria-label="Close">
1738
1763
  <svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
1739
1764
  <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"/>
@@ -1756,7 +1781,7 @@ var executeModal = async (action, context) => {
1756
1781
  font-weight: 500;
1757
1782
  cursor: pointer;
1758
1783
  transition: background 150ms ease;
1759
- ${isPrimary ? "background: #4f46e5; color: white; border: none;" : "background: white; color: #374151; border: 1px solid #d1d5db;"}
1784
+ ${isPrimary ? `background: ${V.accent}; color: white; border: none;` : `background: transparent; color: ${V.accent}; border: 1px solid currentColor; opacity: 0.7;`}
1760
1785
  "
1761
1786
  >
1762
1787
  ${sanitizeHtml2(btn.label)}
@@ -2382,7 +2407,7 @@ var WorkflowMountableWidget = {
2382
2407
 
2383
2408
  // ../adaptives/adaptive-overlays/dist/runtime.js
2384
2409
  var executeHighlight = async (action, context) => {
2385
- var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2410
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2386
2411
  let anchorEl = context.resolveAnchor(action.anchorId);
2387
2412
  if (!anchorEl && context.waitForAnchor) {
2388
2413
  anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
@@ -2392,14 +2417,29 @@ var executeHighlight = async (action, context) => {
2392
2417
  return { cleanup: () => {
2393
2418
  } };
2394
2419
  }
2420
+ const existing = anchorEl.getAttribute("data-syntro-highlight");
2421
+ if (existing) {
2422
+ const prev = context.overlayRoot.querySelectorAll(".syntro-spotlight-scrim, .syntro-spotlight-ring");
2423
+ prev.forEach((el) => el.remove());
2424
+ }
2425
+ anchorEl.setAttribute("data-syntro-highlight", "true");
2426
+ let ringColor = (_a2 = action.style) == null ? void 0 : _a2.color;
2427
+ if (!ringColor) {
2428
+ try {
2429
+ const primary = (_b = getComputedStyle(context.overlayRoot).getPropertyValue("--sc-color-primary")) == null ? void 0 : _b.trim();
2430
+ if (primary)
2431
+ ringColor = primary;
2432
+ } catch {
2433
+ }
2434
+ }
2395
2435
  const handle = showHighlight(anchorEl, context.overlayRoot, {
2396
- paddingPx: (_b = (_a2 = action.style) == null ? void 0 : _a2.paddingPx) != null ? _b : 12,
2397
- radiusPx: (_d = (_c = action.style) == null ? void 0 : _c.radiusPx) != null ? _d : 12,
2398
- scrimOpacity: (_f = (_e = action.style) == null ? void 0 : _e.scrimOpacity) != null ? _f : 0.55,
2399
- ringColor: (_g = action.style) == null ? void 0 : _g.color,
2400
- blocking: (_h = action.blocking) != null ? _h : false,
2401
- onClickOutside: (_i = action.onClickOutside) != null ? _i : true,
2402
- onEsc: (_j = action.onEsc) != null ? _j : true
2436
+ paddingPx: (_d = (_c = action.style) == null ? void 0 : _c.paddingPx) != null ? _d : 12,
2437
+ radiusPx: (_f = (_e = action.style) == null ? void 0 : _e.radiusPx) != null ? _f : 12,
2438
+ scrimOpacity: (_h = (_g = action.style) == null ? void 0 : _g.scrimOpacity) != null ? _h : 0.55,
2439
+ ringColor,
2440
+ blocking: (_i = action.blocking) != null ? _i : false,
2441
+ onClickOutside: (_j = action.onClickOutside) != null ? _j : true,
2442
+ onEsc: (_k = action.onEsc) != null ? _k : true
2403
2443
  });
2404
2444
  context.publishEvent("action.applied", {
2405
2445
  id: context.generateId(),
@@ -2409,6 +2449,7 @@ var executeHighlight = async (action, context) => {
2409
2449
  return {
2410
2450
  cleanup: () => {
2411
2451
  handle.destroy();
2452
+ anchorEl.removeAttribute("data-syntro-highlight");
2412
2453
  }
2413
2454
  };
2414
2455
  };
@@ -2673,7 +2714,7 @@ var runtime2 = {
2673
2714
  executors: executors2,
2674
2715
  widgets: [
2675
2716
  {
2676
- id: "workflow:tracker",
2717
+ id: "adaptive-overlays:workflow-tracker",
2677
2718
  component: WorkflowMountableWidget,
2678
2719
  metadata: {
2679
2720
  name: "Workflow Tracker",
@@ -3291,7 +3332,7 @@ function getAntiFlickerSnippet(config = {}) {
3291
3332
  }
3292
3333
 
3293
3334
  // src/version.ts
3294
- var SDK_VERSION = "2.4.0-canary.23";
3335
+ var SDK_VERSION = "2.4.0-canary.25";
3295
3336
 
3296
3337
  // src/types.ts
3297
3338
  var SDK_SCHEMA_VERSION = "2.0";
@@ -4246,8 +4287,51 @@ function useDecision(strategy, defaultValue) {
4246
4287
  }
4247
4288
 
4248
4289
  // src/components/TileCard.tsx
4249
- import { useCallback as useCallback3, useEffect as useEffect5, useReducer, useRef as useRef4, useState as useState4 } from "react";
4250
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
4290
+ import {
4291
+ useCallback as useCallback3,
4292
+ useEffect as useEffect5,
4293
+ useMemo as useMemo3,
4294
+ useReducer,
4295
+ useRef as useRef4,
4296
+ useState as useState4
4297
+ } from "react";
4298
+
4299
+ // src/components/TileIcon.tsx
4300
+ import {
4301
+ Compass,
4302
+ FileText,
4303
+ Gamepad2,
4304
+ HelpCircle,
4305
+ Layers,
4306
+ MessageCircle,
4307
+ Sparkles,
4308
+ Trophy
4309
+ } from "lucide-react";
4310
+ import { jsx as jsx4 } from "react/jsx-runtime";
4311
+ var ICON_MAP = {
4312
+ "\u2753": HelpCircle,
4313
+ "\u{1F9ED}": Compass,
4314
+ "\u{1F4DD}": FileText,
4315
+ "\u{1F3AF}": Layers,
4316
+ "\u{1F3C6}": Trophy,
4317
+ "\u2728": Sparkles,
4318
+ "\u{1F4AC}": MessageCircle,
4319
+ "\u{1F3AE}": Gamepad2
4320
+ };
4321
+ function TileIcon({
4322
+ emoji,
4323
+ size = 18,
4324
+ color = "currentColor"
4325
+ }) {
4326
+ const Icon = ICON_MAP[emoji];
4327
+ if (!Icon) {
4328
+ return /* @__PURE__ */ jsx4("span", { children: emoji });
4329
+ }
4330
+ return /* @__PURE__ */ jsx4(Icon, { size, color });
4331
+ }
4332
+
4333
+ // src/components/TileCard.tsx
4334
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
4251
4335
  function WidgetMount({ widgetId, props }) {
4252
4336
  var _a2;
4253
4337
  const runtime3 = useRuntime();
@@ -4290,7 +4374,7 @@ function WidgetMount({ widgetId, props }) {
4290
4374
  }
4291
4375
  );
4292
4376
  }
4293
- return /* @__PURE__ */ jsx4("div", { ref: containerRef, style: { width: "100%", minHeight: "40px" } });
4377
+ return /* @__PURE__ */ jsx5("div", { ref: containerRef, style: { width: "100%", minHeight: "40px" } });
4294
4378
  }
4295
4379
  function TileCard({
4296
4380
  config,
@@ -4298,12 +4382,29 @@ function TileCard({
4298
4382
  telemetry: _telemetry,
4299
4383
  style
4300
4384
  }) {
4301
- const { title, widget, props } = config;
4385
+ const { title, subtitle, widget, props, icon } = config;
4302
4386
  const [, setTick] = useState4(0);
4303
4387
  const runtime3 = useRuntime();
4304
4388
  useEffect5(() => {
4305
4389
  if (runtime3) setTick((t) => t + 1);
4306
4390
  }, [runtime3]);
4391
+ const registration = useMemo3(
4392
+ () => {
4393
+ var _a2, _b;
4394
+ return (_b = (_a2 = runtime3 == null ? void 0 : runtime3.widgets) == null ? void 0 : _a2.getRegistration) == null ? void 0 : _b.call(_a2, widget);
4395
+ },
4396
+ [runtime3 == null ? void 0 : runtime3.widgets, widget]
4397
+ );
4398
+ const resolvedIcon = useMemo3(() => {
4399
+ var _a2, _b;
4400
+ if (icon) return icon;
4401
+ return (_b = (_a2 = registration == null ? void 0 : registration.metadata) == null ? void 0 : _a2.icon) != null ? _b : "+";
4402
+ }, [icon, registration]);
4403
+ const resolvedSubtitle = useMemo3(() => {
4404
+ var _a2;
4405
+ if (subtitle) return subtitle;
4406
+ return (_a2 = registration == null ? void 0 : registration.metadata) == null ? void 0 : _a2.subtitle;
4407
+ }, [subtitle, registration]);
4307
4408
  const [hovered, setHovered] = useState4(false);
4308
4409
  const onMouseEnter = useCallback3(() => setHovered(true), []);
4309
4410
  const onMouseLeave = useCallback3(() => setHovered(false), []);
@@ -4327,21 +4428,15 @@ function TileCard({
4327
4428
  const headerStyle = {
4328
4429
  display: "flex",
4329
4430
  alignItems: "center",
4330
- gap: "0.75rem",
4331
- padding: "0.875rem 1rem",
4332
- minHeight: "72px"
4431
+ gap: "var(--sc-tile-gap, 0.25rem)",
4432
+ padding: "var(--sc-tile-header-padding, 0.375rem 0.75rem)",
4433
+ minHeight: "44px"
4333
4434
  };
4334
4435
  const iconStyle = {
4335
- width: "40px",
4336
- height: "40px",
4337
- borderRadius: "10px",
4338
- background: "var(--sc-tile-icon-background)",
4339
4436
  display: "flex",
4340
4437
  alignItems: "center",
4341
4438
  justifyContent: "center",
4342
- fontSize: "1.25rem",
4343
- flexShrink: 0,
4344
- boxShadow: "var(--sc-tile-icon-shadow)"
4439
+ flexShrink: 0
4345
4440
  };
4346
4441
  return /* @__PURE__ */ jsxs2(
4347
4442
  "article",
@@ -4352,31 +4447,48 @@ function TileCard({
4352
4447
  onMouseLeave,
4353
4448
  children: [
4354
4449
  /* @__PURE__ */ jsxs2("div", { style: headerStyle, children: [
4355
- /* @__PURE__ */ jsx4("div", { style: iconStyle, children: "+" }),
4356
- /* @__PURE__ */ jsx4("div", { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsx4(
4357
- "h3",
4358
- {
4359
- style: {
4360
- fontSize: "0.95rem",
4361
- fontWeight: 600,
4362
- color: "var(--sc-tile-title-color)",
4363
- margin: "0.125rem 0 0",
4364
- whiteSpace: "nowrap",
4365
- overflow: "hidden",
4366
- textOverflow: "ellipsis"
4367
- },
4368
- children: title != null ? title : widget
4369
- }
4370
- ) })
4450
+ /* @__PURE__ */ jsx5("div", { style: iconStyle, children: /* @__PURE__ */ jsx5(TileIcon, { emoji: resolvedIcon, size: resolvedSubtitle ? 36 : 24 }) }),
4451
+ /* @__PURE__ */ jsxs2("div", { style: { flex: 1, minWidth: 0 }, children: [
4452
+ /* @__PURE__ */ jsx5(
4453
+ "h3",
4454
+ {
4455
+ style: {
4456
+ fontSize: "1.14rem",
4457
+ fontWeight: 600,
4458
+ color: "var(--sc-tile-title-color)",
4459
+ margin: "0.125rem 0 0",
4460
+ whiteSpace: "nowrap",
4461
+ overflow: "hidden",
4462
+ textOverflow: "ellipsis"
4463
+ },
4464
+ children: title != null ? title : widget
4465
+ }
4466
+ ),
4467
+ resolvedSubtitle && /* @__PURE__ */ jsx5(
4468
+ "p",
4469
+ {
4470
+ style: {
4471
+ fontSize: "0.8rem",
4472
+ fontWeight: 400,
4473
+ color: "var(--sc-tile-text-color)",
4474
+ margin: "0.125rem 0 0",
4475
+ whiteSpace: "nowrap",
4476
+ overflow: "hidden",
4477
+ textOverflow: "ellipsis"
4478
+ },
4479
+ children: resolvedSubtitle
4480
+ }
4481
+ )
4482
+ ] })
4371
4483
  ] }),
4372
- /* @__PURE__ */ jsx4(
4484
+ /* @__PURE__ */ jsx5(
4373
4485
  "div",
4374
4486
  {
4375
4487
  style: {
4376
- padding: "0 1rem 1rem",
4488
+ padding: "var(--sc-tile-body-padding, 0 0.75rem 0.5rem)",
4377
4489
  borderTop: "1px solid rgba(255, 255, 255, 0.06)"
4378
4490
  },
4379
- children: /* @__PURE__ */ jsx4("div", { style: { paddingTop: "0.875rem" }, children: /* @__PURE__ */ jsx4(WidgetMount, { widgetId: widget, props: { ...props, instanceId: config.id } }) })
4491
+ children: /* @__PURE__ */ jsx5("div", { style: { paddingTop: "var(--sc-tile-gap, 0.25rem)" }, children: /* @__PURE__ */ jsx5(WidgetMount, { widgetId: widget, props: { ...props, instanceId: config.id } }) })
4380
4492
  }
4381
4493
  )
4382
4494
  ]
@@ -4385,7 +4497,7 @@ function TileCard({
4385
4497
  }
4386
4498
 
4387
4499
  // src/components/ShadowCanvasOverlay.tsx
4388
- import { useCallback as useCallback4, useEffect as useEffect7, useMemo as useMemo4, useRef as useRef5, useState as useState5 } from "react";
4500
+ import { useCallback as useCallback4, useEffect as useEffect7, useMemo as useMemo5, useRef as useRef5, useState as useState5 } from "react";
4389
4501
  import { createPortal } from "react-dom";
4390
4502
 
4391
4503
  // src/theme/defaultTheme.ts
@@ -4563,7 +4675,10 @@ var darkDefaults = {
4563
4675
  background: withAlpha(slateGrey[1], 0.6),
4564
4676
  blur: "blur(24px)",
4565
4677
  border: "none",
4566
- width: "clamp(380px, 25vw, 520px)"
4678
+ width: "clamp(380px, 25vw, 520px)",
4679
+ transitionDuration: "300ms",
4680
+ transitionEasing: "cubic-bezier(0.16, 1, 0.3, 1)",
4681
+ transitionFade: "6%"
4567
4682
  },
4568
4683
  launcher: {
4569
4684
  background: button.primary.backgroundDefault,
@@ -4643,7 +4758,10 @@ var lightDefaults = {
4643
4758
  background: withAlpha(slateGrey[12], 0.7),
4644
4759
  blur: "blur(24px)",
4645
4760
  border: "none",
4646
- width: "clamp(380px, 25vw, 520px)"
4761
+ width: "clamp(380px, 25vw, 520px)",
4762
+ transitionDuration: "300ms",
4763
+ transitionEasing: "cubic-bezier(0.16, 1, 0.3, 1)",
4764
+ transitionFade: "6%"
4647
4765
  },
4648
4766
  launcher: {
4649
4767
  background: brand[3],
@@ -4777,8 +4895,8 @@ function flattenThemeConfig(config) {
4777
4895
  }
4778
4896
 
4779
4897
  // src/theme/ThemeProvider.tsx
4780
- import { createContext as createContext3, useContext as useContext3, useEffect as useEffect6, useMemo as useMemo3 } from "react";
4781
- import { jsx as jsx5 } from "react/jsx-runtime";
4898
+ import { createContext as createContext3, useContext as useContext3, useEffect as useEffect6, useMemo as useMemo4 } from "react";
4899
+ import { jsx as jsx6 } from "react/jsx-runtime";
4782
4900
  var ThemeContext = createContext3(null);
4783
4901
  function ThemeProvider({
4784
4902
  children,
@@ -4786,11 +4904,11 @@ function ThemeProvider({
4786
4904
  workspaceTheme,
4787
4905
  shadowRoot
4788
4906
  }) {
4789
- const merged = useMemo3(
4907
+ const merged = useMemo4(
4790
4908
  () => workspaceTheme ? mergeThemeWithWorkspace(workspaceTheme, themeConfig != null ? themeConfig : {}) : mergeThemeConfig(themeConfig != null ? themeConfig : {}),
4791
4909
  [themeConfig, workspaceTheme]
4792
4910
  );
4793
- const cssVariables = useMemo3(() => flattenThemeConfig(merged), [merged]);
4911
+ const cssVariables = useMemo4(() => flattenThemeConfig(merged), [merged]);
4794
4912
  useEffect6(() => {
4795
4913
  if (!shadowRoot) return;
4796
4914
  let styleEl = shadowRoot.querySelector("#sc-theme-vars");
@@ -4809,7 +4927,7 @@ ${cssRules}
4809
4927
  mode: merged.mode,
4810
4928
  cssVariables
4811
4929
  };
4812
- return /* @__PURE__ */ jsx5(ThemeContext.Provider, { value, children });
4930
+ return /* @__PURE__ */ jsx6(ThemeContext.Provider, { value, children });
4813
4931
  }
4814
4932
  function useTheme() {
4815
4933
  const context = useContext3(ThemeContext);
@@ -4820,7 +4938,7 @@ function useTheme() {
4820
4938
  }
4821
4939
 
4822
4940
  // src/components/ShadowCanvasOverlay.tsx
4823
- import { Fragment, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
4941
+ import { Fragment, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
4824
4942
  var LAUNCHER_STYLES_ID = "syntro-launcher-styles";
4825
4943
  function ensureLauncherStyles(target, css) {
4826
4944
  if (target.querySelector(`#${LAUNCHER_STYLES_ID}`)) return;
@@ -4845,7 +4963,7 @@ function ShadowCanvasOverlay({
4845
4963
  canvasTitle,
4846
4964
  displayMode = "standard"
4847
4965
  }) {
4848
- var _a2, _b, _c, _d, _e;
4966
+ var _a2, _b, _c, _d;
4849
4967
  const [mounted, setMounted] = useState5(false);
4850
4968
  const [launcherPos, setLauncherPos] = useState5(null);
4851
4969
  const dragRef = useRef5(null);
@@ -4879,7 +4997,7 @@ function ShadowCanvasOverlay({
4879
4997
  },
4880
4998
  [runtime3, isOpen, onToggle, dismissNotification]
4881
4999
  );
4882
- const launcherCss = useMemo4(
5000
+ const launcherCss = useMemo5(
4883
5001
  () => `
4884
5002
  @keyframes syntro-launcher-pulse {
4885
5003
  0%, 100% {
@@ -4967,7 +5085,7 @@ function ShadowCanvasOverlay({
4967
5085
  }
4968
5086
  }, []);
4969
5087
  const onLauncherPointerUp = useCallback4(
4970
- (_e2) => {
5088
+ (_e) => {
4971
5089
  const drag = dragRef.current;
4972
5090
  dragRef.current = null;
4973
5091
  if (drag && !drag.dragged) {
@@ -4979,17 +5097,20 @@ function ShadowCanvasOverlay({
4979
5097
  const isFocused = displayMode === "focused";
4980
5098
  const isRight = config.canvas.position === "right";
4981
5099
  const isPush = config.canvas.layout === "push";
5100
+ const canvasBorder = (_b = config.canvas.border) != null ? _b : "none";
4982
5101
  const containerRef = useRef5(null);
4983
5102
  const zIndex = 2147483600;
4984
5103
  useEffect7(() => {
4985
- var _a3, _b2;
5104
+ var _a3, _b2, _c2, _d2;
4986
5105
  if (!isPush) return;
4987
5106
  const root = document.documentElement;
4988
5107
  const prop = isRight ? "marginRight" : "marginLeft";
5108
+ const duration = (_a3 = config.canvas.transitionDuration) != null ? _a3 : "300ms";
5109
+ const easing = (_b2 = config.canvas.transitionEasing) != null ? _b2 : "cubic-bezier(0.16, 1, 0.3, 1)";
4989
5110
  const prevTransition = root.style.transition;
4990
- root.style.transition = `${prop} 340ms cubic-bezier(0.16, 1, 0.3, 1)`;
5111
+ root.style.transition = `${prop} ${duration} ${easing}`;
4991
5112
  if (isOpen) {
4992
- const width = (_b2 = (_a3 = containerRef.current) == null ? void 0 : _a3.offsetWidth) != null ? _b2 : 380;
5113
+ const width = (_d2 = (_c2 = containerRef.current) == null ? void 0 : _c2.offsetWidth) != null ? _d2 : 380;
4993
5114
  root.style[prop] = `${width}px`;
4994
5115
  } else {
4995
5116
  root.style[prop] = "0px";
@@ -4998,7 +5119,7 @@ function ShadowCanvasOverlay({
4998
5119
  root.style[prop] = "";
4999
5120
  root.style.transition = prevTransition;
5000
5121
  };
5001
- }, [isPush, isOpen, isRight]);
5122
+ }, [isPush, isOpen, isRight, config.canvas.transitionDuration, config.canvas.transitionEasing]);
5002
5123
  useEffect7(() => {
5003
5124
  if (!isPush || !isOpen) return;
5004
5125
  const container = containerRef.current;
@@ -5019,19 +5140,31 @@ function ShadowCanvasOverlay({
5019
5140
  maxHeight: "100%",
5020
5141
  pointerEvents: "auto",
5021
5142
  opacity: isOpen ? 1 : 0,
5022
- transition: isOpen ? "transform 340ms cubic-bezier(0.16, 1, 0.3, 1), opacity 280ms ease-out" : "transform 280ms cubic-bezier(0.4, 0, 0.2, 1), opacity 200ms ease-in",
5143
+ transition: (() => {
5144
+ var _a3, _b2;
5145
+ const dur = (_a3 = config.canvas.transitionDuration) != null ? _a3 : "300ms";
5146
+ const ease = (_b2 = config.canvas.transitionEasing) != null ? _b2 : "cubic-bezier(0.16, 1, 0.3, 1)";
5147
+ return isOpen ? `transform ${dur} ${ease}, opacity ${dur} ease-out` : `transform ${dur} ${ease}, opacity ${dur} ease-in`;
5148
+ })(),
5023
5149
  color: "var(--sc-overlay-text-color)",
5024
- // Standard mode: no tint, just blur with a tight fade mask at the leading edge
5025
- // Focused mode: full frosted glass
5026
- background: isFocused ? "var(--sc-canvas-background)" : "var(--sc-canvas-background, transparent)",
5027
- backdropFilter: isFocused ? `${(_b = config.canvas.blur) != null ? _b : "blur(24px)"} saturate(1.2)` : "blur(6px)",
5028
- WebkitBackdropFilter: isFocused ? `${(_c = config.canvas.blur) != null ? _c : "blur(24px)"} saturate(1.2)` : "blur(6px)",
5029
- // Tight fade mask so blur cuts off sharply at the leading edge
5030
- ...!isFocused ? {
5031
- maskImage: isRight ? "linear-gradient(to right, transparent, black 6%)" : "linear-gradient(to left, transparent, black 6%)",
5032
- WebkitMaskImage: isRight ? "linear-gradient(to right, transparent, black 6%)" : "linear-gradient(to left, transparent, black 6%)"
5033
- } : {},
5034
- border: "none",
5150
+ background: "var(--sc-canvas-background)",
5151
+ // Standard mode: config blur only. Focused mode: config blur + saturate boost.
5152
+ ...(() => {
5153
+ var _a3;
5154
+ const blur = (_a3 = config.canvas.blur) != null ? _a3 : "blur(24px)";
5155
+ const filter = isFocused && blur !== "none" ? `${blur} saturate(1.2)` : blur;
5156
+ return { backdropFilter: filter, WebkitBackdropFilter: filter };
5157
+ })(),
5158
+ // Tight fade mask so blur cuts off sharply at the leading edge.
5159
+ // Disabled when a visible border is configured (mask would fade the border).
5160
+ ...(() => {
5161
+ var _a3;
5162
+ if (isFocused || canvasBorder && canvasBorder !== "none") return {};
5163
+ const fade = (_a3 = config.canvas.transitionFade) != null ? _a3 : "6%";
5164
+ const mask = isRight ? `linear-gradient(to right, transparent, black ${fade})` : `linear-gradient(to left, transparent, black ${fade})`;
5165
+ return { maskImage: mask, WebkitMaskImage: mask };
5166
+ })(),
5167
+ border: canvasBorder,
5035
5168
  borderRadius: "var(--sc-overlay-border-radius, 0)",
5036
5169
  boxShadow: "none",
5037
5170
  // Transform logic
@@ -5046,7 +5179,7 @@ function ShadowCanvasOverlay({
5046
5179
  pointerEvents: "none",
5047
5180
  padding: "0"
5048
5181
  };
5049
- const content = /* @__PURE__ */ jsx6(
5182
+ const content = /* @__PURE__ */ jsx7(
5050
5183
  "div",
5051
5184
  {
5052
5185
  "data-shadow-canvas-id": "overlay-root",
@@ -5058,7 +5191,7 @@ function ShadowCanvasOverlay({
5058
5191
  },
5059
5192
  children: /* @__PURE__ */ jsxs3("div", { style: wrapperStyle, children: [
5060
5193
  /* @__PURE__ */ jsxs3("div", { ref: containerRef, "data-shadow-canvas-id": "overlay-container", style: containerStyle, children: [
5061
- isFocused && canvasTitle && /* @__PURE__ */ jsx6("header", { style: { color: "white", padding: "1.5rem 1.5rem 0" }, children: /* @__PURE__ */ jsx6(
5194
+ isFocused && canvasTitle && /* @__PURE__ */ jsx7("header", { style: { color: "white", padding: "1.5rem 1.5rem 0" }, children: /* @__PURE__ */ jsx7(
5062
5195
  "p",
5063
5196
  {
5064
5197
  style: {
@@ -5071,7 +5204,7 @@ function ShadowCanvasOverlay({
5071
5204
  children: canvasTitle
5072
5205
  }
5073
5206
  ) }),
5074
- /* @__PURE__ */ jsx6("div", { style: { flex: 1, overflowY: "auto", padding: isFocused ? "0" : "1rem" }, children: isLoading ? /* @__PURE__ */ jsx6(
5207
+ /* @__PURE__ */ jsx7("div", { style: { flex: 1, overflowY: "auto", padding: isFocused ? "0" : "1rem" }, children: isLoading ? /* @__PURE__ */ jsx7(
5075
5208
  "div",
5076
5209
  {
5077
5210
  style: { color: "var(--sc-overlay-text-color)", padding: isFocused ? "1rem" : "0" },
@@ -5091,7 +5224,7 @@ function ShadowCanvasOverlay({
5091
5224
  }
5092
5225
  ) : isFocused ? (
5093
5226
  /* Focused Mode: Render first tile full size */
5094
- tiles.length > 0 ? /* @__PURE__ */ jsx6(
5227
+ tiles.length > 0 ? /* @__PURE__ */ jsx7(
5095
5228
  TileCard,
5096
5229
  {
5097
5230
  config: tiles[0],
@@ -5102,7 +5235,7 @@ function ShadowCanvasOverlay({
5102
5235
  ) : null
5103
5236
  ) : (
5104
5237
  /* Standard Mode: Stacked cards — widgets always visible */
5105
- /* @__PURE__ */ jsx6(
5238
+ /* @__PURE__ */ jsx7(
5106
5239
  "div",
5107
5240
  {
5108
5241
  style: {
@@ -5111,7 +5244,7 @@ function ShadowCanvasOverlay({
5111
5244
  gap: "0.75rem",
5112
5245
  width: "100%"
5113
5246
  },
5114
- children: tiles.map((tile) => /* @__PURE__ */ jsx6(
5247
+ children: tiles.map((tile) => /* @__PURE__ */ jsx7(
5115
5248
  TileCard,
5116
5249
  {
5117
5250
  config: tile,
@@ -5126,7 +5259,7 @@ function ShadowCanvasOverlay({
5126
5259
  ) }),
5127
5260
  footerSlot
5128
5261
  ] }),
5129
- /* @__PURE__ */ jsx6(
5262
+ /* @__PURE__ */ jsx7(
5130
5263
  "div",
5131
5264
  {
5132
5265
  onClick: toggle2,
@@ -5154,13 +5287,13 @@ function ShadowCanvasOverlay({
5154
5287
  zIndex: zIndex + 47
5155
5288
  },
5156
5289
  children: [
5157
- /* @__PURE__ */ jsx6(
5290
+ /* @__PURE__ */ jsx7(
5158
5291
  NotificationToastStack,
5159
5292
  {
5160
5293
  notifications,
5161
5294
  onDismiss: dismissNotification,
5162
5295
  onClickNotification: handleNotificationClick,
5163
- position: (_d = config.canvas.position) != null ? _d : "right"
5296
+ position: (_c = config.canvas.position) != null ? _c : "right"
5164
5297
  }
5165
5298
  ),
5166
5299
  /* @__PURE__ */ jsxs3(
@@ -5190,7 +5323,7 @@ function ShadowCanvasOverlay({
5190
5323
  padding: 0,
5191
5324
  border: "none",
5192
5325
  backgroundColor: "var(--sc-launcher-background)",
5193
- cursor: ((_e = dragRef.current) == null ? void 0 : _e.dragged) ? "grabbing" : "pointer",
5326
+ cursor: ((_d = dragRef.current) == null ? void 0 : _d.dragged) ? "grabbing" : "pointer",
5194
5327
  touchAction: "none"
5195
5328
  },
5196
5329
  onPointerDown: onLauncherPointerDown,
@@ -5224,11 +5357,11 @@ function ShadowCanvasOverlay({
5224
5357
  focusable: "false",
5225
5358
  style: { transition: "transform 200ms ease" },
5226
5359
  children: [
5227
- /* @__PURE__ */ jsx6("path", { d: "M18 6L6 18" }),
5228
- /* @__PURE__ */ jsx6("path", { d: "M6 6l12 12" })
5360
+ /* @__PURE__ */ jsx7("path", { d: "M18 6L6 18" }),
5361
+ /* @__PURE__ */ jsx7("path", { d: "M6 6l12 12" })
5229
5362
  ]
5230
5363
  }
5231
- ) : launcherIcon ? /* @__PURE__ */ jsx6(
5364
+ ) : launcherIcon ? /* @__PURE__ */ jsx7(
5232
5365
  "img",
5233
5366
  {
5234
5367
  src: launcherIcon,
@@ -5256,16 +5389,16 @@ function ShadowCanvasOverlay({
5256
5389
  focusable: "false",
5257
5390
  style: { transition: "transform 200ms ease" },
5258
5391
  children: [
5259
- /* @__PURE__ */ jsx6("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" }),
5260
- /* @__PURE__ */ jsx6("path", { d: "M5 3v4" }),
5261
- /* @__PURE__ */ jsx6("path", { d: "M3 5h4" }),
5262
- /* @__PURE__ */ jsx6("path", { d: "M19 17v4" }),
5263
- /* @__PURE__ */ jsx6("path", { d: "M17 19h4" })
5392
+ /* @__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" }),
5393
+ /* @__PURE__ */ jsx7("path", { d: "M5 3v4" }),
5394
+ /* @__PURE__ */ jsx7("path", { d: "M3 5h4" }),
5395
+ /* @__PURE__ */ jsx7("path", { d: "M19 17v4" }),
5396
+ /* @__PURE__ */ jsx7("path", { d: "M17 19h4" })
5264
5397
  ]
5265
5398
  }
5266
5399
  ),
5267
5400
  !isOpen && notifications.length > 0 && /* @__PURE__ */ jsxs3("div", { style: { position: "absolute", top: -2, right: -2, pointerEvents: "none" }, children: [
5268
- /* @__PURE__ */ jsx6(
5401
+ /* @__PURE__ */ jsx7(
5269
5402
  "span",
5270
5403
  {
5271
5404
  className: "syntro-badge-ping",
@@ -5277,7 +5410,7 @@ function ShadowCanvasOverlay({
5277
5410
  }
5278
5411
  }
5279
5412
  ),
5280
- /* @__PURE__ */ jsx6(
5413
+ /* @__PURE__ */ jsx7(
5281
5414
  "span",
5282
5415
  {
5283
5416
  className: "syntro-badge-glow",
@@ -5288,7 +5421,7 @@ function ShadowCanvasOverlay({
5288
5421
  }
5289
5422
  }
5290
5423
  ),
5291
- /* @__PURE__ */ jsx6(
5424
+ /* @__PURE__ */ jsx7(
5292
5425
  "span",
5293
5426
  {
5294
5427
  className: "syntro-badge-bounce",
@@ -5317,12 +5450,12 @@ function ShadowCanvasOverlay({
5317
5450
  ),
5318
5451
  portalRoot
5319
5452
  ),
5320
- isOpen ? createPortal(content, portalRoot) : null
5453
+ createPortal(content, portalRoot)
5321
5454
  ] });
5322
5455
  }
5323
5456
 
5324
5457
  // src/hooks/useShadowCanvasConfig.ts
5325
- import { useCallback as useCallback5, useEffect as useEffect8, useMemo as useMemo5, useRef as useRef6, useState as useState6 } from "react";
5458
+ import { useCallback as useCallback5, useEffect as useEffect8, useMemo as useMemo6, useRef as useRef6, useState as useState6 } from "react";
5326
5459
  var sortTiles = (tiles) => [...tiles].sort((a, b) => {
5327
5460
  var _a2, _b;
5328
5461
  return ((_a2 = b.priority) != null ? _a2 : 0) - ((_b = a.priority) != null ? _b : 0);
@@ -5340,11 +5473,23 @@ function useShadowCanvasConfig({
5340
5473
  isLoading: true
5341
5474
  });
5342
5475
  const prevActionsJsonRef = useRef6("[]");
5476
+ const rawConfigRef = useRef6(null);
5477
+ const refilter = useCallback5(async () => {
5478
+ const raw = rawConfigRef.current;
5479
+ if (!raw || !runtime3) return;
5480
+ let tiles = raw.tiles || [];
5481
+ tiles = await runtime3.filterTiles(tiles);
5482
+ if (experiments) {
5483
+ tiles = tiles.filter((tile) => experiments.shouldRenderRectangle(tile));
5484
+ }
5485
+ setState((prev) => ({ ...prev, tiles: sortTiles(tiles) }));
5486
+ }, [runtime3, experiments]);
5343
5487
  const load = useCallback5(async () => {
5344
5488
  try {
5345
5489
  setState((prev) => ({ ...prev, isLoading: true, error: void 0 }));
5346
5490
  const response = await fetcher();
5347
5491
  debug("SmartCanvas Config", "Raw config response", response);
5492
+ rawConfigRef.current = response;
5348
5493
  let tiles = response.tiles || [];
5349
5494
  if (runtime3) {
5350
5495
  tiles = await runtime3.filterTiles(tiles);
@@ -5387,6 +5532,18 @@ function useShadowCanvasConfig({
5387
5532
  return experiments.onFeaturesChanged(() => load());
5388
5533
  }
5389
5534
  }, [load, experiments, pageUrl]);
5535
+ useEffect8(() => {
5536
+ if (!(runtime3 == null ? void 0 : runtime3.accumulator)) return;
5537
+ return runtime3.accumulator.subscribe(() => {
5538
+ refilter();
5539
+ });
5540
+ }, [runtime3, refilter]);
5541
+ useEffect8(() => {
5542
+ if (!(runtime3 == null ? void 0 : runtime3.context)) return;
5543
+ return runtime3.context.subscribe(() => {
5544
+ refilter();
5545
+ });
5546
+ }, [runtime3, refilter]);
5390
5547
  useEffect8(() => {
5391
5548
  if (!pollIntervalMs) return;
5392
5549
  const id = setInterval(() => {
@@ -5394,12 +5551,12 @@ function useShadowCanvasConfig({
5394
5551
  }, pollIntervalMs);
5395
5552
  return () => clearInterval(id);
5396
5553
  }, [load, pollIntervalMs]);
5397
- return useMemo5(() => state, [state]);
5554
+ return useMemo6(() => state, [state]);
5398
5555
  }
5399
5556
 
5400
5557
  // src/SmartCanvasApp.tsx
5401
- import { useEffect as useEffect9, useMemo as useMemo6, useRef as useRef7, useState as useState7 } from "react";
5402
- import { jsx as jsx7 } from "react/jsx-runtime";
5558
+ import { useEffect as useEffect9, useMemo as useMemo7, useRef as useRef7, useState as useState7 } from "react";
5559
+ import { jsx as jsx8 } from "react/jsx-runtime";
5403
5560
  function SmartCanvasApp({
5404
5561
  controller,
5405
5562
  fetcher,
@@ -5422,7 +5579,7 @@ function SmartCanvasApp({
5422
5579
  workspaceTheme
5423
5580
  }) {
5424
5581
  if (runtime3) {
5425
- return /* @__PURE__ */ jsx7(RuntimeProvider, { runtime: runtime3, children: /* @__PURE__ */ jsx7(
5582
+ return /* @__PURE__ */ jsx8(RuntimeProvider, { runtime: runtime3, children: /* @__PURE__ */ jsx8(
5426
5583
  SmartCanvasAppInner,
5427
5584
  {
5428
5585
  controller,
@@ -5447,7 +5604,7 @@ function SmartCanvasApp({
5447
5604
  }
5448
5605
  ) });
5449
5606
  }
5450
- return /* @__PURE__ */ jsx7(
5607
+ return /* @__PURE__ */ jsx8(
5451
5608
  SmartCanvasAppInner,
5452
5609
  {
5453
5610
  controller,
@@ -5492,7 +5649,7 @@ function SmartCanvasAppInner({
5492
5649
  initialBatchHandle,
5493
5650
  workspaceTheme
5494
5651
  }) {
5495
- var _a2, _b, _c, _d, _e, _f;
5652
+ var _a2, _b, _c, _d, _e, _f, _g;
5496
5653
  const [open, setOpen] = useState7(controller.getState().open);
5497
5654
  const pageContext = usePageContext();
5498
5655
  const [localUrl, setLocalUrl] = useState7(
@@ -5522,7 +5679,7 @@ function SmartCanvasAppInner({
5522
5679
  history.replaceState = originalReplaceState;
5523
5680
  };
5524
5681
  }, [runtime3]);
5525
- const derivedFetcher = useMemo6(() => {
5682
+ const derivedFetcher = useMemo7(() => {
5526
5683
  if (fetcher) return fetcher;
5527
5684
  return createCanvasConfigFetcher({
5528
5685
  configUri,
@@ -5547,6 +5704,7 @@ function SmartCanvasAppInner({
5547
5704
  }, [controller, hasContent, configState.isLoading]);
5548
5705
  const batchHandleRef = useRef7(initialBatchHandle != null ? initialBatchHandle : null);
5549
5706
  const adoptedInitialRef = useRef7(!!initialBatchHandle);
5707
+ const runVersionRef = useRef7(0);
5550
5708
  useEffect9(() => {
5551
5709
  if (!(runtime3 == null ? void 0 : runtime3.actions)) return;
5552
5710
  if (adoptedInitialRef.current) {
@@ -5555,7 +5713,8 @@ function SmartCanvasAppInner({
5555
5713
  }
5556
5714
  return;
5557
5715
  }
5558
- let cancelled = false;
5716
+ const version = ++runVersionRef.current;
5717
+ const stale = () => version !== runVersionRef.current;
5559
5718
  const run = async () => {
5560
5719
  if (batchHandleRef.current) {
5561
5720
  try {
@@ -5565,17 +5724,17 @@ function SmartCanvasAppInner({
5565
5724
  }
5566
5725
  batchHandleRef.current = null;
5567
5726
  }
5568
- if (cancelled) return;
5727
+ if (stale()) return;
5569
5728
  if (configState.actions.length > 0) {
5570
5729
  try {
5571
5730
  const handle = await runtime3.actions.applyBatch(configState.actions);
5572
- if (cancelled) {
5731
+ if (stale()) {
5573
5732
  await handle.revertAll();
5574
5733
  } else {
5575
5734
  batchHandleRef.current = handle;
5576
5735
  }
5577
5736
  } catch (err) {
5578
- if (!cancelled) {
5737
+ if (!stale()) {
5579
5738
  console.error("[SmartCanvasApp] Failed to apply actions:", err);
5580
5739
  }
5581
5740
  }
@@ -5583,7 +5742,6 @@ function SmartCanvasAppInner({
5583
5742
  };
5584
5743
  run();
5585
5744
  return () => {
5586
- cancelled = true;
5587
5745
  if (batchHandleRef.current) {
5588
5746
  batchHandleRef.current.revertAll().catch((err) => {
5589
5747
  console.error("[SmartCanvasApp] Failed to revert actions on cleanup:", err);
@@ -5604,13 +5762,13 @@ function SmartCanvasAppInner({
5604
5762
  if (!configState.isLoading && !hasContent) {
5605
5763
  return null;
5606
5764
  }
5607
- return /* @__PURE__ */ jsx7(
5765
+ return /* @__PURE__ */ jsx8(
5608
5766
  ThemeProvider,
5609
5767
  {
5610
5768
  themeConfig,
5611
5769
  workspaceTheme,
5612
5770
  shadowRoot,
5613
- children: /* @__PURE__ */ jsx7(
5771
+ children: /* @__PURE__ */ jsx8(
5614
5772
  ShadowCanvasOverlay,
5615
5773
  {
5616
5774
  tiles: configState.tiles,
@@ -5619,9 +5777,10 @@ function SmartCanvasAppInner({
5619
5777
  canvasTitle: configState.canvasTitle,
5620
5778
  telemetry,
5621
5779
  launcherLabel: launcherLabel != null ? launcherLabel : (_b = configState.launcher) == null ? void 0 : _b.label,
5622
- launcherAnimate: (_c = configState.launcher) == null ? void 0 : _c.animate,
5623
- launcherAnimationStyle: (_d = configState.launcher) == null ? void 0 : _d.animationStyle,
5624
- notificationCount: (_f = (_e = configState.launcher) == null ? void 0 : _e.notificationCount) != null ? _f : configState.tiles.length,
5780
+ launcherIcon: (_c = configState.launcher) == null ? void 0 : _c.icon,
5781
+ launcherAnimate: (_d = configState.launcher) == null ? void 0 : _d.animate,
5782
+ launcherAnimationStyle: (_e = configState.launcher) == null ? void 0 : _e.animationStyle,
5783
+ notificationCount: (_g = (_f = configState.launcher) == null ? void 0 : _f.notificationCount) != null ? _g : configState.tiles.length,
5625
5784
  footerSlot,
5626
5785
  isOpen: open,
5627
5786
  onToggle: () => controller.toggle(),
@@ -5634,7 +5793,7 @@ function SmartCanvasAppInner({
5634
5793
 
5635
5794
  // src/SmartCanvasElement.tsx
5636
5795
  import { createRoot as createRoot2 } from "react-dom/client";
5637
- import { jsx as jsx8 } from "react/jsx-runtime";
5796
+ import { jsx as jsx9 } from "react/jsx-runtime";
5638
5797
  var TAG_NAME = "smart-canvas";
5639
5798
  var BASE_CSS = `
5640
5799
  :host {
@@ -5735,13 +5894,13 @@ var SmartCanvasElement = class extends HTMLElement {
5735
5894
  __privateSet(this, _root, createRoot2(__privateGet(this, _mount)));
5736
5895
  }
5737
5896
  __privateGet(this, _root).render(
5738
- /* @__PURE__ */ jsx8(
5897
+ /* @__PURE__ */ jsx9(
5739
5898
  ShadowRootProvider,
5740
5899
  {
5741
5900
  shadowRoot: __privateGet(this, _shadow),
5742
5901
  portalRoot: __privateGet(this, _portalRoot),
5743
5902
  overlayContainer: __privateGet(this, _overlayContainer),
5744
- children: /* @__PURE__ */ jsx8(SmartCanvasApp, { ...__privateGet(this, _lastAppProps), controller: __privateGet(this, _controller), canvasHost: this })
5903
+ children: /* @__PURE__ */ jsx9(SmartCanvasApp, { ...__privateGet(this, _lastAppProps), controller: __privateGet(this, _controller), canvasHost: this })
5745
5904
  }
5746
5905
  )
5747
5906
  );
@@ -6007,6 +6166,9 @@ function injectBaseStyles(target) {
6007
6166
  --syntro-border: var(--sc-overlay-border, #2b333f);
6008
6167
  --syntro-tooltip-bg: var(--syntro-surface);
6009
6168
  --syntro-tooltip-fg: var(--syntro-fg);
6169
+ --syntro-tooltip-title-color: var(--sc-overlay-title-color, var(--syntro-fg));
6170
+ --syntro-tooltip-arrow-bg: var(--sc-overlay-arrow-color, var(--syntro-tooltip-bg));
6171
+ --syntro-tooltip-arrow-size: var(--sc-overlay-arrow-size, 8px);
6010
6172
  --syntro-tooltip-radius: var(--syntro-radius);
6011
6173
  --syntro-tooltip-padding: 12px 16px;
6012
6174
  --syntro-tooltip-shadow: var(--syntro-shadow);
@@ -6033,14 +6195,13 @@ function injectBaseStyles(target) {
6033
6195
  transform 200ms cubic-bezier(0.16, 1, 0.3, 1);
6034
6196
  }
6035
6197
 
6036
- /* Tooltip arrow */
6198
+ /* Tooltip arrow \u2014 triangle via clip-path (square box so rotation is symmetric) */
6037
6199
  .syntro-tooltip-arrow {
6038
6200
  position: absolute;
6039
- width: 8px;
6040
- height: 8px;
6041
- background: inherit;
6042
- transform: rotate(45deg);
6043
- z-index: -1;
6201
+ width: var(--syntro-tooltip-arrow-size);
6202
+ height: var(--syntro-tooltip-arrow-size);
6203
+ background: var(--syntro-tooltip-arrow-bg);
6204
+ clip-path: polygon(0 0, 100% 0, 50% 100%);
6044
6205
  }
6045
6206
 
6046
6207
  /* Tooltip content */
@@ -6048,6 +6209,7 @@ function injectBaseStyles(target) {
6048
6209
  font-weight: 600;
6049
6210
  font-size: 15px;
6050
6211
  margin-bottom: 6px;
6212
+ color: var(--syntro-tooltip-title-color);
6051
6213
  }
6052
6214
 
6053
6215
  .syntro-tt-body {
@@ -8558,7 +8720,7 @@ function evaluateCondition(condition, evalContext) {
8558
8720
  switch (condition.type) {
8559
8721
  case "page_url": {
8560
8722
  const { url } = condition;
8561
- const currentUrl = context.page.url;
8723
+ const currentUrl = context.page.url.split("?")[0].split("#")[0];
8562
8724
  const pattern = url.replace(/\*\*/g, "\0GLOBSTAR\0").replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, "[^/]*").replace(/\0GLOBSTAR\0/g, ".*");
8563
8725
  const regex = new RegExp(`^${pattern}$`);
8564
8726
  return regex.test(currentUrl);
@@ -10234,7 +10396,7 @@ function matchesRouteFilter(url, filter) {
10234
10396
  function matchRoutePattern(pathname, pattern) {
10235
10397
  const normalizedPattern = pattern.replace(/\/$/, "") || "/";
10236
10398
  if (pathname === normalizedPattern) return true;
10237
- const regexPattern = normalizedPattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*").replace(/:[^/]+/g, "[^/]+");
10399
+ const regexPattern = normalizedPattern.replace(/\*\*/g, "\0GLOBSTAR\0").replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, "[^/]*").replace(/\0GLOBSTAR\0/g, ".*").replace(/:[^/]+/g, "[^/]+");
10238
10400
  const regex = new RegExp(`^${regexPattern}$`);
10239
10401
  return regex.test(pathname);
10240
10402
  }
@@ -10327,6 +10489,7 @@ function createSmartCanvasRuntime(options = {}) {
10327
10489
  return decisionEngine.evaluateSync(strategy, context.get());
10328
10490
  },
10329
10491
  async filterTiles(tiles) {
10492
+ var _a3, _b2;
10330
10493
  const currentUrl = context.get().page.url;
10331
10494
  const results = [];
10332
10495
  for (const tile of tiles) {
@@ -10338,14 +10501,20 @@ function createSmartCanvasRuntime(options = {}) {
10338
10501
  if (!matchesRouteFilter(currentUrl, activation.routes)) {
10339
10502
  continue;
10340
10503
  }
10341
- if (!activation.strategy) {
10342
- results.push(tile);
10343
- continue;
10344
- }
10345
- const result = await this.evaluate(activation.strategy);
10346
- if (result.value) {
10347
- results.push(tile);
10504
+ if (activation.onlyIfPopulated) {
10505
+ const actions2 = (_b2 = (_a3 = tile.props) == null ? void 0 : _a3.actions) != null ? _b2 : [];
10506
+ if (actions2.length > 0) {
10507
+ const hasVisible = actions2.some((a) => {
10508
+ if (!a.triggerWhen) return true;
10509
+ return decisionEngine.evaluateSync(
10510
+ a.triggerWhen,
10511
+ context.get()
10512
+ ).value;
10513
+ });
10514
+ if (!hasVisible) continue;
10515
+ }
10348
10516
  }
10517
+ results.push(tile);
10349
10518
  }
10350
10519
  return results;
10351
10520
  },
@@ -11118,4 +11287,4 @@ export {
11118
11287
  encodeToken,
11119
11288
  Syntro
11120
11289
  };
11121
- //# sourceMappingURL=chunk-FFIHKDHW.js.map
11290
+ //# sourceMappingURL=chunk-2WDY7YGN.js.map