@ohhwells/bridge 0.1.139-next.383 → 0.1.139-next.385

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -6558,6 +6558,13 @@ function applyIconNameToTree(tree, path, icon) {
6558
6558
  if (feature) {
6559
6559
  return setPricingCardFeatureIcon(tree, Number(feature[1]), Number(feature[2]), icon);
6560
6560
  }
6561
+ return rewriteIconSlot(tree, path, `lucide:${icon}`);
6562
+ }
6563
+ function applyIconUploadToTree(tree, path, mediaRef) {
6564
+ if (FEATURE_ICON_PATH.test(path)) return null;
6565
+ return rewriteIconSlot(tree, path, `icon:${mediaRef}`);
6566
+ }
6567
+ function rewriteIconSlot(tree, path, ref) {
6561
6568
  const segments = path.split(".");
6562
6569
  const slot = segments.pop();
6563
6570
  if (!slot || NODE_SEGMENT.test(slot)) return null;
@@ -6565,8 +6572,8 @@ function applyIconNameToTree(tree, path, icon) {
6565
6572
  const node = nodeAtPath(next, segments);
6566
6573
  if (!node) return null;
6567
6574
  const current = node.slots?.[slot];
6568
- if (typeof current !== "string" || !/^(lucide|simple):/.test(current)) return null;
6569
- node.slots = { ...node.slots, [slot]: `lucide:${icon}` };
6575
+ if (typeof current !== "string" || !/^(lucide|simple|icon):/.test(current)) return null;
6576
+ node.slots = { ...node.slots, [slot]: ref };
6570
6577
  return next;
6571
6578
  }
6572
6579
 
@@ -7953,7 +7960,7 @@ function MediaBox({
7953
7960
  onError
7954
7961
  }) {
7955
7962
  const url = refValue ? ctx.resolveMedia(refValue) : null;
7956
- const isIcon = /^(lucide|simple):/.test(refValue);
7963
+ const isIcon = /^(lucide|simple|icon):/.test(refValue);
7957
7964
  const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
7958
7965
  const editAttrs = ctx.keyFor && editPath && !isIcon ? {
7959
7966
  "data-ohw-key": ctx.keyFor(editPath),
@@ -7961,6 +7968,7 @@ function MediaBox({
7961
7968
  } : {};
7962
7969
  if (isIcon) {
7963
7970
  const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
7971
+ const uploadedIconUrl = refValue.startsWith("icon:") ? ctx.resolveMedia(refValue.slice(5)) : null;
7964
7972
  const iconEditAttrs = ctx.keyFor && editPath && genericImageEdit ? { "data-ohw-key": ctx.keyFor(editPath), "data-ohw-editable": "icon" } : {};
7965
7973
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
7966
7974
  "span",
@@ -7975,7 +7983,7 @@ function MediaBox({
7975
7983
  justifyContent: "center",
7976
7984
  color: ctx.brand.palette.dark
7977
7985
  },
7978
- children: Icon ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { size: 48, color: ctx.brand.palette.dark, strokeWidth: 1.5 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 24 }, children: "\u25C6" })
7986
+ children: uploadedIconUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: uploadedIconUrl, alt: "", style: { width: 48, height: 48, objectFit: "contain" } }) : Icon ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { size: 48, color: ctx.brand.palette.dark, strokeWidth: 1.5 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 24 }, children: "\u25C6" })
7979
7987
  }
7980
7988
  );
7981
7989
  }
@@ -29519,12 +29527,16 @@ function OhhwellsBridge() {
29519
29527
  };
29520
29528
  const handleIconName = (e) => {
29521
29529
  if (e.data?.type !== "ow:icon-name") return;
29522
- const { key, icon } = e.data;
29523
- if (!key || typeof icon !== "string" || !/^[a-z0-9-]+$/.test(icon)) return;
29530
+ const { key, icon, url } = e.data;
29531
+ const isName = typeof icon === "string" && /^[a-z0-9-]+$/.test(icon);
29532
+ const isUpload = !isName && typeof url === "string" && /^https?:\/\/\S+$/i.test(url);
29533
+ if (!key || !isName && !isUpload) return;
29524
29534
  const state = parseAiSectionsState(aiSectionsRef.current);
29525
29535
  const entry = state.sections.find((s) => key.startsWith(aiSlotKeyPrefixFor(s.id)));
29526
29536
  if (!entry) return;
29527
- const nextTree = applyIconNameToTree(entry.tree, key.slice(aiSlotKeyPrefixFor(entry.id).length), icon);
29537
+ const path = key.slice(aiSlotKeyPrefixFor(entry.id).length);
29538
+ const uploadRef = isUpload ? `icon-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}` : null;
29539
+ const nextTree = uploadRef ? applyIconUploadToTree(entry.tree, path, uploadRef) : applyIconNameToTree(entry.tree, path, icon);
29528
29540
  if (!nextTree) return;
29529
29541
  void requestValidateTree5(postToParentRef.current, nextTree).then(({ ok }) => {
29530
29542
  if (!ok) return;
@@ -29534,7 +29546,7 @@ function OhhwellsBridge() {
29534
29546
  targetSectionId: entry.id,
29535
29547
  tree: nextTree,
29536
29548
  label: entry.label,
29537
- media: entry.media,
29549
+ media: uploadRef ? { ...entry.media, [uploadRef]: url } : entry.media,
29538
29550
  ...entry.brand ? { brand: entry.brand } : {},
29539
29551
  // The user is looking at the icon they just changed — no need to recenter on it.
29540
29552
  skipScrollIntoView: true