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

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.
@@ -12860,6 +12860,7 @@ var SyntrologieSDK = (() => {
12860
12860
  TooltipZ: () => TooltipZ,
12861
12861
  TourStepForSchemaZ: () => TourStepForSchemaZ,
12862
12862
  TourZ: () => TourZ,
12863
+ TriggerWhenZ: () => TriggerWhenZ,
12863
12864
  ViewportConditionZ: () => ViewportConditionZ,
12864
12865
  ViewportContextZ: () => ViewportContextZ,
12865
12866
  WaitZ: () => WaitZ,
@@ -12950,7 +12951,7 @@ var SyntrologieSDK = (() => {
12950
12951
  validateStrategy: () => validateStrategy,
12951
12952
  widgetRegistry: () => widgetRegistry
12952
12953
  });
12953
- var import_react17 = __toESM(require_react(), 1);
12954
+ var import_react19 = __toESM(require_react(), 1);
12954
12955
  var import_react_dom3 = __toESM(require_react_dom(), 1);
12955
12956
  var ReactDOMClient = __toESM(require_client(), 1);
12956
12957
 
@@ -13726,7 +13727,7 @@ var SyntrologieSDK = (() => {
13726
13727
  };
13727
13728
 
13728
13729
  // ../adaptives/adaptive-overlays/dist/celebrations/index.js
13729
- var DEFAULT_COLORS2 = [
13730
+ var FALLBACK_COLORS = [
13730
13731
  "#ff0000",
13731
13732
  "#00ff00",
13732
13733
  "#0000ff",
@@ -13736,6 +13737,21 @@ var SyntrologieSDK = (() => {
13736
13737
  "#ff8800",
13737
13738
  "#8800ff"
13738
13739
  ];
13740
+ function buildThemePalette(primary, hover) {
13741
+ return [primary, hover, `${primary}cc`, `${hover}cc`, "#ffffff", `${primary}80`];
13742
+ }
13743
+ function readThemeColors(overlayRoot) {
13744
+ try {
13745
+ const styles2 = getComputedStyle(overlayRoot);
13746
+ const primary = styles2.getPropertyValue("--sc-color-primary")?.trim();
13747
+ const hover = styles2.getPropertyValue("--sc-color-primary-hover")?.trim();
13748
+ if (primary?.startsWith("#") && primary.length >= 7) {
13749
+ return buildThemePalette(primary, hover || primary);
13750
+ }
13751
+ } catch {
13752
+ }
13753
+ return null;
13754
+ }
13739
13755
  var effectRegistry = /* @__PURE__ */ new Map([
13740
13756
  ["confetti", confettiEffect],
13741
13757
  ["fireworks", fireworksEffect],
@@ -13749,10 +13765,11 @@ var SyntrologieSDK = (() => {
13749
13765
  return { cleanup: () => {
13750
13766
  } };
13751
13767
  }
13768
+ const colors = action.colors ?? readThemeColors(context.overlayRoot) ?? FALLBACK_COLORS;
13752
13769
  const config = {
13753
13770
  duration: action.duration ?? 3e3,
13754
13771
  intensity: action.intensity ?? "medium",
13755
- colors: action.colors ?? DEFAULT_COLORS2,
13772
+ colors,
13756
13773
  props: action.props
13757
13774
  };
13758
13775
  const engine = new CelebrationEngine();
@@ -14622,6 +14639,13 @@ var SyntrologieSDK = (() => {
14622
14639
  }
14623
14640
 
14624
14641
  // ../adaptives/adaptive-overlays/dist/modal.js
14642
+ var V = {
14643
+ bg: "var(--sc-overlay-background, #ffffff)",
14644
+ title: "var(--sc-overlay-title-color, var(--sc-overlay-text-color, #111827))",
14645
+ text: "var(--sc-overlay-text-color, #4b5563)",
14646
+ accent: "var(--sc-color-primary, #4f46e5)",
14647
+ radius: "var(--sc-border-radius, 12px)"
14648
+ };
14625
14649
  var executeModal = async (action, context) => {
14626
14650
  const { content, size: size2 = "md", blocking = false, scrim, dismiss, ctaButtons } = action;
14627
14651
  const scrimEl = document.createElement("div");
@@ -14647,8 +14671,8 @@ var SyntrologieSDK = (() => {
14647
14671
  transform: translate(-50%, -50%) scale(0.95);
14648
14672
  max-width: ${sizeMap[size2]};
14649
14673
  width: 90%;
14650
- background: ${base.white};
14651
- border-radius: 12px;
14674
+ background: ${V.bg};
14675
+ border-radius: ${V.radius};
14652
14676
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
14653
14677
  z-index: 2147483646;
14654
14678
  opacity: 0;
@@ -14657,9 +14681,9 @@ var SyntrologieSDK = (() => {
14657
14681
  `;
14658
14682
  let html2 = "";
14659
14683
  if (content.title) {
14660
- html2 += `<h2 class="syntro-modal-title" style="margin: 0 0 12px 0; font-size: 18px; font-weight: 600; color: #111827;">${sanitizeHtml2(content.title)}</h2>`;
14684
+ html2 += `<h2 class="syntro-modal-title" style="margin: 0 0 12px 0; font-size: 18px; font-weight: 600; color: ${V.title};">${sanitizeHtml2(content.title)}</h2>`;
14661
14685
  }
14662
- html2 += `<div class="syntro-modal-body" style="color: #4b5563; line-height: 1.5;">${sanitizeHtml2(content.body)}</div>`;
14686
+ html2 += `<div class="syntro-modal-body" style="color: ${V.text}; line-height: 1.5;">${sanitizeHtml2(content.body)}</div>`;
14663
14687
  if (dismiss?.closeButton !== false) {
14664
14688
  html2 += `
14665
14689
  <button class="syntro-modal-close" data-syntro-action="dismiss" style="
@@ -14670,7 +14694,8 @@ var SyntrologieSDK = (() => {
14670
14694
  border: none;
14671
14695
  cursor: pointer;
14672
14696
  padding: 4px;
14673
- color: #6b7280;
14697
+ color: ${V.text};
14698
+ opacity: 0.6;
14674
14699
  " aria-label="Close">
14675
14700
  <svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
14676
14701
  <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"/>
@@ -14693,7 +14718,7 @@ var SyntrologieSDK = (() => {
14693
14718
  font-weight: 500;
14694
14719
  cursor: pointer;
14695
14720
  transition: background 150ms ease;
14696
- ${isPrimary ? "background: #4f46e5; color: white; border: none;" : "background: white; color: #374151; border: 1px solid #d1d5db;"}
14721
+ ${isPrimary ? `background: ${V.accent}; color: white; border: none;` : `background: transparent; color: ${V.accent}; border: 1px solid currentColor; opacity: 0.7;`}
14697
14722
  "
14698
14723
  >
14699
14724
  ${sanitizeHtml2(btn.label)}
@@ -17056,7 +17081,7 @@ var SyntrologieSDK = (() => {
17056
17081
  executors: executors2,
17057
17082
  widgets: [
17058
17083
  {
17059
- id: "workflow:tracker",
17084
+ id: "adaptive-overlays:workflow-tracker",
17060
17085
  component: WorkflowMountableWidget,
17061
17086
  metadata: {
17062
17087
  name: "Workflow Tracker",
@@ -18093,7 +18118,7 @@ var SyntrologieSDK = (() => {
18093
18118
  }
18094
18119
  var baseStyles = {
18095
18120
  container: {
18096
- fontFamily: "system-ui, -apple-system, sans-serif",
18121
+ fontFamily: "var(--sc-font-family, system-ui, -apple-system, sans-serif)",
18097
18122
  maxWidth: "800px",
18098
18123
  margin: "0 auto"
18099
18124
  },
@@ -18106,7 +18131,9 @@ var SyntrologieSDK = (() => {
18106
18131
  borderRadius: "8px",
18107
18132
  fontSize: "14px",
18108
18133
  outline: "none",
18109
- transition: "border-color 0.15s ease"
18134
+ transition: "border-color 0.15s ease",
18135
+ backgroundColor: "var(--sc-content-search-background)",
18136
+ color: "var(--sc-content-search-color)"
18110
18137
  },
18111
18138
  accordion: {
18112
18139
  display: "flex",
@@ -18132,8 +18159,9 @@ var SyntrologieSDK = (() => {
18132
18159
  transition: "background-color 0.15s ease"
18133
18160
  },
18134
18161
  chevron: {
18135
- fontSize: "18px",
18136
- transition: "transform 0.2s ease"
18162
+ fontSize: "20px",
18163
+ transition: "transform 0.2s ease",
18164
+ color: "var(--sc-content-chevron-color, currentColor)"
18137
18165
  },
18138
18166
  answer: {
18139
18167
  padding: "var(--sc-content-body-padding, 0 16px 12px 16px)",
@@ -18200,9 +18228,7 @@ var SyntrologieSDK = (() => {
18200
18228
  color: "inherit"
18201
18229
  },
18202
18230
  searchInput: {
18203
- backgroundColor: slateGrey[12],
18204
- border: `1px solid ${slateGrey[11]}`,
18205
- color: slateGrey[1]
18231
+ border: `1px solid ${slateGrey[11]}`
18206
18232
  },
18207
18233
  item: {
18208
18234
  backgroundColor: "var(--sc-content-background)",
@@ -18241,9 +18267,7 @@ var SyntrologieSDK = (() => {
18241
18267
  color: "inherit"
18242
18268
  },
18243
18269
  searchInput: {
18244
- backgroundColor: slateGrey[3],
18245
- border: `1px solid ${slateGrey[5]}`,
18246
- color: slateGrey[12]
18270
+ border: `1px solid ${slateGrey[5]}`
18247
18271
  },
18248
18272
  item: {
18249
18273
  backgroundColor: "var(--sc-content-background)",
@@ -18277,7 +18301,7 @@ var SyntrologieSDK = (() => {
18277
18301
  }
18278
18302
  }
18279
18303
  };
18280
- function FAQItem({ item, isExpanded, isHighlighted, onToggle, theme, feedbackConfig, feedbackValue, onFeedback }) {
18304
+ function FAQItem({ item, isExpanded, isHighlighted, isLast, onToggle, theme, feedbackConfig, feedbackValue, onFeedback }) {
18281
18305
  const [isHovered, setIsHovered] = (0, import_react4.useState)(false);
18282
18306
  const colors = themeStyles[theme];
18283
18307
  const { question, answer } = item.config;
@@ -18288,7 +18312,8 @@ var SyntrologieSDK = (() => {
18288
18312
  ...isHighlighted ? {
18289
18313
  boxShadow: "0 0 0 2px #6366f1, 0 0 12px rgba(99, 102, 241, 0.4)",
18290
18314
  transition: "box-shadow 0.3s ease"
18291
- } : {}
18315
+ } : {},
18316
+ ...!isLast ? { borderBottom: "var(--sc-content-item-divider, none)" } : {}
18292
18317
  };
18293
18318
  const questionStyle = {
18294
18319
  ...baseStyles.question,
@@ -18297,7 +18322,7 @@ var SyntrologieSDK = (() => {
18297
18322
  };
18298
18323
  const chevronStyle = {
18299
18324
  ...baseStyles.chevron,
18300
- transform: isExpanded ? "rotate(180deg)" : "rotate(0deg)"
18325
+ transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)"
18301
18326
  };
18302
18327
  const answerStyle = {
18303
18328
  ...baseStyles.answer,
@@ -18309,7 +18334,7 @@ var SyntrologieSDK = (() => {
18309
18334
  ...baseStyles.feedback,
18310
18335
  ...colors.feedbackPrompt
18311
18336
  };
18312
- return (0, import_jsx_runtime4.jsxs)("div", { style: itemStyle, "data-faq-item-id": item.config.id, children: [(0, import_jsx_runtime4.jsxs)("button", { type: "button", style: questionStyle, onClick: onToggle, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), "aria-expanded": isExpanded, children: [(0, import_jsx_runtime4.jsx)("span", { children: question }), (0, import_jsx_runtime4.jsx)("span", { style: chevronStyle, children: "\u25BC" })] }), (0, import_jsx_runtime4.jsxs)("div", { style: answerStyle, "aria-hidden": !isExpanded, children: [renderAnswer(answer), isExpanded && feedbackConfig && (0, import_jsx_runtime4.jsxs)("div", { style: feedbackStyle, children: [(0, import_jsx_runtime4.jsx)("span", { children: getFeedbackPrompt(feedbackConfig) }), (0, import_jsx_runtime4.jsx)("button", { type: "button", style: {
18337
+ return (0, import_jsx_runtime4.jsxs)("div", { style: itemStyle, "data-faq-item-id": item.config.id, children: [(0, import_jsx_runtime4.jsxs)("button", { type: "button", style: questionStyle, onClick: onToggle, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), "aria-expanded": isExpanded, children: [(0, import_jsx_runtime4.jsx)("span", { children: question }), (0, import_jsx_runtime4.jsx)("span", { style: chevronStyle, children: "\u203A" })] }), (0, import_jsx_runtime4.jsxs)("div", { style: answerStyle, "aria-hidden": !isExpanded, children: [renderAnswer(answer), isExpanded && feedbackConfig && (0, import_jsx_runtime4.jsxs)("div", { style: feedbackStyle, children: [(0, import_jsx_runtime4.jsx)("span", { children: getFeedbackPrompt(feedbackConfig) }), (0, import_jsx_runtime4.jsx)("button", { type: "button", style: {
18313
18338
  ...baseStyles.feedbackButton,
18314
18339
  ...feedbackValue === "up" ? baseStyles.feedbackButtonSelected : {}
18315
18340
  }, "aria-label": "Thumbs up", onClick: () => onFeedback(item.config.id, question, "up"), children: "\u{1F44D}" }), (0, import_jsx_runtime4.jsx)("button", { type: "button", style: {
@@ -18490,11 +18515,11 @@ var SyntrologieSDK = (() => {
18490
18515
  ...baseStyles.categoryHeader,
18491
18516
  ...themeStyles[resolvedTheme].categoryHeader
18492
18517
  };
18493
- const renderItems = (items) => items.map((q2) => (0, import_jsx_runtime4.jsx)(FAQItem, { item: q2, isExpanded: expandedIds.has(q2.config.id), isHighlighted: highlightId === q2.config.id, onToggle: () => handleToggle(q2.config.id), theme: resolvedTheme, feedbackConfig, feedbackValue: feedbackState.get(q2.config.id), onFeedback: handleFeedback }, q2.config.id));
18518
+ const renderItems = (items) => items.map((q2, index2) => (0, import_jsx_runtime4.jsx)(FAQItem, { item: q2, isExpanded: expandedIds.has(q2.config.id), isHighlighted: highlightId === q2.config.id, isLast: index2 === items.length - 1, onToggle: () => handleToggle(q2.config.id), theme: resolvedTheme, feedbackConfig, feedbackValue: feedbackState.get(q2.config.id), onFeedback: handleFeedback }, q2.config.id));
18494
18519
  if (visibleQuestions.length === 0) {
18495
18520
  return (0, import_jsx_runtime4.jsx)("div", { style: containerStyle, "data-adaptive-id": instanceId, "data-adaptive-type": "adaptive-faq", children: (0, import_jsx_runtime4.jsx)("div", { style: emptyStateStyle, children: "No FAQ questions available." }) });
18496
18521
  }
18497
- return (0, import_jsx_runtime4.jsxs)("div", { style: containerStyle, "data-adaptive-id": instanceId, "data-adaptive-type": "adaptive-faq", children: [config.searchable && (0, import_jsx_runtime4.jsx)("div", { style: baseStyles.searchWrapper, children: (0, import_jsx_runtime4.jsx)("input", { type: "text", placeholder: "Search questions...", value: searchQuery, onChange: (e2) => setSearchQuery(e2.target.value), style: searchInputStyle }) }), (0, import_jsx_runtime4.jsx)("div", { style: baseStyles.accordion, children: hasCategories ? Array.from(categoryGroups.entries()).map(([category, items]) => (0, import_jsx_runtime4.jsxs)(import_react4.default.Fragment, { children: [category && (0, import_jsx_runtime4.jsx)("div", { style: categoryHeaderStyle, "data-category-header": category, children: category }), renderItems(items)] }, category ?? "__ungrouped")) : renderItems(filteredQuestions) }), config.searchable && filteredQuestions.length === 0 && searchQuery && (0, import_jsx_runtime4.jsxs)("div", { style: { ...baseStyles.noResults, ...themeStyles[resolvedTheme].emptyState }, children: ['No questions found matching "', searchQuery, '"'] })] });
18522
+ return (0, import_jsx_runtime4.jsxs)("div", { style: containerStyle, "data-adaptive-id": instanceId, "data-adaptive-type": "adaptive-faq", children: [config.searchable && (0, import_jsx_runtime4.jsxs)("div", { style: baseStyles.searchWrapper, children: [(0, import_jsx_runtime4.jsx)("style", { children: `[data-adaptive-id="${instanceId}"] input::placeholder { color: var(--sc-content-search-color, inherit); opacity: 0.7; }` }), (0, import_jsx_runtime4.jsx)("input", { type: "text", placeholder: "Search questions...", value: searchQuery, onChange: (e2) => setSearchQuery(e2.target.value), style: searchInputStyle })] }), (0, import_jsx_runtime4.jsx)("div", { style: baseStyles.accordion, children: hasCategories ? Array.from(categoryGroups.entries()).map(([category, items]) => (0, import_jsx_runtime4.jsxs)(import_react4.default.Fragment, { children: [category && (0, import_jsx_runtime4.jsx)("div", { style: categoryHeaderStyle, "data-category-header": category, children: category }), renderItems(items)] }, category ?? "__ungrouped")) : renderItems(filteredQuestions) }), config.searchable && filteredQuestions.length === 0 && searchQuery && (0, import_jsx_runtime4.jsxs)("div", { style: { ...baseStyles.noResults, ...themeStyles[resolvedTheme].emptyState }, children: ['No questions found matching "', searchQuery, '"'] })] });
18498
18523
  }
18499
18524
  var FAQMountableWidget = {
18500
18525
  mount(container, config) {
@@ -18552,7 +18577,8 @@ var SyntrologieSDK = (() => {
18552
18577
  metadata: {
18553
18578
  name: "FAQ Accordion",
18554
18579
  description: "Collapsible Q&A accordion with search, categories, and feedback",
18555
- icon: "\u2753"
18580
+ icon: "\u2753",
18581
+ subtitle: "Curated just for you."
18556
18582
  }
18557
18583
  }
18558
18584
  ],
@@ -19218,7 +19244,7 @@ var SyntrologieSDK = (() => {
19218
19244
  }
19219
19245
 
19220
19246
  // src/version.ts
19221
- var SDK_VERSION = "2.4.0-canary.23";
19247
+ var SDK_VERSION = "2.4.0-canary.24";
19222
19248
 
19223
19249
  // src/types.ts
19224
19250
  var SDK_SCHEMA_VERSION = "2.0";
@@ -19683,6 +19709,9 @@ var SyntrologieSDK = (() => {
19683
19709
  --syntro-border: var(--sc-overlay-border, #2b333f);
19684
19710
  --syntro-tooltip-bg: var(--syntro-surface);
19685
19711
  --syntro-tooltip-fg: var(--syntro-fg);
19712
+ --syntro-tooltip-title-color: var(--sc-overlay-title-color, var(--syntro-fg));
19713
+ --syntro-tooltip-arrow-bg: var(--sc-overlay-arrow-color, var(--syntro-tooltip-bg));
19714
+ --syntro-tooltip-arrow-size: var(--sc-overlay-arrow-size, 8px);
19686
19715
  --syntro-tooltip-radius: var(--syntro-radius);
19687
19716
  --syntro-tooltip-padding: 12px 16px;
19688
19717
  --syntro-tooltip-shadow: var(--syntro-shadow);
@@ -19709,14 +19738,13 @@ var SyntrologieSDK = (() => {
19709
19738
  transform 200ms cubic-bezier(0.16, 1, 0.3, 1);
19710
19739
  }
19711
19740
 
19712
- /* Tooltip arrow */
19741
+ /* Tooltip arrow \u2014 triangle via clip-path (square box so rotation is symmetric) */
19713
19742
  .syntro-tooltip-arrow {
19714
19743
  position: absolute;
19715
- width: 8px;
19716
- height: 8px;
19717
- background: inherit;
19718
- transform: rotate(45deg);
19719
- z-index: -1;
19744
+ width: var(--syntro-tooltip-arrow-size);
19745
+ height: var(--syntro-tooltip-arrow-size);
19746
+ background: var(--syntro-tooltip-arrow-bg);
19747
+ clip-path: polygon(0 0, 100% 0, 50% 100%);
19720
19748
  }
19721
19749
 
19722
19750
  /* Tooltip content */
@@ -19724,6 +19752,7 @@ var SyntrologieSDK = (() => {
19724
19752
  font-weight: 600;
19725
19753
  font-size: 15px;
19726
19754
  margin-bottom: 6px;
19755
+ color: var(--syntro-tooltip-title-color);
19727
19756
  }
19728
19757
 
19729
19758
  .syntro-tt-body {
@@ -20006,10 +20035,10 @@ var SyntrologieSDK = (() => {
20006
20035
  }
20007
20036
 
20008
20037
  // src/SmartCanvasApp.tsx
20009
- var import_react14 = __toESM(require_react(), 1);
20038
+ var import_react16 = __toESM(require_react(), 1);
20010
20039
 
20011
20040
  // src/components/ShadowCanvasOverlay.tsx
20012
- var import_react12 = __toESM(require_react(), 1);
20041
+ var import_react14 = __toESM(require_react(), 1);
20013
20042
  var import_react_dom = __toESM(require_react_dom(), 1);
20014
20043
 
20015
20044
  // src/events/types.ts
@@ -21014,16 +21043,257 @@ ${cssRules}
21014
21043
  }
21015
21044
 
21016
21045
  // src/components/TileCard.tsx
21017
- var import_react11 = __toESM(require_react(), 1);
21046
+ var import_react13 = __toESM(require_react(), 1);
21047
+
21048
+ // ../../node_modules/lucide-react/dist/esm/createLucideIcon.js
21049
+ var import_react12 = __toESM(require_react());
21050
+
21051
+ // ../../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
21052
+ var mergeClasses = (...classes2) => classes2.filter((className, index2, array) => {
21053
+ return Boolean(className) && className.trim() !== "" && array.indexOf(className) === index2;
21054
+ }).join(" ").trim();
21055
+
21056
+ // ../../node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.js
21057
+ var toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
21058
+
21059
+ // ../../node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.js
21060
+ var toCamelCase = (string) => string.replace(
21061
+ /^([A-Z])|[\s-_]+(\w)/g,
21062
+ (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase()
21063
+ );
21064
+
21065
+ // ../../node_modules/lucide-react/dist/esm/shared/src/utils/toPascalCase.js
21066
+ var toPascalCase = (string) => {
21067
+ const camelCase = toCamelCase(string);
21068
+ return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
21069
+ };
21070
+
21071
+ // ../../node_modules/lucide-react/dist/esm/Icon.js
21072
+ var import_react11 = __toESM(require_react());
21073
+
21074
+ // ../../node_modules/lucide-react/dist/esm/defaultAttributes.js
21075
+ var defaultAttributes = {
21076
+ xmlns: "http://www.w3.org/2000/svg",
21077
+ width: 24,
21078
+ height: 24,
21079
+ viewBox: "0 0 24 24",
21080
+ fill: "none",
21081
+ stroke: "currentColor",
21082
+ strokeWidth: 2,
21083
+ strokeLinecap: "round",
21084
+ strokeLinejoin: "round"
21085
+ };
21086
+
21087
+ // ../../node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.js
21088
+ var hasA11yProp = (props) => {
21089
+ for (const prop in props) {
21090
+ if (prop.startsWith("aria-") || prop === "role" || prop === "title") {
21091
+ return true;
21092
+ }
21093
+ }
21094
+ return false;
21095
+ };
21096
+
21097
+ // ../../node_modules/lucide-react/dist/esm/Icon.js
21098
+ var Icon = (0, import_react11.forwardRef)(
21099
+ ({
21100
+ color = "currentColor",
21101
+ size: size2 = 24,
21102
+ strokeWidth = 2,
21103
+ absoluteStrokeWidth,
21104
+ className = "",
21105
+ children,
21106
+ iconNode,
21107
+ ...rest
21108
+ }, ref) => (0, import_react11.createElement)(
21109
+ "svg",
21110
+ {
21111
+ ref,
21112
+ ...defaultAttributes,
21113
+ width: size2,
21114
+ height: size2,
21115
+ stroke: color,
21116
+ strokeWidth: absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size2) : strokeWidth,
21117
+ className: mergeClasses("lucide", className),
21118
+ ...!children && !hasA11yProp(rest) && { "aria-hidden": "true" },
21119
+ ...rest
21120
+ },
21121
+ [
21122
+ ...iconNode.map(([tag2, attrs]) => (0, import_react11.createElement)(tag2, attrs)),
21123
+ ...Array.isArray(children) ? children : [children]
21124
+ ]
21125
+ )
21126
+ );
21127
+
21128
+ // ../../node_modules/lucide-react/dist/esm/createLucideIcon.js
21129
+ var createLucideIcon = (iconName, iconNode) => {
21130
+ const Component = (0, import_react12.forwardRef)(
21131
+ ({ className, ...props }, ref) => (0, import_react12.createElement)(Icon, {
21132
+ ref,
21133
+ iconNode,
21134
+ className: mergeClasses(
21135
+ `lucide-${toKebabCase(toPascalCase(iconName))}`,
21136
+ `lucide-${iconName}`,
21137
+ className
21138
+ ),
21139
+ ...props
21140
+ })
21141
+ );
21142
+ Component.displayName = toPascalCase(iconName);
21143
+ return Component;
21144
+ };
21145
+
21146
+ // ../../node_modules/lucide-react/dist/esm/icons/circle-question-mark.js
21147
+ var __iconNode = [
21148
+ ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
21149
+ ["path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3", key: "1u773s" }],
21150
+ ["path", { d: "M12 17h.01", key: "p32p05" }]
21151
+ ];
21152
+ var CircleQuestionMark = createLucideIcon("circle-question-mark", __iconNode);
21153
+
21154
+ // ../../node_modules/lucide-react/dist/esm/icons/compass.js
21155
+ var __iconNode2 = [
21156
+ ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
21157
+ [
21158
+ "path",
21159
+ {
21160
+ d: "m16.24 7.76-1.804 5.411a2 2 0 0 1-1.265 1.265L7.76 16.24l1.804-5.411a2 2 0 0 1 1.265-1.265z",
21161
+ key: "9ktpf1"
21162
+ }
21163
+ ]
21164
+ ];
21165
+ var Compass = createLucideIcon("compass", __iconNode2);
21166
+
21167
+ // ../../node_modules/lucide-react/dist/esm/icons/file-text.js
21168
+ var __iconNode3 = [
21169
+ [
21170
+ "path",
21171
+ {
21172
+ d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",
21173
+ key: "1oefj6"
21174
+ }
21175
+ ],
21176
+ ["path", { d: "M14 2v5a1 1 0 0 0 1 1h5", key: "wfsgrz" }],
21177
+ ["path", { d: "M10 9H8", key: "b1mrlr" }],
21178
+ ["path", { d: "M16 13H8", key: "t4e002" }],
21179
+ ["path", { d: "M16 17H8", key: "z1uh3a" }]
21180
+ ];
21181
+ var FileText = createLucideIcon("file-text", __iconNode3);
21182
+
21183
+ // ../../node_modules/lucide-react/dist/esm/icons/gamepad-2.js
21184
+ var __iconNode4 = [
21185
+ ["line", { x1: "6", x2: "10", y1: "11", y2: "11", key: "1gktln" }],
21186
+ ["line", { x1: "8", x2: "8", y1: "9", y2: "13", key: "qnk9ow" }],
21187
+ ["line", { x1: "15", x2: "15.01", y1: "12", y2: "12", key: "krot7o" }],
21188
+ ["line", { x1: "18", x2: "18.01", y1: "10", y2: "10", key: "1lcuu1" }],
21189
+ [
21190
+ "path",
21191
+ {
21192
+ d: "M17.32 5H6.68a4 4 0 0 0-3.978 3.59c-.006.052-.01.101-.017.152C2.604 9.416 2 14.456 2 16a3 3 0 0 0 3 3c1 0 1.5-.5 2-1l1.414-1.414A2 2 0 0 1 9.828 16h4.344a2 2 0 0 1 1.414.586L17 18c.5.5 1 1 2 1a3 3 0 0 0 3-3c0-1.545-.604-6.584-.685-7.258-.007-.05-.011-.1-.017-.151A4 4 0 0 0 17.32 5z",
21193
+ key: "mfqc10"
21194
+ }
21195
+ ]
21196
+ ];
21197
+ var Gamepad2 = createLucideIcon("gamepad-2", __iconNode4);
21198
+
21199
+ // ../../node_modules/lucide-react/dist/esm/icons/layers.js
21200
+ var __iconNode5 = [
21201
+ [
21202
+ "path",
21203
+ {
21204
+ d: "M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z",
21205
+ key: "zw3jo"
21206
+ }
21207
+ ],
21208
+ [
21209
+ "path",
21210
+ {
21211
+ d: "M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",
21212
+ key: "1wduqc"
21213
+ }
21214
+ ],
21215
+ [
21216
+ "path",
21217
+ {
21218
+ d: "M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17",
21219
+ key: "kqbvx6"
21220
+ }
21221
+ ]
21222
+ ];
21223
+ var Layers = createLucideIcon("layers", __iconNode5);
21224
+
21225
+ // ../../node_modules/lucide-react/dist/esm/icons/message-circle.js
21226
+ var __iconNode6 = [
21227
+ [
21228
+ "path",
21229
+ {
21230
+ d: "M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719",
21231
+ key: "1sd12s"
21232
+ }
21233
+ ]
21234
+ ];
21235
+ var MessageCircle = createLucideIcon("message-circle", __iconNode6);
21236
+
21237
+ // ../../node_modules/lucide-react/dist/esm/icons/sparkles.js
21238
+ var __iconNode7 = [
21239
+ [
21240
+ "path",
21241
+ {
21242
+ d: "M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",
21243
+ key: "1s2grr"
21244
+ }
21245
+ ],
21246
+ ["path", { d: "M20 2v4", key: "1rf3ol" }],
21247
+ ["path", { d: "M22 4h-4", key: "gwowj6" }],
21248
+ ["circle", { cx: "4", cy: "20", r: "2", key: "6kqj1y" }]
21249
+ ];
21250
+ var Sparkles = createLucideIcon("sparkles", __iconNode7);
21251
+
21252
+ // ../../node_modules/lucide-react/dist/esm/icons/trophy.js
21253
+ var __iconNode8 = [
21254
+ ["path", { d: "M10 14.66v1.626a2 2 0 0 1-.976 1.696A5 5 0 0 0 7 21.978", key: "1n3hpd" }],
21255
+ ["path", { d: "M14 14.66v1.626a2 2 0 0 0 .976 1.696A5 5 0 0 1 17 21.978", key: "rfe1zi" }],
21256
+ ["path", { d: "M18 9h1.5a1 1 0 0 0 0-5H18", key: "7xy6bh" }],
21257
+ ["path", { d: "M4 22h16", key: "57wxv0" }],
21258
+ ["path", { d: "M6 9a6 6 0 0 0 12 0V3a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1z", key: "1mhfuq" }],
21259
+ ["path", { d: "M6 9H4.5a1 1 0 0 1 0-5H6", key: "tex48p" }]
21260
+ ];
21261
+ var Trophy = createLucideIcon("trophy", __iconNode8);
21262
+
21263
+ // src/components/TileIcon.tsx
21018
21264
  var import_jsx_runtime10 = __toESM(require_jsx_runtime(), 1);
21265
+ var ICON_MAP = {
21266
+ "\u2753": CircleQuestionMark,
21267
+ "\u{1F9ED}": Compass,
21268
+ "\u{1F4DD}": FileText,
21269
+ "\u{1F3AF}": Layers,
21270
+ "\u{1F3C6}": Trophy,
21271
+ "\u2728": Sparkles,
21272
+ "\u{1F4AC}": MessageCircle,
21273
+ "\u{1F3AE}": Gamepad2
21274
+ };
21275
+ function TileIcon({
21276
+ emoji,
21277
+ size: size2 = 18,
21278
+ color = "currentColor"
21279
+ }) {
21280
+ const Icon2 = ICON_MAP[emoji];
21281
+ if (!Icon2) {
21282
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: emoji });
21283
+ }
21284
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Icon2, { size: size2, color });
21285
+ }
21286
+
21287
+ // src/components/TileCard.tsx
21288
+ var import_jsx_runtime11 = __toESM(require_jsx_runtime(), 1);
21019
21289
  function WidgetMount({ widgetId, props }) {
21020
21290
  const runtime7 = useRuntime();
21021
- const containerRef = (0, import_react11.useRef)(null);
21022
- const handleRef = (0, import_react11.useRef)(null);
21291
+ const containerRef = (0, import_react13.useRef)(null);
21292
+ const handleRef = (0, import_react13.useRef)(null);
21023
21293
  const registry = runtime7?.widgets;
21024
21294
  const widgetAvailable = registry?.has(widgetId) ?? false;
21025
- const [, forceUpdate] = (0, import_react11.useReducer)((x2) => x2 + 1, 0);
21026
- (0, import_react11.useEffect)(() => {
21295
+ const [, forceUpdate] = (0, import_react13.useReducer)((x2) => x2 + 1, 0);
21296
+ (0, import_react13.useEffect)(() => {
21027
21297
  if (!registry || widgetAvailable) return;
21028
21298
  return registry.subscribe((event) => {
21029
21299
  if (event.type === "registered" && event.widgetId === widgetId) {
@@ -21031,7 +21301,7 @@ ${cssRules}
21031
21301
  }
21032
21302
  });
21033
21303
  }, [registry, widgetId, widgetAvailable]);
21034
- (0, import_react11.useEffect)(() => {
21304
+ (0, import_react13.useEffect)(() => {
21035
21305
  if (!containerRef.current || !registry || !widgetAvailable) return;
21036
21306
  const handle = registry.mount(widgetId, containerRef.current, props);
21037
21307
  handleRef.current = handle;
@@ -21041,7 +21311,7 @@ ${cssRules}
21041
21311
  };
21042
21312
  }, [registry, widgetId, props, widgetAvailable]);
21043
21313
  if (!registry || !registry.has(widgetId)) {
21044
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
21314
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
21045
21315
  "div",
21046
21316
  {
21047
21317
  style: {
@@ -21057,7 +21327,7 @@ ${cssRules}
21057
21327
  }
21058
21328
  );
21059
21329
  }
21060
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { ref: containerRef, style: { width: "100%", minHeight: "40px" } });
21330
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { ref: containerRef, style: { width: "100%", minHeight: "40px" } });
21061
21331
  }
21062
21332
  function TileCard({
21063
21333
  config,
@@ -21065,15 +21335,27 @@ ${cssRules}
21065
21335
  telemetry: _telemetry,
21066
21336
  style
21067
21337
  }) {
21068
- const { title, widget, props } = config;
21069
- const [, setTick] = (0, import_react11.useState)(0);
21338
+ const { title, subtitle, widget, props, icon } = config;
21339
+ const [, setTick] = (0, import_react13.useState)(0);
21070
21340
  const runtime7 = useRuntime();
21071
- (0, import_react11.useEffect)(() => {
21341
+ (0, import_react13.useEffect)(() => {
21072
21342
  if (runtime7) setTick((t2) => t2 + 1);
21073
21343
  }, [runtime7]);
21074
- const [hovered, setHovered] = (0, import_react11.useState)(false);
21075
- const onMouseEnter = (0, import_react11.useCallback)(() => setHovered(true), []);
21076
- const onMouseLeave = (0, import_react11.useCallback)(() => setHovered(false), []);
21344
+ const registration = (0, import_react13.useMemo)(
21345
+ () => runtime7?.widgets?.getRegistration?.(widget),
21346
+ [runtime7?.widgets, widget]
21347
+ );
21348
+ const resolvedIcon = (0, import_react13.useMemo)(() => {
21349
+ if (icon) return icon;
21350
+ return registration?.metadata?.icon ?? "+";
21351
+ }, [icon, registration]);
21352
+ const resolvedSubtitle = (0, import_react13.useMemo)(() => {
21353
+ if (subtitle) return subtitle;
21354
+ return registration?.metadata?.subtitle;
21355
+ }, [subtitle, registration]);
21356
+ const [hovered, setHovered] = (0, import_react13.useState)(false);
21357
+ const onMouseEnter = (0, import_react13.useCallback)(() => setHovered(true), []);
21358
+ const onMouseLeave = (0, import_react13.useCallback)(() => setHovered(false), []);
21077
21359
  const cardStyle = {
21078
21360
  display: "flex",
21079
21361
  flexDirection: "column",
@@ -21094,23 +21376,17 @@ ${cssRules}
21094
21376
  const headerStyle = {
21095
21377
  display: "flex",
21096
21378
  alignItems: "center",
21097
- gap: "0.75rem",
21098
- padding: "0.875rem 1rem",
21099
- minHeight: "72px"
21379
+ gap: "var(--sc-tile-gap, 0.25rem)",
21380
+ padding: "var(--sc-tile-header-padding, 0.375rem 0.75rem)",
21381
+ minHeight: "44px"
21100
21382
  };
21101
21383
  const iconStyle = {
21102
- width: "40px",
21103
- height: "40px",
21104
- borderRadius: "10px",
21105
- background: "var(--sc-tile-icon-background)",
21106
21384
  display: "flex",
21107
21385
  alignItems: "center",
21108
21386
  justifyContent: "center",
21109
- fontSize: "1.25rem",
21110
- flexShrink: 0,
21111
- boxShadow: "var(--sc-tile-icon-shadow)"
21387
+ flexShrink: 0
21112
21388
  };
21113
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
21389
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
21114
21390
  "article",
21115
21391
  {
21116
21392
  "data-shadow-canvas-id": `tile-${config.id}`,
@@ -21118,32 +21394,49 @@ ${cssRules}
21118
21394
  onMouseEnter,
21119
21395
  onMouseLeave,
21120
21396
  children: [
21121
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: headerStyle, children: [
21122
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: iconStyle, children: "+" }),
21123
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
21124
- "h3",
21125
- {
21126
- style: {
21127
- fontSize: "0.95rem",
21128
- fontWeight: 600,
21129
- color: "var(--sc-tile-title-color)",
21130
- margin: "0.125rem 0 0",
21131
- whiteSpace: "nowrap",
21132
- overflow: "hidden",
21133
- textOverflow: "ellipsis"
21134
- },
21135
- children: title ?? widget
21136
- }
21137
- ) })
21397
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: headerStyle, children: [
21398
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: iconStyle, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TileIcon, { emoji: resolvedIcon, size: resolvedSubtitle ? 36 : 24 }) }),
21399
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
21400
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
21401
+ "h3",
21402
+ {
21403
+ style: {
21404
+ fontSize: "1.14rem",
21405
+ fontWeight: 600,
21406
+ color: "var(--sc-tile-title-color)",
21407
+ margin: "0.125rem 0 0",
21408
+ whiteSpace: "nowrap",
21409
+ overflow: "hidden",
21410
+ textOverflow: "ellipsis"
21411
+ },
21412
+ children: title ?? widget
21413
+ }
21414
+ ),
21415
+ resolvedSubtitle && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
21416
+ "p",
21417
+ {
21418
+ style: {
21419
+ fontSize: "0.8rem",
21420
+ fontWeight: 400,
21421
+ color: "var(--sc-tile-text-color)",
21422
+ margin: "0.125rem 0 0",
21423
+ whiteSpace: "nowrap",
21424
+ overflow: "hidden",
21425
+ textOverflow: "ellipsis"
21426
+ },
21427
+ children: resolvedSubtitle
21428
+ }
21429
+ )
21430
+ ] })
21138
21431
  ] }),
21139
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
21432
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
21140
21433
  "div",
21141
21434
  {
21142
21435
  style: {
21143
- padding: "0 1rem 1rem",
21436
+ padding: "var(--sc-tile-body-padding, 0 0.75rem 0.5rem)",
21144
21437
  borderTop: "1px solid rgba(255, 255, 255, 0.06)"
21145
21438
  },
21146
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { paddingTop: "0.875rem" }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(WidgetMount, { widgetId: widget, props: { ...props, instanceId: config.id } }) })
21439
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { paddingTop: "var(--sc-tile-gap, 0.25rem)" }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(WidgetMount, { widgetId: widget, props: { ...props, instanceId: config.id } }) })
21147
21440
  }
21148
21441
  )
21149
21442
  ]
@@ -21152,7 +21445,7 @@ ${cssRules}
21152
21445
  }
21153
21446
 
21154
21447
  // src/components/ShadowCanvasOverlay.tsx
21155
- var import_jsx_runtime11 = __toESM(require_jsx_runtime(), 1);
21448
+ var import_jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
21156
21449
  var LAUNCHER_STYLES_ID = "syntro-launcher-styles";
21157
21450
  function ensureLauncherStyles(target, css) {
21158
21451
  if (target.querySelector(`#${LAUNCHER_STYLES_ID}`)) return;
@@ -21177,9 +21470,9 @@ ${cssRules}
21177
21470
  canvasTitle,
21178
21471
  displayMode = "standard"
21179
21472
  }) {
21180
- const [mounted, setMounted] = (0, import_react12.useState)(false);
21181
- const [launcherPos, setLauncherPos] = (0, import_react12.useState)(null);
21182
- const dragRef = (0, import_react12.useRef)(null);
21473
+ const [mounted, setMounted] = (0, import_react14.useState)(false);
21474
+ const [launcherPos, setLauncherPos] = (0, import_react14.useState)(null);
21475
+ const dragRef = (0, import_react14.useRef)(null);
21183
21476
  const runtime7 = useRuntime();
21184
21477
  const { shadowRoot, portalRoot } = useShadowRoot();
21185
21478
  const { config } = useTheme();
@@ -21188,7 +21481,7 @@ ${cssRules}
21188
21481
  tiles
21189
21482
  );
21190
21483
  useNotifyWatcher(runtime7, tiles, runtime7?.apps);
21191
- const handleNotificationClick = (0, import_react12.useCallback)(
21484
+ const handleNotificationClick = (0, import_react14.useCallback)(
21192
21485
  (notif) => {
21193
21486
  if (runtime7) {
21194
21487
  runtime7.events.publish(StandardEvents.NOTIFICATION_CLICKED, {
@@ -21210,7 +21503,7 @@ ${cssRules}
21210
21503
  },
21211
21504
  [runtime7, isOpen, onToggle, dismissNotification]
21212
21505
  );
21213
- const launcherCss = (0, import_react12.useMemo)(
21506
+ const launcherCss = (0, import_react14.useMemo)(
21214
21507
  () => `
21215
21508
  @keyframes syntro-launcher-pulse {
21216
21509
  0%, 100% {
@@ -21247,7 +21540,7 @@ ${cssRules}
21247
21540
  `,
21248
21541
  [config.colorPrimary, config.colorPrimaryHover]
21249
21542
  );
21250
- (0, import_react12.useEffect)(() => {
21543
+ (0, import_react14.useEffect)(() => {
21251
21544
  if (!isOpen) return;
21252
21545
  tiles.forEach((tile) => {
21253
21546
  telemetry?.trackRectangleViewed(tile.id, "overlay");
@@ -21257,11 +21550,11 @@ ${cssRules}
21257
21550
  }
21258
21551
  });
21259
21552
  }, [telemetry, runtime7, isOpen, tiles]);
21260
- (0, import_react12.useEffect)(() => {
21553
+ (0, import_react14.useEffect)(() => {
21261
21554
  setMounted(true);
21262
21555
  ensureLauncherStyles(shadowRoot, launcherCss);
21263
21556
  }, [shadowRoot, launcherCss]);
21264
- const toggle2 = (0, import_react12.useCallback)(() => {
21557
+ const toggle2 = (0, import_react14.useCallback)(() => {
21265
21558
  const next = !isOpen;
21266
21559
  if (next) {
21267
21560
  telemetry?.trackCanvasOpened("overlay");
@@ -21274,7 +21567,7 @@ ${cssRules}
21274
21567
  }
21275
21568
  onToggle();
21276
21569
  }, [isOpen, telemetry, runtime7, onToggle]);
21277
- const onLauncherPointerDown = (0, import_react12.useCallback)((e2) => {
21570
+ const onLauncherPointerDown = (0, import_react14.useCallback)((e2) => {
21278
21571
  const rect = e2.currentTarget.getBoundingClientRect();
21279
21572
  dragRef.current = {
21280
21573
  startX: e2.clientX,
@@ -21285,7 +21578,7 @@ ${cssRules}
21285
21578
  };
21286
21579
  e2.currentTarget.setPointerCapture(e2.pointerId);
21287
21580
  }, []);
21288
- const onLauncherPointerMove = (0, import_react12.useCallback)((e2) => {
21581
+ const onLauncherPointerMove = (0, import_react14.useCallback)((e2) => {
21289
21582
  const drag = dragRef.current;
21290
21583
  if (!drag) return;
21291
21584
  const dx = e2.clientX - drag.startX;
@@ -21297,7 +21590,7 @@ ${cssRules}
21297
21590
  setLauncherPos({ x: drag.startElX + dx, y: drag.startElY + dy });
21298
21591
  }
21299
21592
  }, []);
21300
- const onLauncherPointerUp = (0, import_react12.useCallback)(
21593
+ const onLauncherPointerUp = (0, import_react14.useCallback)(
21301
21594
  (_e2) => {
21302
21595
  const drag = dragRef.current;
21303
21596
  dragRef.current = null;
@@ -21310,9 +21603,9 @@ ${cssRules}
21310
21603
  const isFocused = displayMode === "focused";
21311
21604
  const isRight = config.canvas.position === "right";
21312
21605
  const isPush = config.canvas.layout === "push";
21313
- const containerRef = (0, import_react12.useRef)(null);
21606
+ const containerRef = (0, import_react14.useRef)(null);
21314
21607
  const zIndex = 2147483600;
21315
- (0, import_react12.useEffect)(() => {
21608
+ (0, import_react14.useEffect)(() => {
21316
21609
  if (!isPush) return;
21317
21610
  const root = document.documentElement;
21318
21611
  const prop = isRight ? "marginRight" : "marginLeft";
@@ -21329,7 +21622,7 @@ ${cssRules}
21329
21622
  root.style.transition = prevTransition;
21330
21623
  };
21331
21624
  }, [isPush, isOpen, isRight]);
21332
- (0, import_react12.useEffect)(() => {
21625
+ (0, import_react14.useEffect)(() => {
21333
21626
  if (!isPush || !isOpen) return;
21334
21627
  const container = containerRef.current;
21335
21628
  if (!container) return;
@@ -21376,7 +21669,7 @@ ${cssRules}
21376
21669
  pointerEvents: "none",
21377
21670
  padding: "0"
21378
21671
  };
21379
- const content = /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
21672
+ const content = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
21380
21673
  "div",
21381
21674
  {
21382
21675
  "data-shadow-canvas-id": "overlay-root",
@@ -21386,9 +21679,9 @@ ${cssRules}
21386
21679
  pointerEvents: isOpen ? "auto" : "none",
21387
21680
  zIndex
21388
21681
  },
21389
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: wrapperStyle, children: [
21390
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { ref: containerRef, "data-shadow-canvas-id": "overlay-container", style: containerStyle, children: [
21391
- isFocused && canvasTitle && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("header", { style: { color: "white", padding: "1.5rem 1.5rem 0" }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
21682
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: wrapperStyle, children: [
21683
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { ref: containerRef, "data-shadow-canvas-id": "overlay-container", style: containerStyle, children: [
21684
+ isFocused && canvasTitle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("header", { style: { color: "white", padding: "1.5rem 1.5rem 0" }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
21392
21685
  "p",
21393
21686
  {
21394
21687
  style: {
@@ -21401,13 +21694,13 @@ ${cssRules}
21401
21694
  children: canvasTitle
21402
21695
  }
21403
21696
  ) }),
21404
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { flex: 1, overflowY: "auto", padding: isFocused ? "0" : "1rem" }, children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
21697
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { flex: 1, overflowY: "auto", padding: isFocused ? "0" : "1rem" }, children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
21405
21698
  "div",
21406
21699
  {
21407
21700
  style: { color: "var(--sc-overlay-text-color)", padding: isFocused ? "1rem" : "0" },
21408
21701
  children: "Loading..."
21409
21702
  }
21410
- ) : error2 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
21703
+ ) : error2 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
21411
21704
  "div",
21412
21705
  {
21413
21706
  style: {
@@ -21421,7 +21714,7 @@ ${cssRules}
21421
21714
  }
21422
21715
  ) : isFocused ? (
21423
21716
  /* Focused Mode: Render first tile full size */
21424
- tiles.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
21717
+ tiles.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
21425
21718
  TileCard,
21426
21719
  {
21427
21720
  config: tiles[0],
@@ -21432,7 +21725,7 @@ ${cssRules}
21432
21725
  ) : null
21433
21726
  ) : (
21434
21727
  /* Standard Mode: Stacked cards — widgets always visible */
21435
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
21728
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
21436
21729
  "div",
21437
21730
  {
21438
21731
  style: {
@@ -21441,7 +21734,7 @@ ${cssRules}
21441
21734
  gap: "0.75rem",
21442
21735
  width: "100%"
21443
21736
  },
21444
- children: tiles.map((tile) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
21737
+ children: tiles.map((tile) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
21445
21738
  TileCard,
21446
21739
  {
21447
21740
  config: tile,
@@ -21456,7 +21749,7 @@ ${cssRules}
21456
21749
  ) }),
21457
21750
  footerSlot
21458
21751
  ] }),
21459
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
21752
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
21460
21753
  "div",
21461
21754
  {
21462
21755
  onClick: toggle2,
@@ -21471,9 +21764,9 @@ ${cssRules}
21471
21764
  }
21472
21765
  );
21473
21766
  if (!mounted) return null;
21474
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
21767
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
21475
21768
  (0, import_react_dom.createPortal)(
21476
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
21769
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
21477
21770
  "div",
21478
21771
  {
21479
21772
  "data-shadow-canvas-id": "overlay-launcher",
@@ -21484,7 +21777,7 @@ ${cssRules}
21484
21777
  zIndex: zIndex + 47
21485
21778
  },
21486
21779
  children: [
21487
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
21780
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
21488
21781
  NotificationToastStack,
21489
21782
  {
21490
21783
  notifications,
@@ -21493,7 +21786,7 @@ ${cssRules}
21493
21786
  position: config.canvas.position ?? "right"
21494
21787
  }
21495
21788
  ),
21496
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
21789
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
21497
21790
  "button",
21498
21791
  {
21499
21792
  type: "button",
@@ -21537,7 +21830,7 @@ ${cssRules}
21537
21830
  }
21538
21831
  },
21539
21832
  children: [
21540
- isOpen ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
21833
+ isOpen ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
21541
21834
  "svg",
21542
21835
  {
21543
21836
  width: "24",
@@ -21552,11 +21845,11 @@ ${cssRules}
21552
21845
  focusable: "false",
21553
21846
  style: { transition: "transform 200ms ease" },
21554
21847
  children: [
21555
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M18 6L6 18" }),
21556
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M6 6l12 12" })
21848
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M18 6L6 18" }),
21849
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M6 6l12 12" })
21557
21850
  ]
21558
21851
  }
21559
- ) : launcherIcon ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
21852
+ ) : launcherIcon ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
21560
21853
  "img",
21561
21854
  {
21562
21855
  src: launcherIcon,
@@ -21569,7 +21862,7 @@ ${cssRules}
21569
21862
  pointerEvents: "none"
21570
21863
  }
21571
21864
  }
21572
- ) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
21865
+ ) : /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
21573
21866
  "svg",
21574
21867
  {
21575
21868
  width: "24",
@@ -21584,16 +21877,16 @@ ${cssRules}
21584
21877
  focusable: "false",
21585
21878
  style: { transition: "transform 200ms ease" },
21586
21879
  children: [
21587
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("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" }),
21588
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M5 3v4" }),
21589
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M3 5h4" }),
21590
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M19 17v4" }),
21591
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M17 19h4" })
21880
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("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" }),
21881
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M5 3v4" }),
21882
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M3 5h4" }),
21883
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M19 17v4" }),
21884
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M17 19h4" })
21592
21885
  ]
21593
21886
  }
21594
21887
  ),
21595
- !isOpen && notifications.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { position: "absolute", top: -2, right: -2, pointerEvents: "none" }, children: [
21596
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
21888
+ !isOpen && notifications.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { position: "absolute", top: -2, right: -2, pointerEvents: "none" }, children: [
21889
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
21597
21890
  "span",
21598
21891
  {
21599
21892
  className: "syntro-badge-ping",
@@ -21605,7 +21898,7 @@ ${cssRules}
21605
21898
  }
21606
21899
  }
21607
21900
  ),
21608
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
21901
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
21609
21902
  "span",
21610
21903
  {
21611
21904
  className: "syntro-badge-glow",
@@ -21616,7 +21909,7 @@ ${cssRules}
21616
21909
  }
21617
21910
  }
21618
21911
  ),
21619
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
21912
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
21620
21913
  "span",
21621
21914
  {
21622
21915
  className: "syntro-badge-bounce",
@@ -21650,7 +21943,7 @@ ${cssRules}
21650
21943
  }
21651
21944
 
21652
21945
  // src/hooks/useShadowCanvasConfig.ts
21653
- var import_react13 = __toESM(require_react(), 1);
21946
+ var import_react15 = __toESM(require_react(), 1);
21654
21947
  var sortTiles = (tiles) => [...tiles].sort((a2, b2) => (b2.priority ?? 0) - (a2.priority ?? 0));
21655
21948
  function useShadowCanvasConfig({
21656
21949
  fetcher,
@@ -21659,17 +21952,29 @@ ${cssRules}
21659
21952
  pageUrl,
21660
21953
  pollIntervalMs
21661
21954
  }) {
21662
- const [state, setState] = (0, import_react13.useState)({
21955
+ const [state, setState] = (0, import_react15.useState)({
21663
21956
  tiles: [],
21664
21957
  actions: [],
21665
21958
  isLoading: true
21666
21959
  });
21667
- const prevActionsJsonRef = (0, import_react13.useRef)("[]");
21668
- const load = (0, import_react13.useCallback)(async () => {
21960
+ const prevActionsJsonRef = (0, import_react15.useRef)("[]");
21961
+ const rawConfigRef = (0, import_react15.useRef)(null);
21962
+ const refilter = (0, import_react15.useCallback)(async () => {
21963
+ const raw = rawConfigRef.current;
21964
+ if (!raw || !runtime7) return;
21965
+ let tiles = raw.tiles || [];
21966
+ tiles = await runtime7.filterTiles(tiles);
21967
+ if (experiments) {
21968
+ tiles = tiles.filter((tile) => experiments.shouldRenderRectangle(tile));
21969
+ }
21970
+ setState((prev) => ({ ...prev, tiles: sortTiles(tiles) }));
21971
+ }, [runtime7, experiments]);
21972
+ const load = (0, import_react15.useCallback)(async () => {
21669
21973
  try {
21670
21974
  setState((prev) => ({ ...prev, isLoading: true, error: void 0 }));
21671
21975
  const response = await fetcher();
21672
21976
  debug("SmartCanvas Config", "Raw config response", response);
21977
+ rawConfigRef.current = response;
21673
21978
  let tiles = response.tiles || [];
21674
21979
  if (runtime7) {
21675
21980
  tiles = await runtime7.filterTiles(tiles);
@@ -21706,24 +22011,36 @@ ${cssRules}
21706
22011
  }));
21707
22012
  }
21708
22013
  }, [experiments, fetcher, runtime7]);
21709
- (0, import_react13.useEffect)(() => {
22014
+ (0, import_react15.useEffect)(() => {
21710
22015
  load();
21711
22016
  if (experiments?.onFeaturesChanged) {
21712
22017
  return experiments.onFeaturesChanged(() => load());
21713
22018
  }
21714
22019
  }, [load, experiments, pageUrl]);
21715
- (0, import_react13.useEffect)(() => {
22020
+ (0, import_react15.useEffect)(() => {
22021
+ if (!runtime7?.accumulator) return;
22022
+ return runtime7.accumulator.subscribe(() => {
22023
+ refilter();
22024
+ });
22025
+ }, [runtime7, refilter]);
22026
+ (0, import_react15.useEffect)(() => {
22027
+ if (!runtime7?.context) return;
22028
+ return runtime7.context.subscribe(() => {
22029
+ refilter();
22030
+ });
22031
+ }, [runtime7, refilter]);
22032
+ (0, import_react15.useEffect)(() => {
21716
22033
  if (!pollIntervalMs) return;
21717
22034
  const id = setInterval(() => {
21718
22035
  load();
21719
22036
  }, pollIntervalMs);
21720
22037
  return () => clearInterval(id);
21721
22038
  }, [load, pollIntervalMs]);
21722
- return (0, import_react13.useMemo)(() => state, [state]);
22039
+ return (0, import_react15.useMemo)(() => state, [state]);
21723
22040
  }
21724
22041
 
21725
22042
  // src/SmartCanvasApp.tsx
21726
- var import_jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
22043
+ var import_jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
21727
22044
  function SmartCanvasApp({
21728
22045
  controller,
21729
22046
  fetcher,
@@ -21746,7 +22063,7 @@ ${cssRules}
21746
22063
  workspaceTheme
21747
22064
  }) {
21748
22065
  if (runtime7) {
21749
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(RuntimeProvider, { runtime: runtime7, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
22066
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(RuntimeProvider, { runtime: runtime7, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
21750
22067
  SmartCanvasAppInner,
21751
22068
  {
21752
22069
  controller,
@@ -21771,7 +22088,7 @@ ${cssRules}
21771
22088
  }
21772
22089
  ) });
21773
22090
  }
21774
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
22091
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
21775
22092
  SmartCanvasAppInner,
21776
22093
  {
21777
22094
  controller,
@@ -21816,13 +22133,13 @@ ${cssRules}
21816
22133
  initialBatchHandle,
21817
22134
  workspaceTheme
21818
22135
  }) {
21819
- const [open, setOpen] = (0, import_react14.useState)(controller.getState().open);
22136
+ const [open, setOpen] = (0, import_react16.useState)(controller.getState().open);
21820
22137
  const pageContext = usePageContext();
21821
- const [localUrl, setLocalUrl] = (0, import_react14.useState)(
22138
+ const [localUrl, setLocalUrl] = (0, import_react16.useState)(
21822
22139
  () => typeof window !== "undefined" ? window.location.href : "/"
21823
22140
  );
21824
22141
  const pageUrl = pageContext?.url ?? localUrl;
21825
- (0, import_react14.useEffect)(() => {
22142
+ (0, import_react16.useEffect)(() => {
21826
22143
  if (runtime7) return;
21827
22144
  if (typeof window === "undefined") return;
21828
22145
  const updateUrl = () => setLocalUrl(window.location.href);
@@ -21845,7 +22162,7 @@ ${cssRules}
21845
22162
  history.replaceState = originalReplaceState;
21846
22163
  };
21847
22164
  }, [runtime7]);
21848
- const derivedFetcher = (0, import_react14.useMemo)(() => {
22165
+ const derivedFetcher = (0, import_react16.useMemo)(() => {
21849
22166
  if (fetcher) return fetcher;
21850
22167
  return createCanvasConfigFetcher({
21851
22168
  configUri,
@@ -21862,15 +22179,15 @@ ${cssRules}
21862
22179
  pageUrl
21863
22180
  });
21864
22181
  const hasContent = configState.tiles.length > 0 && !configState.error;
21865
- (0, import_react14.useEffect)(() => controller.subscribe((state) => setOpen(state.open)), [controller]);
21866
- (0, import_react14.useEffect)(() => {
22182
+ (0, import_react16.useEffect)(() => controller.subscribe((state) => setOpen(state.open)), [controller]);
22183
+ (0, import_react16.useEffect)(() => {
21867
22184
  if (!configState.isLoading && !hasContent && controller.getState().open) {
21868
22185
  controller.setOpen(false);
21869
22186
  }
21870
22187
  }, [controller, hasContent, configState.isLoading]);
21871
- const batchHandleRef = (0, import_react14.useRef)(initialBatchHandle ?? null);
21872
- const adoptedInitialRef = (0, import_react14.useRef)(!!initialBatchHandle);
21873
- (0, import_react14.useEffect)(() => {
22188
+ const batchHandleRef = (0, import_react16.useRef)(initialBatchHandle ?? null);
22189
+ const adoptedInitialRef = (0, import_react16.useRef)(!!initialBatchHandle);
22190
+ (0, import_react16.useEffect)(() => {
21874
22191
  if (!runtime7?.actions) return;
21875
22192
  if (adoptedInitialRef.current) {
21876
22193
  if (configState.actions.length > 0) {
@@ -21915,7 +22232,7 @@ ${cssRules}
21915
22232
  }
21916
22233
  };
21917
22234
  }, [runtime7, configState.actions, pageUrl]);
21918
- (0, import_react14.useEffect)(() => {
22235
+ (0, import_react16.useEffect)(() => {
21919
22236
  if (!runtime7) return;
21920
22237
  return runtime7.events.subscribe(
21921
22238
  { names: ["canvas.requestOpen"] },
@@ -21927,13 +22244,13 @@ ${cssRules}
21927
22244
  if (!configState.isLoading && !hasContent) {
21928
22245
  return null;
21929
22246
  }
21930
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
22247
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
21931
22248
  ThemeProvider,
21932
22249
  {
21933
22250
  themeConfig,
21934
22251
  workspaceTheme,
21935
22252
  shadowRoot,
21936
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
22253
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
21937
22254
  ShadowCanvasOverlay,
21938
22255
  {
21939
22256
  tiles: configState.tiles,
@@ -21942,6 +22259,7 @@ ${cssRules}
21942
22259
  canvasTitle: configState.canvasTitle,
21943
22260
  telemetry,
21944
22261
  launcherLabel: launcherLabel ?? configState.launcher?.label,
22262
+ launcherIcon: configState.launcher?.icon,
21945
22263
  launcherAnimate: configState.launcher?.animate,
21946
22264
  launcherAnimationStyle: configState.launcher?.animationStyle,
21947
22265
  notificationCount: configState.launcher?.notificationCount ?? configState.tiles.length,
@@ -21956,7 +22274,7 @@ ${cssRules}
21956
22274
  }
21957
22275
 
21958
22276
  // src/SmartCanvasElement.tsx
21959
- var import_jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
22277
+ var import_jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
21960
22278
  var TAG_NAME = "smart-canvas";
21961
22279
  var BASE_CSS = `
21962
22280
  :host {
@@ -22056,13 +22374,13 @@ ${cssRules}
22056
22374
  __privateSet(this, _root, (0, import_client5.createRoot)(__privateGet(this, _mount)));
22057
22375
  }
22058
22376
  __privateGet(this, _root).render(
22059
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
22377
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
22060
22378
  ShadowRootProvider,
22061
22379
  {
22062
22380
  shadowRoot: __privateGet(this, _shadow),
22063
22381
  portalRoot: __privateGet(this, _portalRoot),
22064
22382
  overlayContainer: __privateGet(this, _overlayContainer),
22065
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SmartCanvasApp, { ...__privateGet(this, _lastAppProps), controller: __privateGet(this, _controller), canvasHost: this })
22383
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SmartCanvasApp, { ...__privateGet(this, _lastAppProps), controller: __privateGet(this, _controller), canvasHost: this })
22066
22384
  }
22067
22385
  )
22068
22386
  );
@@ -22288,32 +22606,32 @@ ${cssRules}
22288
22606
  }
22289
22607
 
22290
22608
  // src/components/TileWheel.tsx
22291
- var import_react15 = __toESM(require_react(), 1);
22292
- var import_jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
22609
+ var import_react17 = __toESM(require_react(), 1);
22610
+ var import_jsx_runtime15 = __toESM(require_jsx_runtime(), 1);
22293
22611
  function TileWheel({ tiles, intervalMs = 7e3, telemetry }) {
22294
- const [index2, setIndex] = (0, import_react15.useState)(0);
22295
- const ordered = (0, import_react15.useMemo)(
22612
+ const [index2, setIndex] = (0, import_react17.useState)(0);
22613
+ const ordered = (0, import_react17.useMemo)(
22296
22614
  () => [...tiles].sort((a2, b2) => (a2.priority ?? 0) - (b2.priority ?? 0)),
22297
22615
  [tiles]
22298
22616
  );
22299
- (0, import_react15.useEffect)(() => {
22617
+ (0, import_react17.useEffect)(() => {
22300
22618
  telemetry?.trackCanvasOpened("wheel");
22301
22619
  }, [telemetry]);
22302
- (0, import_react15.useEffect)(() => {
22620
+ (0, import_react17.useEffect)(() => {
22303
22621
  if (ordered.length <= 1) return;
22304
22622
  const id = setInterval(() => {
22305
22623
  setIndex((prev) => (prev + 1) % ordered.length);
22306
22624
  }, intervalMs);
22307
22625
  return () => clearInterval(id);
22308
22626
  }, [ordered, intervalMs]);
22309
- (0, import_react15.useEffect)(() => {
22627
+ (0, import_react17.useEffect)(() => {
22310
22628
  const current = ordered[index2];
22311
22629
  if (current) {
22312
22630
  telemetry?.trackRectangleViewed(current.id, "wheel");
22313
22631
  }
22314
22632
  }, [index2, ordered, telemetry]);
22315
22633
  if (!ordered.length) return null;
22316
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
22634
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
22317
22635
  "div",
22318
22636
  {
22319
22637
  style: {
@@ -22327,7 +22645,7 @@ ${cssRules}
22327
22645
  },
22328
22646
  "data-shadow-canvas-id": "wheel",
22329
22647
  children: [
22330
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
22648
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
22331
22649
  "div",
22332
22650
  {
22333
22651
  style: {
@@ -22336,10 +22654,10 @@ ${cssRules}
22336
22654
  transform: `translateX(-${index2 * 100}%)`,
22337
22655
  width: `${ordered.length * 100}%`
22338
22656
  },
22339
- children: ordered.map((tile) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { width: "100%", flexShrink: 0, padding: "0 1rem" }, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TileCard, { config: tile, surface: "wheel", telemetry }) }, tile.id))
22657
+ children: ordered.map((tile) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { width: "100%", flexShrink: 0, padding: "0 1rem" }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TileCard, { config: tile, surface: "wheel", telemetry }) }, tile.id))
22340
22658
  }
22341
22659
  ),
22342
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { marginTop: "1rem", display: "flex", justifyContent: "center", gap: "0.5rem" }, children: ordered.map((tile, idx) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
22660
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { marginTop: "1rem", display: "flex", justifyContent: "center", gap: "0.5rem" }, children: ordered.map((tile, idx) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
22343
22661
  "button",
22344
22662
  {
22345
22663
  type: "button",
@@ -22436,18 +22754,7 @@ ${cssRules}
22436
22754
  if (config.tiles && Array.isArray(config.tiles)) {
22437
22755
  migrated.tiles = config.tiles.map((tile) => {
22438
22756
  const migratedTile = { ...tile };
22439
- if (tile.experiment && !tile.activation) {
22440
- const exp = tile.experiment;
22441
- if (exp.featureKey) {
22442
- migratedTile.activation = {
22443
- strategy: {
22444
- type: "external",
22445
- provider: "growthbook",
22446
- featureKey: exp.featureKey,
22447
- fallback: false
22448
- }
22449
- };
22450
- }
22757
+ if (tile.experiment) {
22451
22758
  delete migratedTile.experiment;
22452
22759
  }
22453
22760
  return migratedTile;
@@ -29543,11 +29850,11 @@ ${cssRules}
29543
29850
  };
29544
29851
 
29545
29852
  // src/SmartCanvasPortal.tsx
29546
- var import_react16 = __toESM(require_react(), 1);
29853
+ var import_react18 = __toESM(require_react(), 1);
29547
29854
  var import_react_dom2 = __toESM(require_react_dom(), 1);
29548
29855
  function SmartCanvasPortal({ element, children }) {
29549
- const [mountNode, setMountNode] = (0, import_react16.useState)(null);
29550
- (0, import_react16.useLayoutEffect)(() => {
29856
+ const [mountNode, setMountNode] = (0, import_react18.useState)(null);
29857
+ (0, import_react18.useLayoutEffect)(() => {
29551
29858
  if (!element) {
29552
29859
  setMountNode(null);
29553
29860
  return;
@@ -29732,7 +30039,7 @@ ${cssRules}
29732
30039
  }
29733
30040
  var W = [true, "true", 1, "1", "yes"];
29734
30041
  var G = (t2) => w(W, t2);
29735
- var V = [false, "false", 0, "0", "no"];
30042
+ var V2 = [false, "false", 0, "0", "no"];
29736
30043
  function J(t2, i2, e2, r2, s2) {
29737
30044
  return i2 > e2 && (r2.warn("min cannot be greater than max."), i2 = e2), L(t2) ? t2 > e2 ? (r2.warn(" cannot be greater than max: " + e2 + ". Using max value instead."), e2) : t2 < i2 ? (r2.warn(" cannot be less than min: " + i2 + ". Using min value instead."), i2) : t2 : (r2.warn(" must be a number. using max or fallback. max: " + e2 + ", fallback: " + s2), J(s2 || e2, i2, e2, r2));
29738
30045
  }
@@ -30958,7 +31265,7 @@ ${cssRules}
30958
31265
  }
30959
31266
  get K() {
30960
31267
  var t2 = this.Y.q(this.X);
30961
- return G(t2) ? Ne.GRANTED : w(V, t2) ? Ne.DENIED : Ne.PENDING;
31268
+ return G(t2) ? Ne.GRANTED : w(V2, t2) ? Ne.DENIED : Ne.PENDING;
30962
31269
  }
30963
31270
  get Y() {
30964
31271
  if (!this.Z) {
@@ -31800,8 +32107,8 @@ ${cssRules}
31800
32107
  }
31801
32108
  if (D2) {
31802
32109
  w2[P2++] = 268435456 | Os[A2] << 18 | As[D2];
31803
- var V2 = 31 & Os[A2], J2 = 31 & As[D2];
31804
- k2 += Ts[V2] + Rs[J2], ++x2[257 + V2], ++S2[J2], T2 = h2 + A2, ++E2;
32110
+ var V3 = 31 & Os[A2], J2 = 31 & As[D2];
32111
+ k2 += Ts[V3] + Rs[J2], ++x2[257 + V3], ++S2[J2], T2 = h2 + A2, ++E2;
31805
32112
  } else w2[P2++] = t3[h2], ++x2[t3[h2]];
31806
32113
  }
31807
32114
  }
@@ -35678,12 +35985,16 @@ ${cssRules}
35678
35985
 
35679
35986
  // src/decisions/schema.ts
35680
35987
  var RouteFilterZ = external_exports.object({
35681
- include: external_exports.array(external_exports.string()).optional(),
35682
- exclude: external_exports.array(external_exports.string()).optional()
35988
+ include: external_exports.array(external_exports.string()).optional().describe(
35989
+ "URL patterns where this tile appears. Supports *, **, :param wildcards. Use sparingly \u2014 mostly to isolate to specific webapp functionality. Omit to appear on all routes."
35990
+ ),
35991
+ exclude: external_exports.array(external_exports.string()).optional().describe("URL patterns where this tile should NOT appear. Evaluated before include.")
35683
35992
  });
35684
35993
  var ActivationConfigZ = external_exports.object({
35685
35994
  routes: RouteFilterZ,
35686
- strategy: DecisionStrategyZ.optional()
35995
+ onlyIfPopulated: external_exports.boolean().optional().describe(
35996
+ "When true, tile is hidden if none of its props.actions[] have an active triggerWhen. Useful for tiles with all-deferred FAQ questions or nav tips. Default: false."
35997
+ )
35687
35998
  });
35688
35999
  function validateCondition(data) {
35689
36000
  return ConditionZ.safeParse(data);
@@ -35846,7 +36157,7 @@ ${cssRules}
35846
36157
 
35847
36158
  // src/actions/schema.ts
35848
36159
  var ActionTriggerZ = {
35849
- triggerWhen: DecisionStrategyZ.nullable().optional()
36160
+ triggerWhen: TriggerWhenZ
35850
36161
  };
35851
36162
  var AnchorIdZ2 = external_exports.object({
35852
36163
  selector: external_exports.string(),
@@ -38261,14 +38572,20 @@ ${cssRules}
38261
38572
  if (!matchesRouteFilter(currentUrl, activation.routes)) {
38262
38573
  continue;
38263
38574
  }
38264
- if (!activation.strategy) {
38265
- results.push(tile);
38266
- continue;
38267
- }
38268
- const result = await this.evaluate(activation.strategy);
38269
- if (result.value) {
38270
- results.push(tile);
38575
+ if (activation.onlyIfPopulated) {
38576
+ const actions2 = tile.props?.actions ?? [];
38577
+ if (actions2.length > 0) {
38578
+ const hasVisible = actions2.some((a2) => {
38579
+ if (!a2.triggerWhen) return true;
38580
+ return decisionEngine.evaluateSync(
38581
+ a2.triggerWhen,
38582
+ context.get()
38583
+ ).value;
38584
+ });
38585
+ if (!hasVisible) continue;
38586
+ }
38271
38587
  }
38588
+ results.push(tile);
38272
38589
  }
38273
38590
  return results;
38274
38591
  },
@@ -38945,7 +39262,7 @@ ${cssRules}
38945
39262
  }
38946
39263
 
38947
39264
  // src/index.ts
38948
- var RUNTIME_SDK_BUILD = true ? `${"2026-03-03T23:31:20.312Z"} (${"19510df2c8"})` : "dev";
39265
+ var RUNTIME_SDK_BUILD = true ? `${"2026-03-04T00:05:33.583Z"} (${"00e3189890"})` : "dev";
38949
39266
  if (typeof window !== "undefined") {
38950
39267
  console.log(`[Syntro Runtime] Build: ${RUNTIME_SDK_BUILD}`);
38951
39268
  const existing = window.SynOS;
@@ -38954,7 +39271,7 @@ ${cssRules}
38954
39271
  ...existing,
38955
39272
  appRegistry: registry,
38956
39273
  _runtimeBuild: RUNTIME_SDK_BUILD,
38957
- React: import_react17.default,
39274
+ React: import_react19.default,
38958
39275
  ReactDOM: { ...ReactDOMClient, createPortal: import_react_dom3.createPortal, flushSync: import_react_dom3.flushSync }
38959
39276
  };
38960
39277
  registerBuiltinRuntimeModules(registry);
@@ -39017,6 +39334,30 @@ react/cjs/react-jsx-runtime.production.js:
39017
39334
  * This source code is licensed under the MIT license found in the
39018
39335
  * LICENSE file in the root directory of this source tree.
39019
39336
  *)
39337
+
39338
+ lucide-react/dist/esm/shared/src/utils/mergeClasses.js:
39339
+ lucide-react/dist/esm/shared/src/utils/toKebabCase.js:
39340
+ lucide-react/dist/esm/shared/src/utils/toCamelCase.js:
39341
+ lucide-react/dist/esm/shared/src/utils/toPascalCase.js:
39342
+ lucide-react/dist/esm/defaultAttributes.js:
39343
+ lucide-react/dist/esm/shared/src/utils/hasA11yProp.js:
39344
+ lucide-react/dist/esm/Icon.js:
39345
+ lucide-react/dist/esm/createLucideIcon.js:
39346
+ lucide-react/dist/esm/icons/circle-question-mark.js:
39347
+ lucide-react/dist/esm/icons/compass.js:
39348
+ lucide-react/dist/esm/icons/file-text.js:
39349
+ lucide-react/dist/esm/icons/gamepad-2.js:
39350
+ lucide-react/dist/esm/icons/layers.js:
39351
+ lucide-react/dist/esm/icons/message-circle.js:
39352
+ lucide-react/dist/esm/icons/sparkles.js:
39353
+ lucide-react/dist/esm/icons/trophy.js:
39354
+ lucide-react/dist/esm/lucide-react.js:
39355
+ (**
39356
+ * @license lucide-react v0.576.0 - ISC
39357
+ *
39358
+ * This source code is licensed under the ISC license.
39359
+ * See the LICENSE file in the root directory of this source tree.
39360
+ *)
39020
39361
  */
39021
39362
  window.Syntro=SyntrologieSDK.Syntro;
39022
39363
  //# sourceMappingURL=smart-canvas.js.map