@ohhwells/bridge 0.1.10 → 0.1.11

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.js CHANGED
@@ -3791,7 +3791,7 @@ function StateToggle({
3791
3791
  left: rect.right - 8,
3792
3792
  transform: "translateX(-100%)"
3793
3793
  },
3794
- children: states.map((state) => /* @__PURE__ */ jsx3(ToggleGroupItem, { value: state, children: state }, state))
3794
+ children: states.map((state) => /* @__PURE__ */ jsx3(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
3795
3795
  }
3796
3796
  );
3797
3797
  }
@@ -3801,20 +3801,19 @@ function OhhwellsBridge() {
3801
3801
  const router = useRouter();
3802
3802
  const searchParams = useSearchParams();
3803
3803
  const isEditMode = isEditSessionActive();
3804
- useEffect(() => {
3805
- if (!isEditMode) return;
3806
- const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
3807
- const preconnect2 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "" });
3808
- const stylesheet = Object.assign(document.createElement("link"), { rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=Figtree:ital,wght@0,300..900;1,300..900&display=swap" });
3809
- document.head.append(preconnect1, preconnect2, stylesheet);
3810
- return () => {
3811
- preconnect1.remove();
3812
- preconnect2.remove();
3813
- stylesheet.remove();
3814
- };
3815
- }, [isEditMode]);
3816
3804
  const [bridgeRoot, setBridgeRoot] = useState(null);
3817
3805
  useEffect(() => {
3806
+ const figtreeFontId = "ohw-figtree-font";
3807
+ if (!document.getElementById(figtreeFontId)) {
3808
+ const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
3809
+ const preconnect2 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "" });
3810
+ const stylesheet = Object.assign(document.createElement("link"), {
3811
+ id: figtreeFontId,
3812
+ rel: "stylesheet",
3813
+ href: "https://fonts.googleapis.com/css2?family=Figtree:ital,wght@0,300..900;1,300..900&display=swap"
3814
+ });
3815
+ document.head.append(preconnect1, preconnect2, stylesheet);
3816
+ }
3818
3817
  const el = document.createElement("div");
3819
3818
  el.setAttribute("data-ohw-bridge-root", "");
3820
3819
  el.setAttribute("data-ohw-bridge", "");
@@ -3845,6 +3844,9 @@ function OhhwellsBridge() {
3845
3844
  const toolbarElRef = useRef(null);
3846
3845
  const glowElRef = useRef(null);
3847
3846
  const hoveredImageRef = useRef(null);
3847
+ const hoveredImageHasTextOverlapRef = useRef(false);
3848
+ const imageUnhoverTimerRef = useRef(null);
3849
+ const imageShowTimerRef = useRef(null);
3848
3850
  const editStylesRef = useRef(null);
3849
3851
  const activateRef = useRef(() => {
3850
3852
  });
@@ -3958,7 +3960,7 @@ function OhhwellsBridge() {
3958
3960
  }
3959
3961
  let cancelled = false;
3960
3962
  setFetchState("loading");
3961
- const apiUrl = globalThis.process?.env?.NEXT_PUBLIC_FLOWOPS_API_URL ?? "http://localhost:4005";
3963
+ const apiUrl = globalThis.process?.env?.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
3962
3964
  fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
3963
3965
  if (cancelled) return;
3964
3966
  const content = data?.content ?? {};
@@ -4085,7 +4087,9 @@ function OhhwellsBridge() {
4085
4087
  [data-ohw-editable][contenteditable] *::selection { background: ${PRIMARY}59 !important; }
4086
4088
  [data-ohw-editable-state], [data-ohw-editable-state] * { pointer-events: none !important; }
4087
4089
  [data-ohw-editable-state][data-ohw-active-state] [data-ohw-editable] { pointer-events: auto !important; }
4088
- [data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]) { pointer-events: auto !important; }
4090
+ [data-ohw-editable-state][data-ohw-active-state][data-ohw-editable] { pointer-events: auto !important; }
4091
+ [data-ohw-editable-state] [data-ohw-editable="image"],
4092
+ [data-ohw-editable-state][data-ohw-editable="image"] { pointer-events: auto !important; }
4089
4093
  `;
4090
4094
  const forceHover = document.createElement("style");
4091
4095
  forceHover.setAttribute("data-ohw-active-state-style", "");
@@ -4178,10 +4182,10 @@ function OhhwellsBridge() {
4178
4182
  }
4179
4183
  return { top, left, width: Math.max(0, right - left), height: Math.max(0, bottom - top) };
4180
4184
  };
4181
- const postImageHover = (imgEl, isDragOver = false) => {
4185
+ const postImageHover = (imgEl, isDragOver = false, forceTextOverlap) => {
4182
4186
  const r2 = getVisibleRect(imgEl);
4183
- const hasTextOverlap = imgEl.dataset.ohwEditable === "bg-image" || imgEl.hasAttribute("data-ohw-editable-state");
4184
- console.log("[OHW] postImageHover", { key: imgEl.dataset.ohwKey, editable: imgEl.dataset.ohwEditable, hasState: imgEl.hasAttribute("data-ohw-editable-state"), hasTextOverlap });
4187
+ const hasTextOverlap = forceTextOverlap ?? (imgEl.dataset.ohwEditable === "bg-image" || imgEl.hasAttribute("data-ohw-editable-state"));
4188
+ hoveredImageHasTextOverlapRef.current = hasTextOverlap;
4185
4189
  postToParentRef.current({
4186
4190
  type: "ow:image-hover",
4187
4191
  key: imgEl.dataset.ohwKey ?? "",
@@ -4234,15 +4238,6 @@ function OhhwellsBridge() {
4234
4238
  return smallest;
4235
4239
  };
4236
4240
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
4237
- if (activeElRef.current) {
4238
- console.log("[OHW] probeImageAt: text active, suppressing image hover");
4239
- if (hoveredImageRef.current) {
4240
- hoveredImageRef.current = null;
4241
- resumeAnimTracks();
4242
- postToParentRef.current({ type: "ow:image-unhover" });
4243
- }
4244
- return;
4245
- }
4246
4241
  const toggleEl = document.querySelector("[data-ohw-state-toggle]");
4247
4242
  if (toggleEl) {
4248
4243
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
@@ -4268,37 +4263,52 @@ function OhhwellsBridge() {
4268
4263
  }
4269
4264
  return;
4270
4265
  }
4266
+ const isStateCardImage = !!imgEl.closest("[data-ohw-editable-state]");
4271
4267
  const textEditable = Array.from(
4272
4268
  document.querySelectorAll('[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"])')
4273
4269
  ).find((el) => {
4274
4270
  const er = el.getBoundingClientRect();
4275
4271
  return x >= er.left && x <= er.right && y >= er.top && y <= er.bottom;
4276
4272
  });
4277
- if (textEditable) {
4278
- if (hoveredImageRef.current) {
4279
- hoveredImageRef.current = null;
4280
- resumeAnimTracks();
4281
- postToParentRef.current({ type: "ow:image-unhover" });
4282
- }
4283
- document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4284
- if (!textEditable.hasAttribute("contenteditable")) textEditable.setAttribute("data-ohw-hovered", "");
4285
- return;
4273
+ if (imageUnhoverTimerRef.current) {
4274
+ clearTimeout(imageUnhoverTimerRef.current);
4275
+ imageUnhoverTimerRef.current = null;
4276
+ }
4277
+ if (imageShowTimerRef.current) {
4278
+ clearTimeout(imageShowTimerRef.current);
4279
+ imageShowTimerRef.current = null;
4286
4280
  }
4287
- const activeHovered = document.querySelector("[data-ohw-hovered]");
4288
- if (activeHovered) {
4289
- const outlinePad = 8;
4290
- const hr = activeHovered.getBoundingClientRect();
4291
- if (x >= hr.left - outlinePad && x <= hr.right + outlinePad && y >= hr.top - outlinePad && y <= hr.bottom + outlinePad) {
4281
+ if (textEditable) {
4282
+ if (textEditable.hasAttribute("contenteditable")) {
4292
4283
  if (hoveredImageRef.current) {
4293
4284
  hoveredImageRef.current = null;
4285
+ hoveredImageHasTextOverlapRef.current = false;
4294
4286
  resumeAnimTracks();
4295
4287
  postToParentRef.current({ type: "ow:image-unhover" });
4296
4288
  }
4297
4289
  return;
4298
4290
  }
4291
+ if (isStateCardImage) {
4292
+ if (imgEl !== hoveredImageRef.current || !hoveredImageHasTextOverlapRef.current) {
4293
+ hoveredImageRef.current = imgEl;
4294
+ postImageHover(imgEl, isDragOver, true);
4295
+ }
4296
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4297
+ textEditable.setAttribute("data-ohw-hovered", "");
4298
+ return;
4299
+ }
4300
+ if (hoveredImageRef.current) {
4301
+ hoveredImageRef.current = null;
4302
+ hoveredImageHasTextOverlapRef.current = false;
4303
+ resumeAnimTracks();
4304
+ postToParentRef.current({ type: "ow:image-unhover" });
4305
+ }
4306
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4307
+ textEditable.setAttribute("data-ohw-hovered", "");
4308
+ return;
4299
4309
  }
4300
4310
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4301
- if (imgEl !== hoveredImageRef.current) {
4311
+ if (imgEl !== hoveredImageRef.current || hoveredImageHasTextOverlapRef.current) {
4302
4312
  hoveredImageRef.current = imgEl;
4303
4313
  postImageHover(imgEl, isDragOver);
4304
4314
  } else if (isDragOver) {
@@ -4307,8 +4317,17 @@ function OhhwellsBridge() {
4307
4317
  } else {
4308
4318
  const inIframeView = clientX >= 0 && clientY >= 0 && clientX <= window.innerWidth && clientY <= window.innerHeight;
4309
4319
  if (!inIframeView) return;
4320
+ if (imageUnhoverTimerRef.current) {
4321
+ clearTimeout(imageUnhoverTimerRef.current);
4322
+ imageUnhoverTimerRef.current = null;
4323
+ }
4324
+ if (imageShowTimerRef.current) {
4325
+ clearTimeout(imageShowTimerRef.current);
4326
+ imageShowTimerRef.current = null;
4327
+ }
4310
4328
  if (hoveredImageRef.current) {
4311
4329
  hoveredImageRef.current = null;
4330
+ hoveredImageHasTextOverlapRef.current = false;
4312
4331
  resumeAnimTracks();
4313
4332
  postToParentRef.current({ type: "ow:image-unhover" });
4314
4333
  }
@@ -4339,15 +4358,18 @@ function OhhwellsBridge() {
4339
4358
  }) ?? null;
4340
4359
  const currentLocked = activeStateElRef.current?.hasAttribute("data-ohw-active-state") ? activeStateElRef.current : null;
4341
4360
  const active = found ?? currentLocked;
4361
+ const prev = activeStateElRef.current;
4342
4362
  activeStateElRef.current = active;
4343
- document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
4344
- if (active) {
4345
- if (active.querySelector("[data-ohw-state-view]")) active.setAttribute("data-ohw-state-hovered", "");
4346
- const states = deriveStates(active.dataset.ohwEditableState ?? "");
4347
- const activeState = active.hasAttribute("data-ohw-active-state") ? (active.getAttribute("data-ohw-active-state") ?? "Default").charAt(0).toUpperCase() + (active.getAttribute("data-ohw-active-state") ?? "").slice(1) : "Default";
4348
- setToggleState({ rect: active.getBoundingClientRect(), activeState, states });
4349
- } else {
4350
- setToggleState(null);
4363
+ if (active !== prev) {
4364
+ if (prev) prev.removeAttribute("data-ohw-state-hovered");
4365
+ if (active) {
4366
+ if (active.querySelector("[data-ohw-state-view]")) active.setAttribute("data-ohw-state-hovered", "");
4367
+ const states = deriveStates(active.dataset.ohwEditableState ?? "");
4368
+ const activeState = active.hasAttribute("data-ohw-active-state") ? (active.getAttribute("data-ohw-active-state") ?? "Default").charAt(0).toUpperCase() + (active.getAttribute("data-ohw-active-state") ?? "").slice(1) : "Default";
4369
+ setToggleState({ rect: active.getBoundingClientRect(), activeState, states });
4370
+ } else {
4371
+ setToggleState(null);
4372
+ }
4351
4373
  }
4352
4374
  };
4353
4375
  const handleMouseMove = (e) => {
@@ -4682,6 +4704,8 @@ function OhhwellsBridge() {
4682
4704
  window.removeEventListener("message", handleDeactivate);
4683
4705
  autoSaveTimers.current.forEach(clearTimeout);
4684
4706
  autoSaveTimers.current.clear();
4707
+ if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
4708
+ if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
4685
4709
  };
4686
4710
  }, [isEditMode, refreshStateRules]);
4687
4711
  useEffect(() => {