@ohhwells/bridge 0.1.14-next.3 → 0.1.14

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
@@ -3396,9 +3396,7 @@ function ToggleGroupItem({
3396
3396
  Toggle,
3397
3397
  {
3398
3398
  pressed: groupValue === value,
3399
- onPressedChange: (pressed) => {
3400
- if (pressed) onValueChange(value);
3401
- },
3399
+ onPressedChange: () => onValueChange(value),
3402
3400
  className: cn(
3403
3401
  "text-foreground cursor-pointer hover:bg-transparent hover:text-foreground",
3404
3402
  "data-[state=on]:bg-background data-[state=on]:shadow-sm",
@@ -3793,7 +3791,7 @@ function StateToggle({
3793
3791
  left: rect.right - 8,
3794
3792
  transform: "translateX(-100%)"
3795
3793
  },
3796
- children: states.map((state) => /* @__PURE__ */ jsx3(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
3794
+ children: states.map((state) => /* @__PURE__ */ jsx3(ToggleGroupItem, { value: state, children: state }, state))
3797
3795
  }
3798
3796
  );
3799
3797
  }
@@ -3803,19 +3801,20 @@ function OhhwellsBridge() {
3803
3801
  const router = useRouter();
3804
3802
  const searchParams = useSearchParams();
3805
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]);
3806
3816
  const [bridgeRoot, setBridgeRoot] = useState(null);
3807
3817
  useEffect(() => {
3808
- const figtreeFontId = "ohw-figtree-font";
3809
- if (!document.getElementById(figtreeFontId)) {
3810
- const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
3811
- const preconnect2 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "" });
3812
- const stylesheet = Object.assign(document.createElement("link"), {
3813
- id: figtreeFontId,
3814
- rel: "stylesheet",
3815
- href: "https://fonts.googleapis.com/css2?family=Figtree:ital,wght@0,300..900;1,300..900&display=swap"
3816
- });
3817
- document.head.append(preconnect1, preconnect2, stylesheet);
3818
- }
3819
3818
  const el = document.createElement("div");
3820
3819
  el.setAttribute("data-ohw-bridge-root", "");
3821
3820
  el.setAttribute("data-ohw-bridge", "");
@@ -3846,9 +3845,6 @@ function OhhwellsBridge() {
3846
3845
  const toolbarElRef = useRef(null);
3847
3846
  const glowElRef = useRef(null);
3848
3847
  const hoveredImageRef = useRef(null);
3849
- const hoveredImageHasTextOverlapRef = useRef(false);
3850
- const imageUnhoverTimerRef = useRef(null);
3851
- const imageShowTimerRef = useRef(null);
3852
3848
  const editStylesRef = useRef(null);
3853
3849
  const activateRef = useRef(() => {
3854
3850
  });
@@ -3911,10 +3907,6 @@ function OhhwellsBridge() {
3911
3907
  const activate = useCallback((el) => {
3912
3908
  if (activeElRef.current === el) return;
3913
3909
  deactivate();
3914
- if (hoveredImageRef.current) {
3915
- hoveredImageRef.current = null;
3916
- postToParentRef.current({ type: "ow:image-unhover" });
3917
- }
3918
3910
  el.setAttribute("contenteditable", "true");
3919
3911
  el.removeAttribute("data-ohw-hovered");
3920
3912
  activeElRef.current = el;
@@ -3962,7 +3954,7 @@ function OhhwellsBridge() {
3962
3954
  }
3963
3955
  let cancelled = false;
3964
3956
  setFetchState("loading");
3965
- const apiUrl = globalThis.process?.env?.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
3957
+ const apiUrl = globalThis.process?.env?.NEXT_PUBLIC_FLOWOPS_API_URL ?? "http://localhost:4005";
3966
3958
  fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
3967
3959
  if (cancelled) return;
3968
3960
  const content = data?.content ?? {};
@@ -4089,7 +4081,6 @@ function OhhwellsBridge() {
4089
4081
  [data-ohw-editable][contenteditable] *::selection { background: ${PRIMARY}59 !important; }
4090
4082
  [data-ohw-editable-state], [data-ohw-editable-state] * { pointer-events: none !important; }
4091
4083
  [data-ohw-editable-state][data-ohw-active-state] [data-ohw-editable] { pointer-events: auto !important; }
4092
- [data-ohw-editable-state][data-ohw-active-state][data-ohw-editable] { pointer-events: auto !important; }
4093
4084
  `;
4094
4085
  const forceHover = document.createElement("style");
4095
4086
  forceHover.setAttribute("data-ohw-active-state-style", "");
@@ -4116,12 +4107,10 @@ function OhhwellsBridge() {
4116
4107
  if (editable) {
4117
4108
  if (editable.dataset.ohwEditable === "image" || editable.dataset.ohwEditable === "bg-image") {
4118
4109
  e.preventDefault();
4119
- e.stopPropagation();
4120
4110
  postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "" });
4121
4111
  return;
4122
4112
  }
4123
4113
  e.preventDefault();
4124
- e.stopPropagation();
4125
4114
  activateRef.current(editable);
4126
4115
  return;
4127
4116
  }
@@ -4184,15 +4173,12 @@ function OhhwellsBridge() {
4184
4173
  }
4185
4174
  return { top, left, width: Math.max(0, right - left), height: Math.max(0, bottom - top) };
4186
4175
  };
4187
- const postImageHover = (imgEl, isDragOver = false, forceTextOverlap) => {
4176
+ const postImageHover = (imgEl, isDragOver = false) => {
4188
4177
  const r2 = getVisibleRect(imgEl);
4189
- const hasTextOverlap = forceTextOverlap ?? false;
4190
- hoveredImageHasTextOverlapRef.current = hasTextOverlap;
4191
4178
  postToParentRef.current({
4192
4179
  type: "ow:image-hover",
4193
4180
  key: imgEl.dataset.ohwKey ?? "",
4194
4181
  rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
4195
- hasTextOverlap,
4196
4182
  ...isDragOver ? { isDragOver: true } : {}
4197
4183
  });
4198
4184
  const track = imgEl.closest("[data-ohw-hover-pause]");
@@ -4239,7 +4225,7 @@ function OhhwellsBridge() {
4239
4225
  }
4240
4226
  return smallest;
4241
4227
  };
4242
- const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
4228
+ const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false, fromOverlay = false) => {
4243
4229
  const toggleEl = document.querySelector("[data-ohw-state-toggle]");
4244
4230
  if (toggleEl) {
4245
4231
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
@@ -4265,52 +4251,33 @@ function OhhwellsBridge() {
4265
4251
  }
4266
4252
  return;
4267
4253
  }
4268
- const isStateCardImage = !!imgEl.closest("[data-ohw-editable-state]");
4269
- const textEditable = Array.from(
4270
- document.querySelectorAll('[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"])')
4271
- ).find((el) => {
4272
- const er = el.getBoundingClientRect();
4273
- return x >= er.left && x <= er.right && y >= er.top && y <= er.bottom;
4274
- });
4275
- if (imageUnhoverTimerRef.current) {
4276
- clearTimeout(imageUnhoverTimerRef.current);
4277
- imageUnhoverTimerRef.current = null;
4278
- }
4279
- if (imageShowTimerRef.current) {
4280
- clearTimeout(imageShowTimerRef.current);
4281
- imageShowTimerRef.current = null;
4254
+ const topEditable = topEl?.closest("[data-ohw-editable]");
4255
+ if (topEditable && topEditable.dataset.ohwEditable !== "image" && topEditable.dataset.ohwEditable !== "bg-image") {
4256
+ if (topEditable.hasAttribute("contenteditable") && fromOverlay) return;
4257
+ if (hoveredImageRef.current) {
4258
+ hoveredImageRef.current = null;
4259
+ resumeAnimTracks();
4260
+ postToParentRef.current({ type: "ow:image-unhover" });
4261
+ }
4262
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4263
+ topEditable.setAttribute("data-ohw-hovered", "");
4264
+ return;
4282
4265
  }
4283
- if (textEditable) {
4284
- if (textEditable.hasAttribute("contenteditable")) {
4266
+ const activeHovered = document.querySelector("[data-ohw-hovered]");
4267
+ if (activeHovered) {
4268
+ const outlinePad = 8;
4269
+ const hr = activeHovered.getBoundingClientRect();
4270
+ if (x >= hr.left - outlinePad && x <= hr.right + outlinePad && y >= hr.top - outlinePad && y <= hr.bottom + outlinePad) {
4285
4271
  if (hoveredImageRef.current) {
4286
4272
  hoveredImageRef.current = null;
4287
- hoveredImageHasTextOverlapRef.current = false;
4288
4273
  resumeAnimTracks();
4289
4274
  postToParentRef.current({ type: "ow:image-unhover" });
4290
4275
  }
4291
4276
  return;
4292
4277
  }
4293
- if (isStateCardImage) {
4294
- if (imgEl !== hoveredImageRef.current || !hoveredImageHasTextOverlapRef.current) {
4295
- hoveredImageRef.current = imgEl;
4296
- postImageHover(imgEl, isDragOver, true);
4297
- }
4298
- document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4299
- textEditable.setAttribute("data-ohw-hovered", "");
4300
- return;
4301
- }
4302
- if (hoveredImageRef.current) {
4303
- hoveredImageRef.current = null;
4304
- hoveredImageHasTextOverlapRef.current = false;
4305
- resumeAnimTracks();
4306
- postToParentRef.current({ type: "ow:image-unhover" });
4307
- }
4308
- document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4309
- textEditable.setAttribute("data-ohw-hovered", "");
4310
- return;
4311
4278
  }
4312
4279
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4313
- if (imgEl !== hoveredImageRef.current || hoveredImageHasTextOverlapRef.current) {
4280
+ if (imgEl !== hoveredImageRef.current) {
4314
4281
  hoveredImageRef.current = imgEl;
4315
4282
  postImageHover(imgEl, isDragOver);
4316
4283
  } else if (isDragOver) {
@@ -4319,29 +4286,9 @@ function OhhwellsBridge() {
4319
4286
  } else {
4320
4287
  const inIframeView = clientX >= 0 && clientY >= 0 && clientX <= window.innerWidth && clientY <= window.innerHeight;
4321
4288
  if (!inIframeView) return;
4322
- if (imageUnhoverTimerRef.current) {
4323
- clearTimeout(imageUnhoverTimerRef.current);
4324
- imageUnhoverTimerRef.current = null;
4325
- }
4326
- if (imageShowTimerRef.current) {
4327
- clearTimeout(imageShowTimerRef.current);
4328
- imageShowTimerRef.current = null;
4329
- }
4330
- if (hoveredImageRef.current) {
4331
- hoveredImageRef.current = null;
4332
- hoveredImageHasTextOverlapRef.current = false;
4333
- resumeAnimTracks();
4334
- postToParentRef.current({ type: "ow:image-unhover" });
4335
- }
4336
- const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
4337
- const textEl = Array.from(
4338
- document.querySelectorAll('[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"])')
4339
- ).find((el) => {
4340
- const er = el.getBoundingClientRect();
4341
- return x >= er.left && x <= er.right && y >= er.top && y <= er.bottom;
4342
- });
4343
- document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
4344
- if (textEl && !textEl.hasAttribute("contenteditable")) textEl.setAttribute("data-ohw-hovered", "");
4289
+ hoveredImageRef.current = null;
4290
+ resumeAnimTracks();
4291
+ postToParentRef.current({ type: "ow:image-unhover" });
4345
4292
  }
4346
4293
  };
4347
4294
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
@@ -4360,18 +4307,15 @@ function OhhwellsBridge() {
4360
4307
  }) ?? null;
4361
4308
  const currentLocked = activeStateElRef.current?.hasAttribute("data-ohw-active-state") ? activeStateElRef.current : null;
4362
4309
  const active = found ?? currentLocked;
4363
- const prev = activeStateElRef.current;
4364
4310
  activeStateElRef.current = active;
4365
- if (active !== prev) {
4366
- if (prev) prev.removeAttribute("data-ohw-state-hovered");
4367
- if (active) {
4368
- if (active.querySelector("[data-ohw-state-view]")) active.setAttribute("data-ohw-state-hovered", "");
4369
- const states = deriveStates(active.dataset.ohwEditableState ?? "");
4370
- 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";
4371
- setToggleState({ rect: active.getBoundingClientRect(), activeState, states });
4372
- } else {
4373
- setToggleState(null);
4374
- }
4311
+ document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
4312
+ if (active) {
4313
+ if (active.querySelector("[data-ohw-state-view]")) active.setAttribute("data-ohw-state-hovered", "");
4314
+ const states = deriveStates(active.dataset.ohwEditableState ?? "");
4315
+ 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";
4316
+ setToggleState({ rect: active.getBoundingClientRect(), activeState, states });
4317
+ } else {
4318
+ setToggleState(null);
4375
4319
  }
4376
4320
  };
4377
4321
  const handleMouseMove = (e) => {
@@ -4381,9 +4325,9 @@ function OhhwellsBridge() {
4381
4325
  };
4382
4326
  const handlePointerSync = (e) => {
4383
4327
  if (e.data?.type !== "ow:pointer-sync") return;
4384
- const { clientX, clientY } = e.data;
4328
+ const { clientX, clientY, fromOverlay } = e.data;
4385
4329
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
4386
- probeImageAt(clientX, clientY);
4330
+ probeImageAt(clientX, clientY, false, false, fromOverlay ?? false);
4387
4331
  probeHoverCardsAt(clientX, clientY);
4388
4332
  };
4389
4333
  const handleDragOver = (e) => {
@@ -4396,8 +4340,7 @@ function OhhwellsBridge() {
4396
4340
  e.dataTransfer.dropEffect = "copy";
4397
4341
  if (hoveredImageRef.current !== el) {
4398
4342
  hoveredImageRef.current = el;
4399
- const isStateCard = !!el.closest("[data-ohw-editable-state]");
4400
- postImageHover(el, true, isStateCard ? true : void 0);
4343
+ postImageHover(el, true);
4401
4344
  }
4402
4345
  };
4403
4346
  const handleDragLeave = (e) => {
@@ -4583,13 +4526,11 @@ function OhhwellsBridge() {
4583
4526
  setToggleState((prev) => prev ? { ...prev, rect } : null);
4584
4527
  }
4585
4528
  if (hoveredImageRef.current) {
4586
- const el = hoveredImageRef.current;
4587
- const r2 = el.getBoundingClientRect();
4529
+ const r2 = hoveredImageRef.current.getBoundingClientRect();
4588
4530
  postToParentRef.current({
4589
4531
  type: "ow:image-hover",
4590
- key: el.dataset.ohwKey ?? "",
4591
- rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
4592
- hasTextOverlap: hoveredImageHasTextOverlapRef.current
4532
+ key: hoveredImageRef.current.dataset.ohwKey ?? "",
4533
+ rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height }
4593
4534
  });
4594
4535
  }
4595
4536
  };
@@ -4663,49 +4604,12 @@ function OhhwellsBridge() {
4663
4604
  parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
4664
4605
  if (activeElRef.current) applyToolbarPos(activeElRef.current.getBoundingClientRect());
4665
4606
  };
4666
- const handleClickAt = (e) => {
4667
- if (e.data?.type !== "ow:click-at") return;
4668
- const { clientX, clientY } = e.data;
4669
- const allImages = Array.from(
4670
- document.querySelectorAll('[data-ohw-editable="image"], [data-ohw-editable="bg-image"]')
4671
- ).filter((el) => !!el.closest("[data-ohw-editable-state]"));
4672
- const stateCardImage = allImages.find((el) => {
4673
- const ownerCard = el.closest("[data-ohw-editable-state]");
4674
- if (ownerCard) {
4675
- const inHoverState = ownerCard.getAttribute("data-ohw-active-state") === "hover";
4676
- const elState = el.dataset.ohwState;
4677
- if (el === ownerCard && inHoverState) return false;
4678
- if (elState === "default" && inHoverState) return false;
4679
- if (elState === "hover" && !inHoverState) return false;
4680
- }
4681
- const r2 = el.getBoundingClientRect();
4682
- return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
4683
- });
4684
- if (stateCardImage) {
4685
- postToParentRef.current({ type: "ow:image-pick", key: stateCardImage.dataset.ohwKey ?? "" });
4686
- return;
4687
- }
4688
- const textEditable = Array.from(
4689
- document.querySelectorAll(
4690
- '[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"])'
4691
- )
4692
- ).find((el) => {
4693
- const r2 = el.getBoundingClientRect();
4694
- return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
4695
- });
4696
- if (textEditable) {
4697
- activateRef.current(textEditable);
4698
- return;
4699
- }
4700
- deactivateRef.current();
4701
- };
4702
4607
  window.addEventListener("message", handleSave);
4703
4608
  window.addEventListener("message", handleImageUrl);
4704
4609
  window.addEventListener("message", handleAnimLock);
4705
4610
  window.addEventListener("message", handleCanvasHeight);
4706
4611
  window.addEventListener("message", handleParentScroll);
4707
4612
  window.addEventListener("message", handlePointerSync);
4708
- window.addEventListener("message", handleClickAt);
4709
4613
  document.addEventListener("click", handleClick, true);
4710
4614
  document.addEventListener("paste", handlePaste, true);
4711
4615
  document.addEventListener("input", handleInput, true);
@@ -4739,13 +4643,10 @@ function OhhwellsBridge() {
4739
4643
  window.removeEventListener("message", handleCanvasHeight);
4740
4644
  window.removeEventListener("message", handleParentScroll);
4741
4645
  window.removeEventListener("message", handlePointerSync);
4742
- window.removeEventListener("message", handleClickAt);
4743
4646
  window.removeEventListener("message", handleHydrate);
4744
4647
  window.removeEventListener("message", handleDeactivate);
4745
4648
  autoSaveTimers.current.forEach(clearTimeout);
4746
4649
  autoSaveTimers.current.clear();
4747
- if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
4748
- if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
4749
4650
  };
4750
4651
  }, [isEditMode, refreshStateRules]);
4751
4652
  useEffect(() => {