@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.cjs CHANGED
@@ -3830,7 +3830,7 @@ function StateToggle({
3830
3830
  left: rect.right - 8,
3831
3831
  transform: "translateX(-100%)"
3832
3832
  },
3833
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ToggleGroupItem, { value: state, children: state }, state))
3833
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
3834
3834
  }
3835
3835
  );
3836
3836
  }
@@ -3840,20 +3840,19 @@ function OhhwellsBridge() {
3840
3840
  const router = (0, import_navigation.useRouter)();
3841
3841
  const searchParams = (0, import_navigation.useSearchParams)();
3842
3842
  const isEditMode = isEditSessionActive();
3843
- (0, import_react.useEffect)(() => {
3844
- if (!isEditMode) return;
3845
- const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
3846
- const preconnect2 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "" });
3847
- 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" });
3848
- document.head.append(preconnect1, preconnect2, stylesheet);
3849
- return () => {
3850
- preconnect1.remove();
3851
- preconnect2.remove();
3852
- stylesheet.remove();
3853
- };
3854
- }, [isEditMode]);
3855
3843
  const [bridgeRoot, setBridgeRoot] = (0, import_react.useState)(null);
3856
3844
  (0, import_react.useEffect)(() => {
3845
+ const figtreeFontId = "ohw-figtree-font";
3846
+ if (!document.getElementById(figtreeFontId)) {
3847
+ const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
3848
+ const preconnect2 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "" });
3849
+ const stylesheet = Object.assign(document.createElement("link"), {
3850
+ id: figtreeFontId,
3851
+ rel: "stylesheet",
3852
+ href: "https://fonts.googleapis.com/css2?family=Figtree:ital,wght@0,300..900;1,300..900&display=swap"
3853
+ });
3854
+ document.head.append(preconnect1, preconnect2, stylesheet);
3855
+ }
3857
3856
  const el = document.createElement("div");
3858
3857
  el.setAttribute("data-ohw-bridge-root", "");
3859
3858
  el.setAttribute("data-ohw-bridge", "");
@@ -3884,6 +3883,9 @@ function OhhwellsBridge() {
3884
3883
  const toolbarElRef = (0, import_react.useRef)(null);
3885
3884
  const glowElRef = (0, import_react.useRef)(null);
3886
3885
  const hoveredImageRef = (0, import_react.useRef)(null);
3886
+ const hoveredImageHasTextOverlapRef = (0, import_react.useRef)(false);
3887
+ const imageUnhoverTimerRef = (0, import_react.useRef)(null);
3888
+ const imageShowTimerRef = (0, import_react.useRef)(null);
3887
3889
  const editStylesRef = (0, import_react.useRef)(null);
3888
3890
  const activateRef = (0, import_react.useRef)(() => {
3889
3891
  });
@@ -3997,7 +3999,7 @@ function OhhwellsBridge() {
3997
3999
  }
3998
4000
  let cancelled = false;
3999
4001
  setFetchState("loading");
4000
- const apiUrl = globalThis.process?.env?.NEXT_PUBLIC_FLOWOPS_API_URL ?? "http://localhost:4005";
4002
+ const apiUrl = globalThis.process?.env?.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
4001
4003
  fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
4002
4004
  if (cancelled) return;
4003
4005
  const content = data?.content ?? {};
@@ -4124,7 +4126,9 @@ function OhhwellsBridge() {
4124
4126
  [data-ohw-editable][contenteditable] *::selection { background: ${PRIMARY}59 !important; }
4125
4127
  [data-ohw-editable-state], [data-ohw-editable-state] * { pointer-events: none !important; }
4126
4128
  [data-ohw-editable-state][data-ohw-active-state] [data-ohw-editable] { pointer-events: auto !important; }
4127
- [data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]) { pointer-events: auto !important; }
4129
+ [data-ohw-editable-state][data-ohw-active-state][data-ohw-editable] { pointer-events: auto !important; }
4130
+ [data-ohw-editable-state] [data-ohw-editable="image"],
4131
+ [data-ohw-editable-state][data-ohw-editable="image"] { pointer-events: auto !important; }
4128
4132
  `;
4129
4133
  const forceHover = document.createElement("style");
4130
4134
  forceHover.setAttribute("data-ohw-active-state-style", "");
@@ -4217,10 +4221,10 @@ function OhhwellsBridge() {
4217
4221
  }
4218
4222
  return { top, left, width: Math.max(0, right - left), height: Math.max(0, bottom - top) };
4219
4223
  };
4220
- const postImageHover = (imgEl, isDragOver = false) => {
4224
+ const postImageHover = (imgEl, isDragOver = false, forceTextOverlap) => {
4221
4225
  const r2 = getVisibleRect(imgEl);
4222
- const hasTextOverlap = imgEl.dataset.ohwEditable === "bg-image" || imgEl.hasAttribute("data-ohw-editable-state");
4223
- console.log("[OHW] postImageHover", { key: imgEl.dataset.ohwKey, editable: imgEl.dataset.ohwEditable, hasState: imgEl.hasAttribute("data-ohw-editable-state"), hasTextOverlap });
4226
+ const hasTextOverlap = forceTextOverlap ?? (imgEl.dataset.ohwEditable === "bg-image" || imgEl.hasAttribute("data-ohw-editable-state"));
4227
+ hoveredImageHasTextOverlapRef.current = hasTextOverlap;
4224
4228
  postToParentRef.current({
4225
4229
  type: "ow:image-hover",
4226
4230
  key: imgEl.dataset.ohwKey ?? "",
@@ -4273,15 +4277,6 @@ function OhhwellsBridge() {
4273
4277
  return smallest;
4274
4278
  };
4275
4279
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
4276
- if (activeElRef.current) {
4277
- console.log("[OHW] probeImageAt: text active, suppressing image hover");
4278
- if (hoveredImageRef.current) {
4279
- hoveredImageRef.current = null;
4280
- resumeAnimTracks();
4281
- postToParentRef.current({ type: "ow:image-unhover" });
4282
- }
4283
- return;
4284
- }
4285
4280
  const toggleEl = document.querySelector("[data-ohw-state-toggle]");
4286
4281
  if (toggleEl) {
4287
4282
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
@@ -4307,37 +4302,52 @@ function OhhwellsBridge() {
4307
4302
  }
4308
4303
  return;
4309
4304
  }
4305
+ const isStateCardImage = !!imgEl.closest("[data-ohw-editable-state]");
4310
4306
  const textEditable = Array.from(
4311
4307
  document.querySelectorAll('[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"])')
4312
4308
  ).find((el) => {
4313
4309
  const er = el.getBoundingClientRect();
4314
4310
  return x >= er.left && x <= er.right && y >= er.top && y <= er.bottom;
4315
4311
  });
4316
- if (textEditable) {
4317
- if (hoveredImageRef.current) {
4318
- hoveredImageRef.current = null;
4319
- resumeAnimTracks();
4320
- postToParentRef.current({ type: "ow:image-unhover" });
4321
- }
4322
- document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4323
- if (!textEditable.hasAttribute("contenteditable")) textEditable.setAttribute("data-ohw-hovered", "");
4324
- return;
4312
+ if (imageUnhoverTimerRef.current) {
4313
+ clearTimeout(imageUnhoverTimerRef.current);
4314
+ imageUnhoverTimerRef.current = null;
4315
+ }
4316
+ if (imageShowTimerRef.current) {
4317
+ clearTimeout(imageShowTimerRef.current);
4318
+ imageShowTimerRef.current = null;
4325
4319
  }
4326
- const activeHovered = document.querySelector("[data-ohw-hovered]");
4327
- if (activeHovered) {
4328
- const outlinePad = 8;
4329
- const hr = activeHovered.getBoundingClientRect();
4330
- if (x >= hr.left - outlinePad && x <= hr.right + outlinePad && y >= hr.top - outlinePad && y <= hr.bottom + outlinePad) {
4320
+ if (textEditable) {
4321
+ if (textEditable.hasAttribute("contenteditable")) {
4331
4322
  if (hoveredImageRef.current) {
4332
4323
  hoveredImageRef.current = null;
4324
+ hoveredImageHasTextOverlapRef.current = false;
4333
4325
  resumeAnimTracks();
4334
4326
  postToParentRef.current({ type: "ow:image-unhover" });
4335
4327
  }
4336
4328
  return;
4337
4329
  }
4330
+ if (isStateCardImage) {
4331
+ if (imgEl !== hoveredImageRef.current || !hoveredImageHasTextOverlapRef.current) {
4332
+ hoveredImageRef.current = imgEl;
4333
+ postImageHover(imgEl, isDragOver, true);
4334
+ }
4335
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4336
+ textEditable.setAttribute("data-ohw-hovered", "");
4337
+ return;
4338
+ }
4339
+ if (hoveredImageRef.current) {
4340
+ hoveredImageRef.current = null;
4341
+ hoveredImageHasTextOverlapRef.current = false;
4342
+ resumeAnimTracks();
4343
+ postToParentRef.current({ type: "ow:image-unhover" });
4344
+ }
4345
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4346
+ textEditable.setAttribute("data-ohw-hovered", "");
4347
+ return;
4338
4348
  }
4339
4349
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4340
- if (imgEl !== hoveredImageRef.current) {
4350
+ if (imgEl !== hoveredImageRef.current || hoveredImageHasTextOverlapRef.current) {
4341
4351
  hoveredImageRef.current = imgEl;
4342
4352
  postImageHover(imgEl, isDragOver);
4343
4353
  } else if (isDragOver) {
@@ -4346,8 +4356,17 @@ function OhhwellsBridge() {
4346
4356
  } else {
4347
4357
  const inIframeView = clientX >= 0 && clientY >= 0 && clientX <= window.innerWidth && clientY <= window.innerHeight;
4348
4358
  if (!inIframeView) return;
4359
+ if (imageUnhoverTimerRef.current) {
4360
+ clearTimeout(imageUnhoverTimerRef.current);
4361
+ imageUnhoverTimerRef.current = null;
4362
+ }
4363
+ if (imageShowTimerRef.current) {
4364
+ clearTimeout(imageShowTimerRef.current);
4365
+ imageShowTimerRef.current = null;
4366
+ }
4349
4367
  if (hoveredImageRef.current) {
4350
4368
  hoveredImageRef.current = null;
4369
+ hoveredImageHasTextOverlapRef.current = false;
4351
4370
  resumeAnimTracks();
4352
4371
  postToParentRef.current({ type: "ow:image-unhover" });
4353
4372
  }
@@ -4378,15 +4397,18 @@ function OhhwellsBridge() {
4378
4397
  }) ?? null;
4379
4398
  const currentLocked = activeStateElRef.current?.hasAttribute("data-ohw-active-state") ? activeStateElRef.current : null;
4380
4399
  const active = found ?? currentLocked;
4400
+ const prev = activeStateElRef.current;
4381
4401
  activeStateElRef.current = active;
4382
- document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
4383
- if (active) {
4384
- if (active.querySelector("[data-ohw-state-view]")) active.setAttribute("data-ohw-state-hovered", "");
4385
- const states = deriveStates(active.dataset.ohwEditableState ?? "");
4386
- 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";
4387
- setToggleState({ rect: active.getBoundingClientRect(), activeState, states });
4388
- } else {
4389
- setToggleState(null);
4402
+ if (active !== prev) {
4403
+ if (prev) prev.removeAttribute("data-ohw-state-hovered");
4404
+ if (active) {
4405
+ if (active.querySelector("[data-ohw-state-view]")) active.setAttribute("data-ohw-state-hovered", "");
4406
+ const states = deriveStates(active.dataset.ohwEditableState ?? "");
4407
+ 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";
4408
+ setToggleState({ rect: active.getBoundingClientRect(), activeState, states });
4409
+ } else {
4410
+ setToggleState(null);
4411
+ }
4390
4412
  }
4391
4413
  };
4392
4414
  const handleMouseMove = (e) => {
@@ -4721,6 +4743,8 @@ function OhhwellsBridge() {
4721
4743
  window.removeEventListener("message", handleDeactivate);
4722
4744
  autoSaveTimers.current.forEach(clearTimeout);
4723
4745
  autoSaveTimers.current.clear();
4746
+ if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
4747
+ if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
4724
4748
  };
4725
4749
  }, [isEditMode, refreshStateRules]);
4726
4750
  (0, import_react.useEffect)(() => {