@ohhwells/bridge 0.1.9 → 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,6 +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; }
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; }
4088
4093
  `;
4089
4094
  const forceHover = document.createElement("style");
4090
4095
  forceHover.setAttribute("data-ohw-active-state-style", "");
@@ -4177,12 +4182,15 @@ function OhhwellsBridge() {
4177
4182
  }
4178
4183
  return { top, left, width: Math.max(0, right - left), height: Math.max(0, bottom - top) };
4179
4184
  };
4180
- const postImageHover = (imgEl, isDragOver = false) => {
4185
+ const postImageHover = (imgEl, isDragOver = false, forceTextOverlap) => {
4181
4186
  const r2 = getVisibleRect(imgEl);
4187
+ const hasTextOverlap = forceTextOverlap ?? (imgEl.dataset.ohwEditable === "bg-image" || imgEl.hasAttribute("data-ohw-editable-state"));
4188
+ hoveredImageHasTextOverlapRef.current = hasTextOverlap;
4182
4189
  postToParentRef.current({
4183
4190
  type: "ow:image-hover",
4184
4191
  key: imgEl.dataset.ohwKey ?? "",
4185
4192
  rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
4193
+ hasTextOverlap,
4186
4194
  ...isDragOver ? { isDragOver: true } : {}
4187
4195
  });
4188
4196
  const track = imgEl.closest("[data-ohw-hover-pause]");
@@ -4230,7 +4238,6 @@ function OhhwellsBridge() {
4230
4238
  return smallest;
4231
4239
  };
4232
4240
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
4233
- if (activeElRef.current) return;
4234
4241
  const toggleEl = document.querySelector("[data-ohw-state-toggle]");
4235
4242
  if (toggleEl) {
4236
4243
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
@@ -4256,32 +4263,52 @@ function OhhwellsBridge() {
4256
4263
  }
4257
4264
  return;
4258
4265
  }
4259
- const topEditable = topEl?.closest("[data-ohw-editable]");
4260
- if (topEditable && topEditable.dataset.ohwEditable !== "image" && topEditable.dataset.ohwEditable !== "bg-image") {
4261
- if (hoveredImageRef.current) {
4262
- hoveredImageRef.current = null;
4263
- resumeAnimTracks();
4264
- postToParentRef.current({ type: "ow:image-unhover" });
4265
- }
4266
- document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4267
- topEditable.setAttribute("data-ohw-hovered", "");
4268
- return;
4266
+ const isStateCardImage = !!imgEl.closest("[data-ohw-editable-state]");
4267
+ const textEditable = Array.from(
4268
+ document.querySelectorAll('[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"])')
4269
+ ).find((el) => {
4270
+ const er = el.getBoundingClientRect();
4271
+ return x >= er.left && x <= er.right && y >= er.top && y <= er.bottom;
4272
+ });
4273
+ if (imageUnhoverTimerRef.current) {
4274
+ clearTimeout(imageUnhoverTimerRef.current);
4275
+ imageUnhoverTimerRef.current = null;
4269
4276
  }
4270
- const activeHovered = document.querySelector("[data-ohw-hovered]");
4271
- if (activeHovered) {
4272
- const outlinePad = 8;
4273
- const hr = activeHovered.getBoundingClientRect();
4274
- if (x >= hr.left - outlinePad && x <= hr.right + outlinePad && y >= hr.top - outlinePad && y <= hr.bottom + outlinePad) {
4277
+ if (imageShowTimerRef.current) {
4278
+ clearTimeout(imageShowTimerRef.current);
4279
+ imageShowTimerRef.current = null;
4280
+ }
4281
+ if (textEditable) {
4282
+ if (textEditable.hasAttribute("contenteditable")) {
4275
4283
  if (hoveredImageRef.current) {
4276
4284
  hoveredImageRef.current = null;
4285
+ hoveredImageHasTextOverlapRef.current = false;
4277
4286
  resumeAnimTracks();
4278
4287
  postToParentRef.current({ type: "ow:image-unhover" });
4279
4288
  }
4280
4289
  return;
4281
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;
4282
4309
  }
4283
4310
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4284
- if (imgEl !== hoveredImageRef.current) {
4311
+ if (imgEl !== hoveredImageRef.current || hoveredImageHasTextOverlapRef.current) {
4285
4312
  hoveredImageRef.current = imgEl;
4286
4313
  postImageHover(imgEl, isDragOver);
4287
4314
  } else if (isDragOver) {
@@ -4290,9 +4317,29 @@ function OhhwellsBridge() {
4290
4317
  } else {
4291
4318
  const inIframeView = clientX >= 0 && clientY >= 0 && clientX <= window.innerWidth && clientY <= window.innerHeight;
4292
4319
  if (!inIframeView) return;
4293
- hoveredImageRef.current = null;
4294
- resumeAnimTracks();
4295
- postToParentRef.current({ type: "ow:image-unhover" });
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
+ }
4328
+ if (hoveredImageRef.current) {
4329
+ hoveredImageRef.current = null;
4330
+ hoveredImageHasTextOverlapRef.current = false;
4331
+ resumeAnimTracks();
4332
+ postToParentRef.current({ type: "ow:image-unhover" });
4333
+ }
4334
+ const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
4335
+ const textEl = Array.from(
4336
+ document.querySelectorAll('[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"])')
4337
+ ).find((el) => {
4338
+ const er = el.getBoundingClientRect();
4339
+ return x >= er.left && x <= er.right && y >= er.top && y <= er.bottom;
4340
+ });
4341
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4342
+ if (textEl && !textEl.hasAttribute("contenteditable")) textEl.setAttribute("data-ohw-hovered", "");
4296
4343
  }
4297
4344
  };
4298
4345
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
@@ -4311,15 +4358,18 @@ function OhhwellsBridge() {
4311
4358
  }) ?? null;
4312
4359
  const currentLocked = activeStateElRef.current?.hasAttribute("data-ohw-active-state") ? activeStateElRef.current : null;
4313
4360
  const active = found ?? currentLocked;
4361
+ const prev = activeStateElRef.current;
4314
4362
  activeStateElRef.current = active;
4315
- document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
4316
- if (active) {
4317
- if (active.querySelector("[data-ohw-state-view]")) active.setAttribute("data-ohw-state-hovered", "");
4318
- const states = deriveStates(active.dataset.ohwEditableState ?? "");
4319
- 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";
4320
- setToggleState({ rect: active.getBoundingClientRect(), activeState, states });
4321
- } else {
4322
- 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
+ }
4323
4373
  }
4324
4374
  };
4325
4375
  const handleMouseMove = (e) => {
@@ -4530,11 +4580,14 @@ function OhhwellsBridge() {
4530
4580
  setToggleState((prev) => prev ? { ...prev, rect } : null);
4531
4581
  }
4532
4582
  if (hoveredImageRef.current) {
4533
- const r2 = hoveredImageRef.current.getBoundingClientRect();
4583
+ const el = hoveredImageRef.current;
4584
+ const r2 = el.getBoundingClientRect();
4585
+ const hasTextOverlap = el.dataset.ohwEditable === "bg-image" || el.hasAttribute("data-ohw-editable-state");
4534
4586
  postToParentRef.current({
4535
4587
  type: "ow:image-hover",
4536
- key: hoveredImageRef.current.dataset.ohwKey ?? "",
4537
- rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height }
4588
+ key: el.dataset.ohwKey ?? "",
4589
+ rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
4590
+ hasTextOverlap
4538
4591
  });
4539
4592
  }
4540
4593
  };
@@ -4651,6 +4704,8 @@ function OhhwellsBridge() {
4651
4704
  window.removeEventListener("message", handleDeactivate);
4652
4705
  autoSaveTimers.current.forEach(clearTimeout);
4653
4706
  autoSaveTimers.current.clear();
4707
+ if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
4708
+ if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
4654
4709
  };
4655
4710
  }, [isEditMode, refreshStateRules]);
4656
4711
  useEffect(() => {