@ohhwells/bridge 0.1.66-next.190 → 0.1.67-next.193

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
@@ -75,7 +75,7 @@ __export(index_exports, {
75
75
  module.exports = __toCommonJS(index_exports);
76
76
 
77
77
  // src/OhhwellsBridge.tsx
78
- var import_react16 = __toESM(require("react"), 1);
78
+ var import_react17 = __toESM(require("react"), 1);
79
79
  var import_client2 = require("react-dom/client");
80
80
  var import_react_dom3 = require("react-dom");
81
81
 
@@ -7551,13 +7551,17 @@ function MediaOverlay({
7551
7551
  hover,
7552
7552
  isUploading,
7553
7553
  fadingOut = false,
7554
+ selected = false,
7555
+ hovered = false,
7554
7556
  onFadeOutComplete,
7555
7557
  onReplace,
7558
+ onSelect,
7556
7559
  onVideoSettingsChange
7557
7560
  }) {
7558
7561
  const { rect } = hover;
7559
7562
  const skeletonRef = React7.useRef(null);
7560
7563
  const isVideo = hover.elementType === "video";
7564
+ const showChrome = !selected || hovered;
7561
7565
  const autoplay = hover.videoAutoplay ?? true;
7562
7566
  const muted = hover.videoMuted ?? true;
7563
7567
  const box = {
@@ -7592,7 +7596,7 @@ function MediaOverlay({
7592
7596
  }
7593
7597
  );
7594
7598
  }
7595
- const settingsBar = isVideo && !hover.isDragOver ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7599
+ const settingsBar = isVideo && !hover.isDragOver && showChrome ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7596
7600
  "div",
7597
7601
  {
7598
7602
  "data-ohw-bridge": "",
@@ -7662,11 +7666,13 @@ function MediaOverlay({
7662
7666
  // in-document, pointer-events does it natively. The button below opts back in, so
7663
7667
  // Replace still works.
7664
7668
  pointerEvents: hover.hasTextOverlap ? "none" : "auto",
7665
- boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
7666
- background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
7669
+ // Selected: a firm component ring with no wash, so the image reads as chosen rather
7670
+ // than hovered. Hover keeps the existing tinted preview.
7671
+ boxShadow: selected ? "inset 0 0 0 2px var(--color-primary)" : "inset 0 0 0 1.5px var(--color-primary)",
7672
+ background: selected ? "transparent" : "color-mix(in srgb, var(--color-primary) 20%, transparent)"
7667
7673
  },
7668
- onClick: () => onReplace(hover.key),
7669
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7674
+ onClick: () => onSelect && !selected ? onSelect(hover.key) : onReplace(hover.key),
7675
+ children: showChrome && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7670
7676
  Button,
7671
7677
  {
7672
7678
  "data-ohw-media-overlay": "",
@@ -8130,6 +8136,58 @@ function AiSectionOverlay({
8130
8136
 
8131
8137
  // src/lib/section-instances.ts
8132
8138
  var SECTION_ORDER_KEY = "__ohw_section_order";
8139
+ function topLevelSections() {
8140
+ return Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
8141
+ (el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
8142
+ );
8143
+ }
8144
+ function instanceIdOf(el) {
8145
+ return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
8146
+ }
8147
+ function planSectionMove(instanceId, targetIndex, currentPath) {
8148
+ const sections = topLevelSections();
8149
+ const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
8150
+ if (index === -1) return null;
8151
+ const dragged = sections[index];
8152
+ const others = sections.filter((_, i) => i !== index);
8153
+ const clamped = Math.max(0, Math.min(targetIndex, others.length));
8154
+ const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
8155
+ return reordered.map((el, order) => ({
8156
+ instanceId: instanceIdOf(el),
8157
+ type: el.getAttribute("data-ohw-section") ?? "",
8158
+ order,
8159
+ pagePath: currentPath
8160
+ }));
8161
+ }
8162
+ function moveSectionInstance(instanceId, direction, currentPath) {
8163
+ const sections = topLevelSections();
8164
+ const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
8165
+ if (index === -1) return null;
8166
+ const siblingIndex = direction === "up" ? index - 1 : index + 1;
8167
+ if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
8168
+ const entries = planSectionMove(instanceId, siblingIndex, currentPath);
8169
+ if (!entries) return null;
8170
+ applyPersistedOrder(entries);
8171
+ return entries;
8172
+ }
8173
+ function applyPersistedOrder(entries) {
8174
+ if (entries.length === 0) return;
8175
+ const sections = topLevelSections();
8176
+ if (sections.length === 0) return;
8177
+ const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
8178
+ const ordered = [...sections].sort((a, b) => {
8179
+ const aOrder = orderIndex.get(instanceIdOf(a));
8180
+ const bOrder = orderIndex.get(instanceIdOf(b));
8181
+ if (aOrder === void 0 && bOrder === void 0) return 0;
8182
+ if (aOrder === void 0) return 1;
8183
+ if (bOrder === void 0) return -1;
8184
+ return aOrder - bOrder;
8185
+ });
8186
+ const parent = sections[0].parentElement;
8187
+ if (!parent) return;
8188
+ const anchor = sections[sections.length - 1].nextSibling;
8189
+ ordered.forEach((el) => parent.insertBefore(el, anchor));
8190
+ }
8133
8191
  function getPageSectionOrderEntries(raw, currentPath) {
8134
8192
  if (!raw) return [];
8135
8193
  try {
@@ -8167,6 +8225,7 @@ function initSectionInstancesFromContent(content, currentPath) {
8167
8225
  rekeySectionSubtree(clone, entry.instanceId);
8168
8226
  original.insertAdjacentElement("afterend", clone);
8169
8227
  }
8228
+ applyPersistedOrder(entries);
8170
8229
  }
8171
8230
 
8172
8231
  // src/OhhwellsBridge.tsx
@@ -13275,6 +13334,333 @@ function useNavItemDrag({
13275
13334
  };
13276
13335
  }
13277
13336
 
13337
+ // src/useSectionDrag.ts
13338
+ var import_react15 = require("react");
13339
+
13340
+ // src/lib/section-dnd.ts
13341
+ function isFooterSection(el) {
13342
+ return el.dataset.ohwSection === "footer";
13343
+ }
13344
+ function buildSectionDropSlots(draggedInstanceId) {
13345
+ const sections = topLevelSections().filter(
13346
+ (el) => instanceIdOf(el) !== draggedInstanceId && !isFooterSection(el)
13347
+ );
13348
+ const slots = [];
13349
+ if (sections.length === 0) return slots;
13350
+ const left = 0;
13351
+ const width = document.documentElement.clientWidth;
13352
+ for (let i = 0; i <= sections.length; i++) {
13353
+ let y;
13354
+ if (i === 0) {
13355
+ y = sections[0].getBoundingClientRect().top;
13356
+ } else if (i === sections.length) {
13357
+ y = sections[sections.length - 1].getBoundingClientRect().bottom;
13358
+ } else {
13359
+ const prev = sections[i - 1].getBoundingClientRect();
13360
+ const next = sections[i].getBoundingClientRect();
13361
+ y = (prev.bottom + next.top) / 2;
13362
+ }
13363
+ slots.push({ insertIndex: i, y, left, width });
13364
+ }
13365
+ return slots;
13366
+ }
13367
+ function hitTestSectionDropSlot(y, slots) {
13368
+ let best = null;
13369
+ for (const slot of slots) {
13370
+ const dist = Math.abs(y - slot.y);
13371
+ if (!best || dist < best.dist) best = { slot, dist };
13372
+ }
13373
+ return best?.slot ?? null;
13374
+ }
13375
+
13376
+ // src/useSectionDrag.ts
13377
+ var PRESS_THRESHOLD = 10;
13378
+ var EDGE_ZONE = 60;
13379
+ var MAX_AUTO_SCROLL_SPEED = 18;
13380
+ var SECTION_DRAG_EXCLUDED_SELECTOR = [
13381
+ "[data-ohw-toolbar]",
13382
+ "[data-ohw-edit-chrome]",
13383
+ "[data-ohw-item-interaction]",
13384
+ "[data-ohw-drag-handle-container]",
13385
+ '[data-slot="drag-handle"]',
13386
+ "[data-ohw-item-toolbar-anchor]",
13387
+ "[data-ohw-item-drag-surface]",
13388
+ "[data-ohw-more-menu]",
13389
+ '[data-slot="dropdown-menu-content"]',
13390
+ '[data-slot="dropdown-menu-item"]',
13391
+ "[data-ohw-state-toggle]",
13392
+ "[data-ohw-max-badge]",
13393
+ "[data-ohw-floating-panel]",
13394
+ "[data-ohw-section-picker]",
13395
+ "[data-ohw-link-popover-root]",
13396
+ "[data-ohw-link-modal-root]",
13397
+ "[data-ohw-link-page-dropdown]",
13398
+ '[data-slot="popover-content"]',
13399
+ '[data-slot="dialog-content"]',
13400
+ '[data-slot="dialog-overlay"]',
13401
+ "[data-ohw-ai-review]",
13402
+ "[data-ohw-editable]",
13403
+ "[data-ohw-editable-state]",
13404
+ "[contenteditable]",
13405
+ "[data-ohw-href-key]",
13406
+ "[data-ohw-footer-col]",
13407
+ "[data-ohw-social-label]",
13408
+ "a",
13409
+ "button",
13410
+ '[role="button"]',
13411
+ '[data-ohw-role="navbar-button"]',
13412
+ '[data-ohw-role="button"]',
13413
+ "[data-ohw-carousel]",
13414
+ "[data-ohw-carousel-value]",
13415
+ "[data-ohw-carousel-slide]",
13416
+ "[data-ohw-carousel-overlay]",
13417
+ "[data-ohw-media-chrome]",
13418
+ "[data-ohw-media-overlay]",
13419
+ "[data-ohw-media-skeleton]"
13420
+ ].join(", ");
13421
+ function visibleClip(ps) {
13422
+ if (!ps) return null;
13423
+ const top = Math.max(0, ps.headerH - ps.iframeOffsetTop);
13424
+ const bottom = Math.min(window.innerHeight, ps.headerH + ps.canvasH - ps.iframeOffsetTop);
13425
+ return { top, bottom: Math.max(top, bottom) };
13426
+ }
13427
+ function useSectionDrag({
13428
+ isEditMode,
13429
+ editContentRef,
13430
+ postToParentRef,
13431
+ parentScrollRef,
13432
+ navDragRef,
13433
+ footerDragRef,
13434
+ suppressNextClickRef,
13435
+ suppressClickUntilRef
13436
+ }) {
13437
+ const sectionDragRef = (0, import_react15.useRef)(null);
13438
+ const [sectionDropSlots, setSectionDropSlots] = (0, import_react15.useState)([]);
13439
+ const [activeSectionDropIndex, setActiveSectionDropIndex] = (0, import_react15.useState)(null);
13440
+ const [isSectionDragging, setIsSectionDragging] = (0, import_react15.useState)(false);
13441
+ const sectionPointerDragRef = (0, import_react15.useRef)(null);
13442
+ const autoScrollRafRef = (0, import_react15.useRef)(null);
13443
+ const autoScrollDeltaRef = (0, import_react15.useRef)(0);
13444
+ const stopAutoScroll = (0, import_react15.useCallback)(() => {
13445
+ if (autoScrollRafRef.current != null) {
13446
+ cancelAnimationFrame(autoScrollRafRef.current);
13447
+ autoScrollRafRef.current = null;
13448
+ }
13449
+ autoScrollDeltaRef.current = 0;
13450
+ }, []);
13451
+ const tickAutoScroll = (0, import_react15.useCallback)(() => {
13452
+ if (!sectionDragRef.current) {
13453
+ stopAutoScroll();
13454
+ return;
13455
+ }
13456
+ if (autoScrollDeltaRef.current !== 0) {
13457
+ postToParentRef.current({ type: "ow:request-scroll", deltaY: autoScrollDeltaRef.current });
13458
+ }
13459
+ autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
13460
+ }, [postToParentRef, stopAutoScroll]);
13461
+ const updateAutoScroll = (0, import_react15.useCallback)(
13462
+ (clientY) => {
13463
+ const clip = visibleClip(parentScrollRef.current);
13464
+ let delta = 0;
13465
+ if (clip) {
13466
+ const distTop = clientY - clip.top;
13467
+ const distBottom = clip.bottom - clientY;
13468
+ if (distTop >= 0 && distTop < EDGE_ZONE) {
13469
+ delta = -MAX_AUTO_SCROLL_SPEED * (1 - distTop / EDGE_ZONE);
13470
+ } else if (distBottom >= 0 && distBottom < EDGE_ZONE) {
13471
+ delta = MAX_AUTO_SCROLL_SPEED * (1 - distBottom / EDGE_ZONE);
13472
+ }
13473
+ }
13474
+ autoScrollDeltaRef.current = delta;
13475
+ if (delta !== 0 && autoScrollRafRef.current == null) {
13476
+ autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
13477
+ } else if (delta === 0) {
13478
+ stopAutoScroll();
13479
+ }
13480
+ },
13481
+ [parentScrollRef, stopAutoScroll, tickAutoScroll]
13482
+ );
13483
+ const clearSectionDragVisuals = (0, import_react15.useCallback)(() => {
13484
+ sectionDragRef.current?.draggedEl.removeAttribute("data-ohw-section-dragging");
13485
+ sectionDragRef.current = null;
13486
+ setSectionDropSlots([]);
13487
+ setActiveSectionDropIndex(null);
13488
+ setIsSectionDragging(false);
13489
+ stopAutoScroll();
13490
+ document.documentElement.removeAttribute("data-ohw-section-dragging-root");
13491
+ unlockItemDragInteraction();
13492
+ }, [stopAutoScroll]);
13493
+ const refreshSectionDragVisuals = (0, import_react15.useCallback)(
13494
+ (session, clientX, clientY) => {
13495
+ session.lastClientX = clientX;
13496
+ session.lastClientY = clientY;
13497
+ const slots = buildSectionDropSlots(session.instanceId);
13498
+ const activeSlot = hitTestSectionDropSlot(clientY, slots);
13499
+ session.activeSlot = activeSlot;
13500
+ setSectionDropSlots(slots);
13501
+ const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
13502
+ setActiveSectionDropIndex(activeIdx >= 0 ? activeIdx : null);
13503
+ updateAutoScroll(clientY);
13504
+ },
13505
+ [updateAutoScroll]
13506
+ );
13507
+ const beginSectionDrag = (0, import_react15.useCallback)(
13508
+ (session) => {
13509
+ sectionDragRef.current = session;
13510
+ setIsSectionDragging(true);
13511
+ lockItemDuringDrag();
13512
+ document.documentElement.setAttribute("data-ohw-section-dragging-root", "");
13513
+ session.draggedEl.setAttribute("data-ohw-section-dragging", "");
13514
+ refreshSectionDragVisuals(session, session.lastClientX, session.lastClientY);
13515
+ },
13516
+ [refreshSectionDragVisuals]
13517
+ );
13518
+ const commitSectionDrag = (0, import_react15.useCallback)(() => {
13519
+ const session = sectionDragRef.current;
13520
+ if (!session) {
13521
+ clearSectionDragVisuals();
13522
+ return;
13523
+ }
13524
+ const slot = session.activeSlot ?? hitTestSectionDropSlot(session.lastClientY, buildSectionDropSlots(session.instanceId));
13525
+ const entries = slot ? planSectionMove(session.instanceId, slot.insertIndex, window.location.pathname) : null;
13526
+ if (!entries) {
13527
+ clearSectionDragVisuals();
13528
+ return;
13529
+ }
13530
+ const orderJson = JSON.stringify(entries);
13531
+ editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
13532
+ postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
13533
+ applyPersistedOrder(entries);
13534
+ clearSectionDragVisuals();
13535
+ requestAnimationFrame(() => {
13536
+ if (editContentRef.current[SECTION_ORDER_KEY] === orderJson) {
13537
+ applyPersistedOrder(entries);
13538
+ }
13539
+ requestAnimationFrame(() => {
13540
+ window.dispatchEvent(new Event("resize"));
13541
+ });
13542
+ });
13543
+ }, [clearSectionDragVisuals, editContentRef, postToParentRef]);
13544
+ const startSectionPressDrag = (0, import_react15.useCallback)(
13545
+ (el, clientX, clientY, pointerId) => {
13546
+ if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return false;
13547
+ const instanceId = instanceIdOf(el);
13548
+ if (!instanceId) return false;
13549
+ sectionPointerDragRef.current = {
13550
+ el,
13551
+ instanceId,
13552
+ startX: clientX,
13553
+ startY: clientY,
13554
+ pointerId,
13555
+ started: false
13556
+ };
13557
+ return true;
13558
+ },
13559
+ [footerDragRef, navDragRef]
13560
+ );
13561
+ (0, import_react15.useEffect)(() => {
13562
+ if (!isEditMode) return;
13563
+ const onPointerDown = (e) => {
13564
+ if (e.button !== 0) return;
13565
+ if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return;
13566
+ if (sectionPointerDragRef.current) return;
13567
+ const target = e.target;
13568
+ if (!(target instanceof HTMLElement)) return;
13569
+ if (target.closest(SECTION_DRAG_EXCLUDED_SELECTOR)) return;
13570
+ const sectionEl = target.closest("[data-ohw-section]");
13571
+ if (!sectionEl || isChromeSection(sectionEl) || sectionEl.dataset.ohwSection === "footer") return;
13572
+ if (!topLevelSections().includes(sectionEl)) return;
13573
+ startSectionPressDrag(sectionEl, e.clientX, e.clientY, e.pointerId);
13574
+ };
13575
+ const onPointerMove = (e) => {
13576
+ const pending = sectionPointerDragRef.current;
13577
+ if (!pending) return;
13578
+ if (pending.started) {
13579
+ e.preventDefault();
13580
+ clearTextSelection();
13581
+ const session = sectionDragRef.current;
13582
+ if (!session) return;
13583
+ refreshSectionDragVisuals(session, e.clientX, e.clientY);
13584
+ return;
13585
+ }
13586
+ const dx = e.clientX - pending.startX;
13587
+ const dy = e.clientY - pending.startY;
13588
+ if (dx * dx + dy * dy < PRESS_THRESHOLD * PRESS_THRESHOLD) return;
13589
+ e.preventDefault();
13590
+ pending.started = true;
13591
+ armItemPressDrag();
13592
+ clearTextSelection();
13593
+ try {
13594
+ document.body.setPointerCapture(pending.pointerId);
13595
+ } catch {
13596
+ }
13597
+ beginSectionDrag({
13598
+ instanceId: pending.instanceId,
13599
+ draggedEl: pending.el,
13600
+ lastClientX: e.clientX,
13601
+ lastClientY: e.clientY,
13602
+ activeSlot: null
13603
+ });
13604
+ };
13605
+ const endPointerDrag = (e) => {
13606
+ const pending = sectionPointerDragRef.current;
13607
+ sectionPointerDragRef.current = null;
13608
+ try {
13609
+ if (document.body.hasPointerCapture(e.pointerId)) {
13610
+ document.body.releasePointerCapture(e.pointerId);
13611
+ }
13612
+ } catch {
13613
+ }
13614
+ if (!pending) return;
13615
+ if (!pending.started) {
13616
+ unlockItemDragInteraction();
13617
+ return;
13618
+ }
13619
+ suppressNextClickRef.current = true;
13620
+ suppressClickUntilRef.current = Date.now() + 500;
13621
+ commitSectionDrag();
13622
+ };
13623
+ const onKeyDown = (e) => {
13624
+ if (e.key !== "Escape") return;
13625
+ if (!sectionDragRef.current && !sectionPointerDragRef.current) return;
13626
+ sectionPointerDragRef.current = null;
13627
+ clearSectionDragVisuals();
13628
+ };
13629
+ document.addEventListener("pointerdown", onPointerDown, true);
13630
+ document.addEventListener("pointermove", onPointerMove, true);
13631
+ document.addEventListener("pointerup", endPointerDrag, true);
13632
+ document.addEventListener("pointercancel", endPointerDrag, true);
13633
+ document.addEventListener("keydown", onKeyDown, true);
13634
+ return () => {
13635
+ document.removeEventListener("pointerdown", onPointerDown, true);
13636
+ document.removeEventListener("pointermove", onPointerMove, true);
13637
+ document.removeEventListener("pointerup", endPointerDrag, true);
13638
+ document.removeEventListener("pointercancel", endPointerDrag, true);
13639
+ document.removeEventListener("keydown", onKeyDown, true);
13640
+ unlockItemDragInteraction();
13641
+ stopAutoScroll();
13642
+ };
13643
+ }, [
13644
+ beginSectionDrag,
13645
+ clearSectionDragVisuals,
13646
+ commitSectionDrag,
13647
+ footerDragRef,
13648
+ isEditMode,
13649
+ navDragRef,
13650
+ refreshSectionDragVisuals,
13651
+ startSectionPressDrag,
13652
+ stopAutoScroll,
13653
+ suppressClickUntilRef,
13654
+ suppressNextClickRef
13655
+ ]);
13656
+ return {
13657
+ sectionDragRef,
13658
+ sectionDropSlots,
13659
+ activeSectionDropIndex,
13660
+ isSectionDragging
13661
+ };
13662
+ }
13663
+
13278
13664
  // src/ui/footer-container-chrome.tsx
13279
13665
  var import_lucide_react16 = require("lucide-react");
13280
13666
  var import_jsx_runtime30 = require("react/jsx-runtime");
@@ -13327,7 +13713,7 @@ function FooterContainerChrome({
13327
13713
  }
13328
13714
 
13329
13715
  // src/lib/carousel.ts
13330
- var import_react15 = require("react");
13716
+ var import_react16 = require("react");
13331
13717
  var CAROUSEL_ATTR = "data-ohw-carousel";
13332
13718
  var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
13333
13719
  var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
@@ -13389,8 +13775,8 @@ function applyCarouselNode(key, val) {
13389
13775
  return true;
13390
13776
  }
13391
13777
  function useOhwCarousel(key, initial) {
13392
- const [images, setImages] = (0, import_react15.useState)(initial);
13393
- (0, import_react15.useEffect)(() => {
13778
+ const [images, setImages] = (0, import_react16.useState)(initial);
13779
+ (0, import_react16.useEffect)(() => {
13394
13780
  const el = document.querySelector(
13395
13781
  `[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
13396
13782
  );
@@ -13468,7 +13854,7 @@ function collectEditableNodes(extraContent, root = document) {
13468
13854
  nodes.push({ key, type: "link", text: href });
13469
13855
  }
13470
13856
  if (extraContent) {
13471
- for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
13857
+ for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY, SECTION_ORDER_KEY]) {
13472
13858
  const text = extraContent[key];
13473
13859
  if (typeof text === "string" && text.length > 0) {
13474
13860
  nodes.push({ key, type: "meta", text });
@@ -14964,9 +15350,9 @@ function FloatingToolbar({
14964
15350
  showEditLink,
14965
15351
  onEditLink
14966
15352
  }) {
14967
- const localRef = import_react16.default.useRef(null);
14968
- const [measuredW, setMeasuredW] = import_react16.default.useState(330);
14969
- const setRefs = import_react16.default.useCallback(
15353
+ const localRef = import_react17.default.useRef(null);
15354
+ const [measuredW, setMeasuredW] = import_react17.default.useState(330);
15355
+ const setRefs = import_react17.default.useCallback(
14970
15356
  (node) => {
14971
15357
  localRef.current = node;
14972
15358
  if (typeof elRef === "function") elRef(node);
@@ -14978,7 +15364,7 @@ function FloatingToolbar({
14978
15364
  },
14979
15365
  [elRef]
14980
15366
  );
14981
- import_react16.default.useLayoutEffect(() => {
15367
+ import_react17.default.useLayoutEffect(() => {
14982
15368
  const node = localRef.current;
14983
15369
  if (!node) return;
14984
15370
  const update = () => {
@@ -15004,7 +15390,7 @@ function FloatingToolbar({
15004
15390
  pointerEvents: "auto"
15005
15391
  },
15006
15392
  children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(CustomToolbar, { children: [
15007
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react16.default.Fragment, { children: [
15393
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react17.default.Fragment, { children: [
15008
15394
  gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(CustomToolbarDivider, {}),
15009
15395
  btns.map((btn) => {
15010
15396
  const isActive = activeCommands.has(btn.cmd);
@@ -15089,6 +15475,44 @@ function StateToggle({
15089
15475
  }
15090
15476
  var contentCache = /* @__PURE__ */ new Map();
15091
15477
  var fetchedContentPaths = /* @__PURE__ */ new Set();
15478
+ var OHW_LOADER_STYLE = {
15479
+ position: "fixed",
15480
+ inset: 0,
15481
+ background: "#fff",
15482
+ zIndex: 2147483646,
15483
+ display: "flex",
15484
+ alignItems: "center",
15485
+ justifyContent: "center"
15486
+ };
15487
+ function OhwLoaderSpinner() {
15488
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", "aria-hidden": true, children: [
15489
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("circle", { cx: "14", cy: "14", r: "11", stroke: "#E7E5E4", strokeWidth: "3" }),
15490
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
15491
+ "circle",
15492
+ {
15493
+ cx: "14",
15494
+ cy: "14",
15495
+ r: "11",
15496
+ stroke: "#1C1917",
15497
+ strokeWidth: "3",
15498
+ strokeDasharray: "17 52",
15499
+ strokeLinecap: "round",
15500
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
15501
+ "animateTransform",
15502
+ {
15503
+ attributeName: "transform",
15504
+ type: "rotate",
15505
+ from: "0 14 14",
15506
+ to: "360 14 14",
15507
+ dur: "0.7s",
15508
+ repeatCount: "indefinite"
15509
+ }
15510
+ )
15511
+ }
15512
+ )
15513
+ ] });
15514
+ }
15515
+ var OHW_LOADER_PREHYDRATE_SCRIPT = `(function(){try{var p=location.hostname.split(".");var fromHost=p.length>=3&&p[0]!=="www"?p[0]:"";var fromQuery=new URLSearchParams(location.search).get("subdomain")||"";if(!fromHost&&!fromQuery)return;var e=document.getElementById("ohw-loader");if(e)e.style.display="flex"}catch(e){}})();`;
15092
15516
  function resolveSubdomain(subdomainFromQuery) {
15093
15517
  if (subdomainFromQuery) return subdomainFromQuery;
15094
15518
  if (typeof window !== "undefined") {
@@ -15111,8 +15535,8 @@ function OhhwellsBridge() {
15111
15535
  const router = (0, import_navigation3.useRouter)();
15112
15536
  const searchParams = (0, import_navigation3.useSearchParams)();
15113
15537
  const isEditMode = isEditSessionActive();
15114
- const [bridgeRoot, setBridgeRoot] = (0, import_react16.useState)(null);
15115
- (0, import_react16.useEffect)(() => {
15538
+ const [bridgeRoot, setBridgeRoot] = (0, import_react17.useState)(null);
15539
+ (0, import_react17.useEffect)(() => {
15116
15540
  const figtreeFontId = "ohw-figtree-font";
15117
15541
  if (!document.getElementById(figtreeFontId)) {
15118
15542
  const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
@@ -15141,82 +15565,146 @@ function OhhwellsBridge() {
15141
15565
  const subdomain = resolveSubdomain(subdomainFromQuery);
15142
15566
  useLinkHrefGuardian(pathname, subdomain, isEditMode);
15143
15567
  useSavedLinkNavigation(isEditMode);
15144
- const postToParent2 = (0, import_react16.useCallback)((data) => {
15568
+ const postToParent2 = (0, import_react17.useCallback)((data) => {
15145
15569
  if (typeof window !== "undefined" && window.parent !== window) {
15146
15570
  window.parent.postMessage(data, "*");
15147
15571
  }
15148
15572
  }, []);
15149
- const [fetchState, setFetchState] = (0, import_react16.useState)("idle");
15150
- const autoSaveTimers = (0, import_react16.useRef)(/* @__PURE__ */ new Map());
15151
- const activeElRef = (0, import_react16.useRef)(null);
15152
- const pointerHeldRef = (0, import_react16.useRef)(false);
15153
- const selectedElRef = (0, import_react16.useRef)(null);
15154
- const selectedHrefKeyRef = (0, import_react16.useRef)(null);
15155
- const selectedFooterColAttrRef = (0, import_react16.useRef)(null);
15156
- const originalContentRef = (0, import_react16.useRef)(null);
15157
- const activeStateElRef = (0, import_react16.useRef)(null);
15158
- const parentScrollRef = (0, import_react16.useRef)(null);
15159
- const visibleViewportRef = (0, import_react16.useRef)(null);
15160
- const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react16.useState)(null);
15161
- const attachVisibleViewport = (0, import_react16.useCallback)((node) => {
15573
+ const [fetchState, setFetchState] = (0, import_react17.useState)("idle");
15574
+ const autoSaveTimers = (0, import_react17.useRef)(/* @__PURE__ */ new Map());
15575
+ const activeElRef = (0, import_react17.useRef)(null);
15576
+ const pointerHeldRef = (0, import_react17.useRef)(false);
15577
+ const selectedElRef = (0, import_react17.useRef)(null);
15578
+ const selectedHrefKeyRef = (0, import_react17.useRef)(null);
15579
+ const selectedFooterColAttrRef = (0, import_react17.useRef)(null);
15580
+ const originalContentRef = (0, import_react17.useRef)(null);
15581
+ const activeStateElRef = (0, import_react17.useRef)(null);
15582
+ const parentScrollRef = (0, import_react17.useRef)(null);
15583
+ const visibleViewportRef = (0, import_react17.useRef)(null);
15584
+ const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react17.useState)(null);
15585
+ const attachVisibleViewport = (0, import_react17.useCallback)((node) => {
15162
15586
  visibleViewportRef.current = node;
15163
15587
  setDialogPortalContainer(node);
15164
15588
  if (node) applyVisibleViewport(node, parentScrollRef.current);
15165
15589
  }, []);
15166
- const toolbarElRef = (0, import_react16.useRef)(null);
15167
- const glowElRef = (0, import_react16.useRef)(null);
15168
- const hoveredImageRef = (0, import_react16.useRef)(null);
15169
- const hoveredImageHasTextOverlapRef = (0, import_react16.useRef)(false);
15170
- const dragOverElRef = (0, import_react16.useRef)(null);
15171
- const [mediaHover, setMediaHover] = (0, import_react16.useState)(null);
15172
- const [carouselHover, setCarouselHover] = (0, import_react16.useState)(null);
15173
- const [uploadingRects, setUploadingRects] = (0, import_react16.useState)({});
15174
- const hoveredGapRef = (0, import_react16.useRef)(null);
15175
- const imageUnhoverTimerRef = (0, import_react16.useRef)(null);
15176
- const imageShowTimerRef = (0, import_react16.useRef)(null);
15177
- const editStylesRef = (0, import_react16.useRef)(null);
15178
- const activateRef = (0, import_react16.useRef)(() => {
15590
+ const toolbarElRef = (0, import_react17.useRef)(null);
15591
+ const glowElRef = (0, import_react17.useRef)(null);
15592
+ const hoveredImageRef = (0, import_react17.useRef)(null);
15593
+ const hoveredImageHasTextOverlapRef = (0, import_react17.useRef)(false);
15594
+ const dragOverElRef = (0, import_react17.useRef)(null);
15595
+ const [mediaHover, setMediaHover] = (0, import_react17.useState)(null);
15596
+ const [selectedMedia, setSelectedMedia] = (0, import_react17.useState)(null);
15597
+ const selectedMediaElRef = (0, import_react17.useRef)(null);
15598
+ const clearMediaSelection = (0, import_react17.useCallback)(() => {
15599
+ const prev = selectedMediaElRef.current;
15600
+ selectedMediaElRef.current = null;
15601
+ setSelectedMedia(null);
15602
+ const sectionEl = prev?.closest("[data-ohw-section]") ?? null;
15603
+ if (sectionEl) {
15604
+ postToParentRef.current({
15605
+ type: "ow:section-selected",
15606
+ sectionId: sectionEl.dataset.ohwSection ?? null,
15607
+ sectionLabel: sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? ""),
15608
+ key: null
15609
+ });
15610
+ }
15611
+ }, []);
15612
+ const clearMediaSelectionRef = (0, import_react17.useRef)(clearMediaSelection);
15613
+ clearMediaSelectionRef.current = clearMediaSelection;
15614
+ const selectMediaElement = (0, import_react17.useCallback)((el) => {
15615
+ const r2 = el.getBoundingClientRect();
15616
+ const video = el.dataset.ohwEditable === "video" ? el.querySelector("video") : null;
15617
+ selectedMediaElRef.current = el;
15618
+ setSelectedMedia({
15619
+ key: el.dataset.ohwKey ?? "",
15620
+ rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
15621
+ elementType: el.dataset.ohwEditable ?? "image",
15622
+ hasTextOverlap: false,
15623
+ isDragOver: false,
15624
+ ...video ? { videoAutoplay: video.autoplay, videoMuted: video.muted } : {}
15625
+ });
15626
+ const sectionEl = el.closest("[data-ohw-section]");
15627
+ aiSectionApiRef.current?.selectFromElement(el, { report: false });
15628
+ postToParentRef.current({
15629
+ type: "ow:section-selected",
15630
+ sectionId: sectionEl?.dataset.ohwSection ?? null,
15631
+ sectionLabel: sectionEl ? sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? "") : null,
15632
+ key: el.dataset.ohwKey ?? null,
15633
+ // Display name for the pill — the raw key prettifies into fragments ("Img"); the
15634
+ // bridge knows what the node IS, so it names it.
15635
+ keyLabel: el.dataset.ohwEditable === "video" ? "Video" : "Image"
15636
+ });
15637
+ }, []);
15638
+ const selectMediaElementRef = (0, import_react17.useRef)(selectMediaElement);
15639
+ selectMediaElementRef.current = selectMediaElement;
15640
+ (0, import_react17.useEffect)(() => {
15641
+ if (!selectedMedia) return;
15642
+ const update = () => {
15643
+ const el = selectedMediaElRef.current;
15644
+ if (!el || !el.isConnected) {
15645
+ clearMediaSelection();
15646
+ return;
15647
+ }
15648
+ const r2 = el.getBoundingClientRect();
15649
+ setSelectedMedia(
15650
+ (prev) => prev ? { ...prev, rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } } : prev
15651
+ );
15652
+ };
15653
+ window.addEventListener("scroll", update, true);
15654
+ window.addEventListener("resize", update);
15655
+ return () => {
15656
+ window.removeEventListener("scroll", update, true);
15657
+ window.removeEventListener("resize", update);
15658
+ };
15659
+ }, [selectedMedia !== null]);
15660
+ const [carouselHover, setCarouselHover] = (0, import_react17.useState)(null);
15661
+ const [uploadingRects, setUploadingRects] = (0, import_react17.useState)({});
15662
+ const hoveredGapRef = (0, import_react17.useRef)(null);
15663
+ const imageUnhoverTimerRef = (0, import_react17.useRef)(null);
15664
+ const imageShowTimerRef = (0, import_react17.useRef)(null);
15665
+ const editStylesRef = (0, import_react17.useRef)(null);
15666
+ const activateRef = (0, import_react17.useRef)(() => {
15179
15667
  });
15180
- const deactivateRef = (0, import_react16.useRef)(() => {
15668
+ const deactivateRef = (0, import_react17.useRef)(() => {
15181
15669
  });
15182
- const selectRef = (0, import_react16.useRef)(() => {
15670
+ const selectRef = (0, import_react17.useRef)(() => {
15183
15671
  });
15184
- const selectFrameRef = (0, import_react16.useRef)(() => {
15672
+ const selectFrameRef = (0, import_react17.useRef)(() => {
15185
15673
  });
15186
- const selectLogoRef = (0, import_react16.useRef)(() => {
15674
+ const selectLogoRef = (0, import_react17.useRef)(() => {
15187
15675
  });
15188
- const openLogoSizePanelRef = (0, import_react16.useRef)(() => {
15676
+ const openLogoSizePanelRef = (0, import_react17.useRef)(() => {
15189
15677
  });
15190
- const deselectRef = (0, import_react16.useRef)(() => {
15678
+ const deselectRef = (0, import_react17.useRef)(() => {
15191
15679
  });
15192
- const closeFloatingPanelOnlyRef = (0, import_react16.useRef)(() => {
15680
+ const closeFloatingPanelOnlyRef = (0, import_react17.useRef)(() => {
15193
15681
  });
15194
- const reselectNavigationItemRef = (0, import_react16.useRef)(() => {
15682
+ const reselectNavigationItemRef = (0, import_react17.useRef)(() => {
15195
15683
  });
15196
- const commitNavigationTextEditRef = (0, import_react16.useRef)(() => {
15684
+ const commitNavigationTextEditRef = (0, import_react17.useRef)(() => {
15197
15685
  });
15198
- const handleDeleteSelectedRef = (0, import_react16.useRef)(() => false);
15199
- const runPendingDeleteUndoRef = (0, import_react16.useRef)(() => false);
15200
- const isFooterFrameSelectionRef = (0, import_react16.useRef)(false);
15201
- const refreshActiveCommandsRef = (0, import_react16.useRef)(() => {
15686
+ const handleDeleteSelectedRef = (0, import_react17.useRef)(() => false);
15687
+ const runPendingDeleteUndoRef = (0, import_react17.useRef)(() => false);
15688
+ const isFooterFrameSelectionRef = (0, import_react17.useRef)(false);
15689
+ const refreshActiveCommandsRef = (0, import_react17.useRef)(() => {
15202
15690
  });
15203
- const postToParentRef = (0, import_react16.useRef)(postToParent2);
15691
+ const postToParentRef = (0, import_react17.useRef)(postToParent2);
15204
15692
  postToParentRef.current = postToParent2;
15205
- const aiSectionApiRef = (0, import_react16.useRef)(null);
15206
- const sectionsLoadedRef = (0, import_react16.useRef)(false);
15207
- const pendingScheduleConfigRequests = (0, import_react16.useRef)([]);
15208
- const [toolbarRect, setToolbarRect] = (0, import_react16.useState)(null);
15209
- const [formPickRect, setFormPickRect] = (0, import_react16.useState)(null);
15210
- const formPickElRef = (0, import_react16.useRef)(null);
15211
- const [formViewState, setFormViewStateUi] = (0, import_react16.useState)("default");
15212
- const [formPickCount, setFormPickCount] = (0, import_react16.useState)(null);
15213
- const [formHoverRect, setFormHoverRect] = (0, import_react16.useState)(null);
15214
- const formHoverElRef = (0, import_react16.useRef)(null);
15215
- const [fieldPickRect, setFieldPickRect] = (0, import_react16.useState)(null);
15216
- const fieldPickElRef = (0, import_react16.useRef)(null);
15217
- const [fieldPickState, setFieldPickState] = (0, import_react16.useState)(null);
15218
- const [fieldTypePickerOpen, setFieldTypePickerOpen] = (0, import_react16.useState)(false);
15219
- const clearFormPick = (0, import_react16.useCallback)(() => {
15693
+ const aiSectionApiRef = (0, import_react17.useRef)(null);
15694
+ const sectionsLoadedRef = (0, import_react17.useRef)(false);
15695
+ const pendingScheduleConfigRequests = (0, import_react17.useRef)([]);
15696
+ const [toolbarRect, setToolbarRect] = (0, import_react17.useState)(null);
15697
+ const [formPickRect, setFormPickRect] = (0, import_react17.useState)(null);
15698
+ const formPickElRef = (0, import_react17.useRef)(null);
15699
+ const [formViewState, setFormViewStateUi] = (0, import_react17.useState)("default");
15700
+ const [formPickCount, setFormPickCount] = (0, import_react17.useState)(null);
15701
+ const [formHoverRect, setFormHoverRect] = (0, import_react17.useState)(null);
15702
+ const formHoverElRef = (0, import_react17.useRef)(null);
15703
+ const [fieldPickRect, setFieldPickRect] = (0, import_react17.useState)(null);
15704
+ const fieldPickElRef = (0, import_react17.useRef)(null);
15705
+ const [fieldPickState, setFieldPickState] = (0, import_react17.useState)(null);
15706
+ const [fieldTypePickerOpen, setFieldTypePickerOpen] = (0, import_react17.useState)(false);
15707
+ const clearFormPick = (0, import_react17.useCallback)(() => {
15220
15708
  const form = formPickElRef.current;
15221
15709
  const editing = fieldPickElRef.current;
15222
15710
  if (commitPlaceholderEdit(editing) && editing) {
@@ -15236,7 +15724,7 @@ function OhhwellsBridge() {
15236
15724
  formPickElRef.current = null;
15237
15725
  setFormPickRect(null);
15238
15726
  }, []);
15239
- const clearFieldPick = (0, import_react16.useCallback)(() => {
15727
+ const clearFieldPick = (0, import_react17.useCallback)(() => {
15240
15728
  const wrapper = fieldPickElRef.current;
15241
15729
  if (commitPlaceholderEdit(wrapper) && wrapper) {
15242
15730
  const form = wrapper.closest('[data-ohw-editable="form"]');
@@ -15246,9 +15734,9 @@ function OhhwellsBridge() {
15246
15734
  setFieldPickRect(null);
15247
15735
  setFieldPickState(null);
15248
15736
  }, []);
15249
- const persistFieldsRef = (0, import_react16.useRef)(() => {
15737
+ const persistFieldsRef = (0, import_react17.useRef)(() => {
15250
15738
  });
15251
- const persistFields = (0, import_react16.useCallback)(
15739
+ const persistFields = (0, import_react17.useCallback)(
15252
15740
  (form) => {
15253
15741
  const key = formKeyOf(form);
15254
15742
  if (!key) return;
@@ -15259,7 +15747,7 @@ function OhhwellsBridge() {
15259
15747
  []
15260
15748
  );
15261
15749
  persistFieldsRef.current = persistFields;
15262
- const selectField = (0, import_react16.useCallback)((wrapper) => {
15750
+ const selectField = (0, import_react17.useCallback)((wrapper) => {
15263
15751
  if (fieldPickElRef.current && fieldPickElRef.current !== wrapper) {
15264
15752
  commitPlaceholderEdit(fieldPickElRef.current);
15265
15753
  }
@@ -15272,7 +15760,7 @@ function OhhwellsBridge() {
15272
15760
  setFieldPickState({ type: fieldTypeOf(wrapper), required: isFieldRequired(wrapper) });
15273
15761
  setFieldTypePickerOpen(false);
15274
15762
  }, []);
15275
- const withSelectedField = (0, import_react16.useCallback)(
15763
+ const withSelectedField = (0, import_react17.useCallback)(
15276
15764
  (run) => {
15277
15765
  const wrapper = fieldPickElRef.current;
15278
15766
  const form = formPickElRef.current;
@@ -15285,28 +15773,28 @@ function OhhwellsBridge() {
15285
15773
  },
15286
15774
  [persistFields]
15287
15775
  );
15288
- const handleFieldTypeChange = (0, import_react16.useCallback)(
15776
+ const handleFieldTypeChange = (0, import_react17.useCallback)(
15289
15777
  (type) => withSelectedField((_form, wrapper) => {
15290
15778
  applyFieldType(wrapper, type);
15291
15779
  selectField(wrapper);
15292
15780
  }),
15293
15781
  [selectField, withSelectedField]
15294
15782
  );
15295
- const handleFieldRequiredToggle = (0, import_react16.useCallback)(
15783
+ const handleFieldRequiredToggle = (0, import_react17.useCallback)(
15296
15784
  () => withSelectedField((_form, wrapper) => {
15297
15785
  setFieldRequired(wrapper, !isFieldRequired(wrapper));
15298
15786
  selectField(wrapper);
15299
15787
  }),
15300
15788
  [selectField, withSelectedField]
15301
15789
  );
15302
- const handleFieldDuplicate = (0, import_react16.useCallback)(
15790
+ const handleFieldDuplicate = (0, import_react17.useCallback)(
15303
15791
  () => withSelectedField((form, wrapper) => {
15304
15792
  const copy = duplicateField(form, wrapper);
15305
15793
  selectField(copy);
15306
15794
  }),
15307
15795
  [selectField, withSelectedField]
15308
15796
  );
15309
- const handleFieldDelete = (0, import_react16.useCallback)(
15797
+ const handleFieldDelete = (0, import_react17.useCallback)(
15310
15798
  () => withSelectedField((_form, wrapper) => {
15311
15799
  removeField(wrapper);
15312
15800
  clearFieldPick();
@@ -15314,7 +15802,7 @@ function OhhwellsBridge() {
15314
15802
  }),
15315
15803
  [clearFieldPick, withSelectedField]
15316
15804
  );
15317
- const handleAddField = (0, import_react16.useCallback)(
15805
+ const handleAddField = (0, import_react17.useCallback)(
15318
15806
  (type) => {
15319
15807
  const form = formPickElRef.current;
15320
15808
  if (!form) return;
@@ -15330,8 +15818,8 @@ function OhhwellsBridge() {
15330
15818
  },
15331
15819
  [persistFields, selectField]
15332
15820
  );
15333
- const fieldDragRef = (0, import_react16.useRef)(null);
15334
- const buildFieldDropSlots = (0, import_react16.useCallback)((form, draggedKey) => {
15821
+ const fieldDragRef = (0, import_react17.useRef)(null);
15822
+ const buildFieldDropSlots = (0, import_react17.useCallback)((form, draggedKey) => {
15335
15823
  const others = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== draggedKey);
15336
15824
  const slots = others.map((el) => {
15337
15825
  const rect = el.getBoundingClientRect();
@@ -15344,7 +15832,7 @@ function OhhwellsBridge() {
15344
15832
  }
15345
15833
  return slots;
15346
15834
  }, []);
15347
- const handleFieldDragStart = (0, import_react16.useCallback)(() => {
15835
+ const handleFieldDragStart = (0, import_react17.useCallback)(() => {
15348
15836
  const wrapper = fieldPickElRef.current;
15349
15837
  const form = formPickElRef.current;
15350
15838
  if (!wrapper || !form) return;
@@ -15353,18 +15841,18 @@ function OhhwellsBridge() {
15353
15841
  setFieldDragging(true);
15354
15842
  setFieldDropSlots(buildFieldDropSlots(form, key));
15355
15843
  }, [buildFieldDropSlots]);
15356
- const handleFieldDragEnd = (0, import_react16.useCallback)(() => {
15844
+ const handleFieldDragEnd = (0, import_react17.useCallback)(() => {
15357
15845
  fieldDragRef.current = null;
15358
15846
  setFieldDropIndex(null);
15359
15847
  setFieldDropSlots([]);
15360
15848
  setFieldDragging(false);
15361
15849
  }, []);
15362
- const [fieldDropIndex, setFieldDropIndex] = (0, import_react16.useState)(null);
15363
- const [fieldDropSlots, setFieldDropSlots] = (0, import_react16.useState)([]);
15364
- const [fieldDragging, setFieldDragging] = (0, import_react16.useState)(false);
15365
- const clearFormPickRef = (0, import_react16.useRef)(clearFormPick);
15850
+ const [fieldDropIndex, setFieldDropIndex] = (0, import_react17.useState)(null);
15851
+ const [fieldDropSlots, setFieldDropSlots] = (0, import_react17.useState)([]);
15852
+ const [fieldDragging, setFieldDragging] = (0, import_react17.useState)(false);
15853
+ const clearFormPickRef = (0, import_react17.useRef)(clearFormPick);
15366
15854
  clearFormPickRef.current = clearFormPick;
15367
- (0, import_react16.useEffect)(() => {
15855
+ (0, import_react17.useEffect)(() => {
15368
15856
  const el = fieldPickElRef.current;
15369
15857
  if (!el || fieldPickRect === null) return;
15370
15858
  const observer = new ResizeObserver(() => {
@@ -15373,7 +15861,7 @@ function OhhwellsBridge() {
15373
15861
  observer.observe(el);
15374
15862
  return () => observer.disconnect();
15375
15863
  }, [fieldPickRect !== null, fieldPickState]);
15376
- (0, import_react16.useEffect)(() => {
15864
+ (0, import_react17.useEffect)(() => {
15377
15865
  const el = formPickElRef.current;
15378
15866
  if (!el || formPickRect === null) return;
15379
15867
  const observer = new ResizeObserver(() => {
@@ -15382,25 +15870,25 @@ function OhhwellsBridge() {
15382
15870
  observer.observe(el);
15383
15871
  return () => observer.disconnect();
15384
15872
  }, [formPickRect !== null, formViewState]);
15385
- const [toolbarVariant, setToolbarVariant] = (0, import_react16.useState)("none");
15386
- const toolbarVariantRef = (0, import_react16.useRef)("none");
15873
+ const [toolbarVariant, setToolbarVariant] = (0, import_react17.useState)("none");
15874
+ const toolbarVariantRef = (0, import_react17.useRef)("none");
15387
15875
  toolbarVariantRef.current = toolbarVariant;
15388
- const [selectedIsCta, setSelectedIsCta] = (0, import_react16.useState)(false);
15389
- const [selectedIsSocial, setSelectedIsSocial] = (0, import_react16.useState)(false);
15390
- const [selectedIsSocialsRow, setSelectedIsSocialsRow] = (0, import_react16.useState)(false);
15391
- const [reorderHrefKey, setReorderHrefKey] = (0, import_react16.useState)(null);
15392
- const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react16.useState)(false);
15393
- const [toggleState, setToggleState] = (0, import_react16.useState)(null);
15394
- const [maxBadge, setMaxBadge] = (0, import_react16.useState)(null);
15395
- const [activeCommands, setActiveCommands] = (0, import_react16.useState)(/* @__PURE__ */ new Set());
15396
- const [sectionGap, setSectionGap] = (0, import_react16.useState)(null);
15397
- const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react16.useState)(false);
15398
- const hoveredNavContainerRef = (0, import_react16.useRef)(null);
15399
- const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react16.useState)(null);
15400
- const hoveredItemElRef = (0, import_react16.useRef)(null);
15401
- const [hoveredItemRect, setHoveredItemRect] = (0, import_react16.useState)(null);
15402
- const [hoveredTextRect, setHoveredTextRect] = (0, import_react16.useState)(null);
15403
- (0, import_react16.useEffect)(() => {
15876
+ const [selectedIsCta, setSelectedIsCta] = (0, import_react17.useState)(false);
15877
+ const [selectedIsSocial, setSelectedIsSocial] = (0, import_react17.useState)(false);
15878
+ const [selectedIsSocialsRow, setSelectedIsSocialsRow] = (0, import_react17.useState)(false);
15879
+ const [reorderHrefKey, setReorderHrefKey] = (0, import_react17.useState)(null);
15880
+ const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react17.useState)(false);
15881
+ const [toggleState, setToggleState] = (0, import_react17.useState)(null);
15882
+ const [maxBadge, setMaxBadge] = (0, import_react17.useState)(null);
15883
+ const [activeCommands, setActiveCommands] = (0, import_react17.useState)(/* @__PURE__ */ new Set());
15884
+ const [sectionGap, setSectionGap] = (0, import_react17.useState)(null);
15885
+ const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react17.useState)(false);
15886
+ const hoveredNavContainerRef = (0, import_react17.useRef)(null);
15887
+ const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react17.useState)(null);
15888
+ const hoveredItemElRef = (0, import_react17.useRef)(null);
15889
+ const [hoveredItemRect, setHoveredItemRect] = (0, import_react17.useState)(null);
15890
+ const [hoveredTextRect, setHoveredTextRect] = (0, import_react17.useState)(null);
15891
+ (0, import_react17.useEffect)(() => {
15404
15892
  const sync = () => {
15405
15893
  const el = document.querySelector(
15406
15894
  '[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]):not([data-ohw-editable="form"] *)'
@@ -15421,48 +15909,48 @@ function OhhwellsBridge() {
15421
15909
  });
15422
15910
  return () => observer.disconnect();
15423
15911
  }, []);
15424
- const siblingHintElRef = (0, import_react16.useRef)(null);
15425
- const [siblingHintRect, setSiblingHintRect] = (0, import_react16.useState)(null);
15426
- const [siblingHintRects, setSiblingHintRects] = (0, import_react16.useState)([]);
15427
- const [isItemDragging, setIsItemDragging] = (0, import_react16.useState)(false);
15428
- const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react16.useState)(false);
15912
+ const siblingHintElRef = (0, import_react17.useRef)(null);
15913
+ const [siblingHintRect, setSiblingHintRect] = (0, import_react17.useState)(null);
15914
+ const [siblingHintRects, setSiblingHintRects] = (0, import_react17.useState)([]);
15915
+ const [isItemDragging, setIsItemDragging] = (0, import_react17.useState)(false);
15916
+ const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react17.useState)(false);
15429
15917
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
15430
- const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react16.useState)(null);
15431
- const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react16.useState)(null);
15432
- const footerDragRef = (0, import_react16.useRef)(null);
15433
- const [footerDropSlots, setFooterDropSlots] = (0, import_react16.useState)([]);
15434
- const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react16.useState)(null);
15435
- const [draggedItemRect, setDraggedItemRect] = (0, import_react16.useState)(null);
15436
- const footerPointerDragRef = (0, import_react16.useRef)(null);
15437
- const suppressNextClickRef = (0, import_react16.useRef)(false);
15438
- const suppressClickUntilRef = (0, import_react16.useRef)(0);
15439
- const [linkPopover, setLinkPopover] = (0, import_react16.useState)(null);
15440
- const linkPopoverSessionRef = (0, import_react16.useRef)(null);
15441
- const addNavAfterAnchorRef = (0, import_react16.useRef)(null);
15442
- const editContentRef = (0, import_react16.useRef)({});
15443
- const aiSectionsRef = (0, import_react16.useRef)("");
15444
- const brandKitRef = (0, import_react16.useRef)("");
15445
- const stylesRef = (0, import_react16.useRef)("");
15446
- const pendingDeleteUndoRef = (0, import_react16.useRef)(null);
15447
- const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
15448
- const floatingPanelOpenRef = (0, import_react16.useRef)(false);
15449
- const setFloatingPanelRef = (0, import_react16.useRef)(setFloatingPanel);
15450
- const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
15451
- const [logoSizeDraft, setLogoSizeDraft] = (0, import_react16.useState)(null);
15452
- const [editorViewport, setEditorViewport] = (0, import_react16.useState)("desktop");
15453
- const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
15454
- const [sitePages, setSitePages] = (0, import_react16.useState)([]);
15455
- const [sectionsByPath, setSectionsByPath] = (0, import_react16.useState)({});
15456
- const sectionsPrefetchGenRef = (0, import_react16.useRef)(0);
15457
- const setLinkPopoverRef = (0, import_react16.useRef)(setLinkPopover);
15458
- const linkPopoverPanelRef = (0, import_react16.useRef)(null);
15459
- const linkPopoverOpenRef = (0, import_react16.useRef)(false);
15460
- const linkPopoverGraceUntilRef = (0, import_react16.useRef)(0);
15918
+ const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react17.useState)(null);
15919
+ const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react17.useState)(null);
15920
+ const footerDragRef = (0, import_react17.useRef)(null);
15921
+ const [footerDropSlots, setFooterDropSlots] = (0, import_react17.useState)([]);
15922
+ const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react17.useState)(null);
15923
+ const [draggedItemRect, setDraggedItemRect] = (0, import_react17.useState)(null);
15924
+ const footerPointerDragRef = (0, import_react17.useRef)(null);
15925
+ const suppressNextClickRef = (0, import_react17.useRef)(false);
15926
+ const suppressClickUntilRef = (0, import_react17.useRef)(0);
15927
+ const [linkPopover, setLinkPopover] = (0, import_react17.useState)(null);
15928
+ const linkPopoverSessionRef = (0, import_react17.useRef)(null);
15929
+ const addNavAfterAnchorRef = (0, import_react17.useRef)(null);
15930
+ const editContentRef = (0, import_react17.useRef)({});
15931
+ const aiSectionsRef = (0, import_react17.useRef)("");
15932
+ const brandKitRef = (0, import_react17.useRef)("");
15933
+ const stylesRef = (0, import_react17.useRef)("");
15934
+ const pendingDeleteUndoRef = (0, import_react17.useRef)(null);
15935
+ const [floatingPanel, setFloatingPanel] = (0, import_react17.useState)(null);
15936
+ const floatingPanelOpenRef = (0, import_react17.useRef)(false);
15937
+ const setFloatingPanelRef = (0, import_react17.useRef)(setFloatingPanel);
15938
+ const [floatingPanelPos, setFloatingPanelPos] = (0, import_react17.useState)(null);
15939
+ const [logoSizeDraft, setLogoSizeDraft] = (0, import_react17.useState)(null);
15940
+ const [editorViewport, setEditorViewport] = (0, import_react17.useState)("desktop");
15941
+ const [parentScrollSnap, setParentScrollSnap] = (0, import_react17.useState)(null);
15942
+ const [sitePages, setSitePages] = (0, import_react17.useState)([]);
15943
+ const [sectionsByPath, setSectionsByPath] = (0, import_react17.useState)({});
15944
+ const sectionsPrefetchGenRef = (0, import_react17.useRef)(0);
15945
+ const setLinkPopoverRef = (0, import_react17.useRef)(setLinkPopover);
15946
+ const linkPopoverPanelRef = (0, import_react17.useRef)(null);
15947
+ const linkPopoverOpenRef = (0, import_react17.useRef)(false);
15948
+ const linkPopoverGraceUntilRef = (0, import_react17.useRef)(0);
15461
15949
  setLinkPopoverRef.current = setLinkPopover;
15462
15950
  setFloatingPanelRef.current = setFloatingPanel;
15463
15951
  linkPopoverSessionRef.current = linkPopover;
15464
15952
  floatingPanelOpenRef.current = Boolean(floatingPanel);
15465
- (0, import_react16.useEffect)(() => {
15953
+ (0, import_react17.useEffect)(() => {
15466
15954
  const syncViewport = () => {
15467
15955
  const next = window.innerWidth <= 480 ? "mobile" : "desktop";
15468
15956
  setEditorViewport((prev) => prev === next ? prev : next);
@@ -15503,10 +15991,20 @@ function OhhwellsBridge() {
15503
15991
  getNavigationItemAnchor,
15504
15992
  isDragHandleDisabled
15505
15993
  });
15994
+ const { sectionDropSlots, activeSectionDropIndex, isSectionDragging } = useSectionDrag({
15995
+ isEditMode,
15996
+ editContentRef,
15997
+ postToParentRef,
15998
+ parentScrollRef,
15999
+ navDragRef,
16000
+ footerDragRef,
16001
+ suppressNextClickRef,
16002
+ suppressClickUntilRef
16003
+ });
15506
16004
  const bumpLinkPopoverGrace = () => {
15507
16005
  linkPopoverGraceUntilRef.current = Date.now() + 350;
15508
16006
  };
15509
- const runSectionsPrefetch = (0, import_react16.useCallback)((pages) => {
16007
+ const runSectionsPrefetch = (0, import_react17.useCallback)((pages) => {
15510
16008
  if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
15511
16009
  const gen = ++sectionsPrefetchGenRef.current;
15512
16010
  const paths = pages.map((p) => p.path);
@@ -15525,9 +16023,9 @@ function OhhwellsBridge() {
15525
16023
  );
15526
16024
  });
15527
16025
  }, [isEditMode, pathname]);
15528
- const runSectionsPrefetchRef = (0, import_react16.useRef)(runSectionsPrefetch);
16026
+ const runSectionsPrefetchRef = (0, import_react17.useRef)(runSectionsPrefetch);
15529
16027
  runSectionsPrefetchRef.current = runSectionsPrefetch;
15530
- (0, import_react16.useEffect)(() => {
16028
+ (0, import_react17.useEffect)(() => {
15531
16029
  if (!linkPopover) {
15532
16030
  document.documentElement.removeAttribute("data-ohw-link-popover-open");
15533
16031
  return;
@@ -15555,7 +16053,7 @@ function OhhwellsBridge() {
15555
16053
  document.documentElement.removeAttribute("data-ohw-link-popover-open");
15556
16054
  };
15557
16055
  }, [linkPopover, postToParent2]);
15558
- (0, import_react16.useEffect)(() => {
16056
+ (0, import_react17.useEffect)(() => {
15559
16057
  if (!isEditMode) return;
15560
16058
  const useFixtures = shouldUseDevFixtures();
15561
16059
  if (useFixtures) {
@@ -15579,14 +16077,14 @@ function OhhwellsBridge() {
15579
16077
  if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
15580
16078
  return () => window.removeEventListener("message", onSitePages);
15581
16079
  }, [isEditMode, postToParent2]);
15582
- (0, import_react16.useEffect)(() => {
16080
+ (0, import_react17.useEffect)(() => {
15583
16081
  if (!isEditMode || shouldUseDevFixtures()) return;
15584
16082
  void loadAllSectionsManifest().then((manifest) => {
15585
16083
  if (Object.keys(manifest).length === 0) return;
15586
16084
  setSectionsByPath((prev) => ({ ...manifest, ...prev }));
15587
16085
  });
15588
16086
  }, [isEditMode]);
15589
- (0, import_react16.useEffect)(() => {
16087
+ (0, import_react17.useEffect)(() => {
15590
16088
  const update = () => {
15591
16089
  const el = activeElRef.current ?? selectedElRef.current;
15592
16090
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
@@ -15610,10 +16108,10 @@ function OhhwellsBridge() {
15610
16108
  vvp.removeEventListener("resize", update);
15611
16109
  };
15612
16110
  }, []);
15613
- const refreshStateRules = (0, import_react16.useCallback)(() => {
16111
+ const refreshStateRules = (0, import_react17.useCallback)(() => {
15614
16112
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
15615
16113
  }, []);
15616
- const processConfigRequest = (0, import_react16.useCallback)((insertAfterVal) => {
16114
+ const processConfigRequest = (0, import_react17.useCallback)((insertAfterVal) => {
15617
16115
  const tracker = getSectionsTracker();
15618
16116
  let entries = [];
15619
16117
  try {
@@ -15636,7 +16134,7 @@ function OhhwellsBridge() {
15636
16134
  }
15637
16135
  window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
15638
16136
  }, [isEditMode]);
15639
- const deactivate = (0, import_react16.useCallback)(() => {
16137
+ const deactivate = (0, import_react17.useCallback)(() => {
15640
16138
  const el = activeElRef.current;
15641
16139
  if (!el) return;
15642
16140
  const isFormBlock = el.dataset.ohwEditable === "form";
@@ -15677,12 +16175,12 @@ function OhhwellsBridge() {
15677
16175
  setToolbarShowEditLink(false);
15678
16176
  postToParent2({ type: "ow:exit-edit" });
15679
16177
  }, [postToParent2]);
15680
- const clearSelectedAttr = (0, import_react16.useCallback)(() => {
16178
+ const clearSelectedAttr = (0, import_react17.useCallback)(() => {
15681
16179
  document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
15682
16180
  el.removeAttribute("data-ohw-selected");
15683
16181
  });
15684
16182
  }, []);
15685
- const deselect = (0, import_react16.useCallback)(() => {
16183
+ const deselect = (0, import_react17.useCallback)(() => {
15686
16184
  clearSelectedAttr();
15687
16185
  selectedElRef.current = null;
15688
16186
  selectedHrefKeyRef.current = null;
@@ -15711,11 +16209,11 @@ function OhhwellsBridge() {
15711
16209
  setToolbarVariant("none");
15712
16210
  }
15713
16211
  }, [clearSelectedAttr]);
15714
- const markSelected = (0, import_react16.useCallback)((el) => {
16212
+ const markSelected = (0, import_react17.useCallback)((el) => {
15715
16213
  clearSelectedAttr();
15716
16214
  el.setAttribute("data-ohw-selected", "");
15717
16215
  }, [clearSelectedAttr]);
15718
- const resolveHrefKeyElement = (0, import_react16.useCallback)((hrefKey) => {
16216
+ const resolveHrefKeyElement = (0, import_react17.useCallback)((hrefKey) => {
15719
16217
  if (isFooterHrefKey(hrefKey)) {
15720
16218
  return document.querySelector(
15721
16219
  `footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
@@ -15730,7 +16228,7 @@ function OhhwellsBridge() {
15730
16228
  `[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
15731
16229
  );
15732
16230
  }, []);
15733
- const resyncSelectedNavigationItem = (0, import_react16.useCallback)(() => {
16231
+ const resyncSelectedNavigationItem = (0, import_react17.useCallback)(() => {
15734
16232
  const hrefKey = selectedHrefKeyRef.current;
15735
16233
  if (hrefKey) {
15736
16234
  const link = resolveHrefKeyElement(hrefKey);
@@ -15768,7 +16266,7 @@ function OhhwellsBridge() {
15768
16266
  );
15769
16267
  }
15770
16268
  }, [resolveHrefKeyElement]);
15771
- const reselectNavigationItem = (0, import_react16.useCallback)((navAnchor) => {
16269
+ const reselectNavigationItem = (0, import_react17.useCallback)((navAnchor) => {
15772
16270
  selectedElRef.current = navAnchor;
15773
16271
  selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
15774
16272
  selectedFooterColAttrRef.current = null;
@@ -15799,7 +16297,7 @@ function OhhwellsBridge() {
15799
16297
  setToolbarShowEditLink(false);
15800
16298
  setActiveCommands(/* @__PURE__ */ new Set());
15801
16299
  }, [markSelected]);
15802
- const commitNavigationTextEdit = (0, import_react16.useCallback)((navAnchor) => {
16300
+ const commitNavigationTextEdit = (0, import_react17.useCallback)((navAnchor) => {
15803
16301
  const el = activeElRef.current;
15804
16302
  if (!el) return;
15805
16303
  const key = el.dataset.ohwKey;
@@ -15832,7 +16330,7 @@ function OhhwellsBridge() {
15832
16330
  postToParent2({ type: "ow:exit-edit" });
15833
16331
  reselectNavigationItem(navAnchor);
15834
16332
  }, [postToParent2, reselectNavigationItem]);
15835
- const handleAddTopLevelNavItem = (0, import_react16.useCallback)(() => {
16333
+ const handleAddTopLevelNavItem = (0, import_react17.useCallback)(() => {
15836
16334
  const items = listNavbarRootItems();
15837
16335
  addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
15838
16336
  deselectRef.current();
@@ -15844,7 +16342,7 @@ function OhhwellsBridge() {
15844
16342
  intent: "add-nav"
15845
16343
  });
15846
16344
  }, []);
15847
- const maybeWarnNavLinkDropdownConflict = (0, import_react16.useCallback)(
16345
+ const maybeWarnNavLinkDropdownConflict = (0, import_react17.useCallback)(
15848
16346
  (anchor) => {
15849
16347
  if (!isNavbarHrefKey(anchor.getAttribute("data-ohw-href-key"))) return;
15850
16348
  if (!navDropdownsOpenOnClick()) return;
@@ -15857,7 +16355,7 @@ function OhhwellsBridge() {
15857
16355
  },
15858
16356
  [postToParent2]
15859
16357
  );
15860
- const handleNavDropdownOpenChange = (0, import_react16.useCallback)((open) => {
16358
+ const handleNavDropdownOpenChange = (0, import_react17.useCallback)((open) => {
15861
16359
  const selected = selectedElRef.current;
15862
16360
  if (!selected || !isNavigationItem2(selected)) return;
15863
16361
  setNavGroupForceOpen(selected, open);
@@ -15869,7 +16367,7 @@ function OhhwellsBridge() {
15869
16367
  }
15870
16368
  });
15871
16369
  }, []);
15872
- const handleFooterHeadingVisibleChange = (0, import_react16.useCallback)(
16370
+ const handleFooterHeadingVisibleChange = (0, import_react17.useCallback)(
15873
16371
  (visible) => {
15874
16372
  const selected = selectedElRef.current;
15875
16373
  if (!selected || !isFooterFrameSelectionRef.current) return;
@@ -15893,7 +16391,7 @@ function OhhwellsBridge() {
15893
16391
  },
15894
16392
  [postToParent2]
15895
16393
  );
15896
- const enterEditOnNewItem = (0, import_react16.useCallback)((anchor) => {
16394
+ const enterEditOnNewItem = (0, import_react17.useCallback)((anchor) => {
15897
16395
  const label = anchor.querySelector('[data-ohw-editable="text"]');
15898
16396
  if (!label) {
15899
16397
  selectRef.current(anchor);
@@ -15902,7 +16400,7 @@ function OhhwellsBridge() {
15902
16400
  setNavGroupForceOpen(anchor, true);
15903
16401
  activateRef.current(label);
15904
16402
  }, []);
15905
- const handleAddChildItem = (0, import_react16.useCallback)(() => {
16403
+ const handleAddChildItem = (0, import_react17.useCallback)(() => {
15906
16404
  const selected = selectedElRef.current;
15907
16405
  if (!selected) return;
15908
16406
  const socialsRow = isSocialsRow(selected) ? selected : findSocialsRow(selected);
@@ -16014,7 +16512,7 @@ function OhhwellsBridge() {
16014
16512
  enterEditOnNewItem(result.anchor);
16015
16513
  });
16016
16514
  }, [enterEditOnNewItem, isFooterFrameSelection, maybeWarnNavLinkDropdownConflict, postToParent2]);
16017
- const handleAddFooterColumn = (0, import_react16.useCallback)(() => {
16515
+ const handleAddFooterColumn = (0, import_react17.useCallback)(() => {
16018
16516
  if (!canAddFooterColumn()) {
16019
16517
  postToParent2({
16020
16518
  type: "ow:toast",
@@ -16035,7 +16533,7 @@ function OhhwellsBridge() {
16035
16533
  selectRef.current(result.firstLink);
16036
16534
  });
16037
16535
  }, [postToParent2]);
16038
- const clearFooterDragVisuals = (0, import_react16.useCallback)(() => {
16536
+ const clearFooterDragVisuals = (0, import_react17.useCallback)(() => {
16039
16537
  footerDragRef.current = null;
16040
16538
  setSiblingHintRects([]);
16041
16539
  setFooterDropSlots([]);
@@ -16044,7 +16542,7 @@ function OhhwellsBridge() {
16044
16542
  setIsItemDragging(false);
16045
16543
  unlockFooterDragInteraction();
16046
16544
  }, []);
16047
- const refreshFooterDragVisuals = (0, import_react16.useCallback)((session, activeSlot, clientX, clientY) => {
16545
+ const refreshFooterDragVisuals = (0, import_react17.useCallback)((session, activeSlot, clientX, clientY) => {
16048
16546
  const dragged = session.draggedEl;
16049
16547
  setDraggedItemRect(dragged.getBoundingClientRect());
16050
16548
  if (typeof clientX === "number" && typeof clientY === "number") {
@@ -16076,13 +16574,13 @@ function OhhwellsBridge() {
16076
16574
  const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
16077
16575
  setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
16078
16576
  }, []);
16079
- const refreshFooterDragVisualsRef = (0, import_react16.useRef)(refreshFooterDragVisuals);
16577
+ const refreshFooterDragVisualsRef = (0, import_react17.useRef)(refreshFooterDragVisuals);
16080
16578
  refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
16081
- const commitFooterDragRef = (0, import_react16.useRef)(() => {
16579
+ const commitFooterDragRef = (0, import_react17.useRef)(() => {
16082
16580
  });
16083
- const beginFooterDragRef = (0, import_react16.useRef)(() => {
16581
+ const beginFooterDragRef = (0, import_react17.useRef)(() => {
16084
16582
  });
16085
- const beginFooterDrag = (0, import_react16.useCallback)(
16583
+ const beginFooterDrag = (0, import_react17.useCallback)(
16086
16584
  (session) => {
16087
16585
  const rect = session.draggedEl.getBoundingClientRect();
16088
16586
  session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
@@ -16102,7 +16600,7 @@ function OhhwellsBridge() {
16102
16600
  [refreshFooterDragVisuals]
16103
16601
  );
16104
16602
  beginFooterDragRef.current = beginFooterDrag;
16105
- const commitFooterDrag = (0, import_react16.useCallback)(
16603
+ const commitFooterDrag = (0, import_react17.useCallback)(
16106
16604
  (clientX, clientY) => {
16107
16605
  const session = footerDragRef.current;
16108
16606
  if (!session) {
@@ -16230,7 +16728,7 @@ function OhhwellsBridge() {
16230
16728
  [clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
16231
16729
  );
16232
16730
  commitFooterDragRef.current = commitFooterDrag;
16233
- const startFooterLinkDrag = (0, import_react16.useCallback)(
16731
+ const startFooterLinkDrag = (0, import_react17.useCallback)(
16234
16732
  (anchor, clientX, clientY, wasSelected) => {
16235
16733
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
16236
16734
  if (!hrefKey) return false;
@@ -16266,7 +16764,7 @@ function OhhwellsBridge() {
16266
16764
  },
16267
16765
  [beginFooterDrag]
16268
16766
  );
16269
- const startFooterColumnDrag = (0, import_react16.useCallback)(
16767
+ const startFooterColumnDrag = (0, import_react17.useCallback)(
16270
16768
  (columnEl, clientX, clientY, wasSelected) => {
16271
16769
  const columns = listFooterColumns();
16272
16770
  const idx = columns.indexOf(columnEl);
@@ -16286,7 +16784,7 @@ function OhhwellsBridge() {
16286
16784
  },
16287
16785
  [beginFooterDrag]
16288
16786
  );
16289
- const handleItemDragStart = (0, import_react16.useCallback)(
16787
+ const handleItemDragStart = (0, import_react17.useCallback)(
16290
16788
  (e) => {
16291
16789
  const selected = selectedElRef.current;
16292
16790
  if (!selected) {
@@ -16306,7 +16804,7 @@ function OhhwellsBridge() {
16306
16804
  },
16307
16805
  [startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
16308
16806
  );
16309
- const handleItemDragEnd = (0, import_react16.useCallback)(
16807
+ const handleItemDragEnd = (0, import_react17.useCallback)(
16310
16808
  (e) => {
16311
16809
  if (footerDragRef.current) {
16312
16810
  const x = e?.clientX;
@@ -16332,7 +16830,7 @@ function OhhwellsBridge() {
16332
16830
  },
16333
16831
  [commitFooterDrag, commitNavDrag, navDragRef]
16334
16832
  );
16335
- const handleItemChromePointerDown = (0, import_react16.useCallback)((e) => {
16833
+ const handleItemChromePointerDown = (0, import_react17.useCallback)((e) => {
16336
16834
  if (e.button !== 0) return;
16337
16835
  const selected = selectedElRef.current;
16338
16836
  if (!selected) return;
@@ -16363,7 +16861,7 @@ function OhhwellsBridge() {
16363
16861
  }
16364
16862
  if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
16365
16863
  }, [armNavPressFromChrome]);
16366
- const handleItemChromeClick = (0, import_react16.useCallback)((clientX, clientY) => {
16864
+ const handleItemChromeClick = (0, import_react17.useCallback)((clientX, clientY) => {
16367
16865
  if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
16368
16866
  suppressNextClickRef.current = false;
16369
16867
  return;
@@ -16376,7 +16874,7 @@ function OhhwellsBridge() {
16376
16874
  }, []);
16377
16875
  reselectNavigationItemRef.current = reselectNavigationItem;
16378
16876
  commitNavigationTextEditRef.current = commitNavigationTextEdit;
16379
- const select = (0, import_react16.useCallback)((anchor) => {
16877
+ const select = (0, import_react17.useCallback)((anchor) => {
16380
16878
  if (!isNavigationItem2(anchor)) return;
16381
16879
  if (activeElRef.current) deactivate();
16382
16880
  aiSectionApiRef.current?.selectFromElement(anchor);
@@ -16419,7 +16917,7 @@ function OhhwellsBridge() {
16419
16917
  setFloatingPanel(null);
16420
16918
  setLogoSizeDraft(null);
16421
16919
  }, [deactivate, markSelected]);
16422
- const selectFrame = (0, import_react16.useCallback)((el) => {
16920
+ const selectFrame = (0, import_react17.useCallback)((el) => {
16423
16921
  if (!isNavigationContainer(el)) return;
16424
16922
  if (activeElRef.current) deactivate();
16425
16923
  aiSectionApiRef.current?.selectFromElement(el);
@@ -16470,7 +16968,7 @@ function OhhwellsBridge() {
16470
16968
  setFloatingPanel(null);
16471
16969
  setLogoSizeDraft(null);
16472
16970
  }, [deactivate, markSelected, postToParent2]);
16473
- const selectLogo = (0, import_react16.useCallback)(
16971
+ const selectLogo = (0, import_react17.useCallback)(
16474
16972
  (logoEl) => {
16475
16973
  if (activeElRef.current) deactivate();
16476
16974
  selectedElRef.current = logoEl;
@@ -16499,7 +16997,7 @@ function OhhwellsBridge() {
16499
16997
  },
16500
16998
  [deactivate, markSelected]
16501
16999
  );
16502
- const openLogoSizePanel = (0, import_react16.useCallback)((logoEl) => {
17000
+ const openLogoSizePanel = (0, import_react17.useCallback)((logoEl) => {
16503
17001
  const placement = getLogoPlacement(logoEl);
16504
17002
  const draft = readLogoSizeState(editContentRef.current, placement);
16505
17003
  setLogoSizeDraft(draft);
@@ -16512,7 +17010,7 @@ function OhhwellsBridge() {
16512
17010
  placement
16513
17011
  });
16514
17012
  }, []);
16515
- const openSocialsDisplayPanel = (0, import_react16.useCallback)((row) => {
17013
+ const openSocialsDisplayPanel = (0, import_react17.useCallback)((row) => {
16516
17014
  setParentScrollSnap(parentScrollRef.current);
16517
17015
  setFloatingPanel({
16518
17016
  key: "socials-display",
@@ -16522,7 +17020,7 @@ function OhhwellsBridge() {
16522
17020
  row
16523
17021
  });
16524
17022
  }, []);
16525
- const changeSocialsDisplay = (0, import_react16.useCallback)(
17023
+ const changeSocialsDisplay = (0, import_react17.useCallback)(
16526
17024
  (row, next) => {
16527
17025
  if (next.icon) {
16528
17026
  const missing = socialsMissingIcons(row);
@@ -16545,17 +17043,17 @@ function OhhwellsBridge() {
16545
17043
  },
16546
17044
  []
16547
17045
  );
16548
- const closeFloatingPanelOnly = (0, import_react16.useCallback)(() => {
17046
+ const closeFloatingPanelOnly = (0, import_react17.useCallback)(() => {
16549
17047
  setFloatingPanel(null);
16550
17048
  setLogoSizeDraft(null);
16551
17049
  }, []);
16552
17050
  closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
16553
- const closeFloatingPanelAndDeselect = (0, import_react16.useCallback)(() => {
17051
+ const closeFloatingPanelAndDeselect = (0, import_react17.useCallback)(() => {
16554
17052
  setFloatingPanel(null);
16555
17053
  setLogoSizeDraft(null);
16556
17054
  deselectRef.current();
16557
17055
  }, []);
16558
- const persistLogoSizeDraft = (0, import_react16.useCallback)(
17056
+ const persistLogoSizeDraft = (0, import_react17.useCallback)(
16559
17057
  (placement, draft) => {
16560
17058
  const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
16561
17059
  const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
@@ -16595,7 +17093,7 @@ function OhhwellsBridge() {
16595
17093
  },
16596
17094
  [postToParent2]
16597
17095
  );
16598
- const activate = (0, import_react16.useCallback)((el, options) => {
17096
+ const activate = (0, import_react17.useCallback)((el, options) => {
16599
17097
  if (activeElRef.current === el) return;
16600
17098
  if (isIconEditable(el)) return;
16601
17099
  if (el.hasAttribute("data-ohw-social-label")) return;
@@ -16679,8 +17177,8 @@ function OhhwellsBridge() {
16679
17177
  openLogoSizePanelRef.current = openLogoSizePanel;
16680
17178
  deselectRef.current = deselect;
16681
17179
  closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
16682
- const lastSiteWideScopeRef = (0, import_react16.useRef)(null);
16683
- (0, import_react16.useEffect)(() => {
17180
+ const lastSiteWideScopeRef = (0, import_react17.useRef)(null);
17181
+ (0, import_react17.useEffect)(() => {
16684
17182
  if (!isEditMode) {
16685
17183
  if (lastSiteWideScopeRef.current !== false) {
16686
17184
  lastSiteWideScopeRef.current = false;
@@ -16706,7 +17204,7 @@ function OhhwellsBridge() {
16706
17204
  isFooterFrameSelection,
16707
17205
  postToParent2
16708
17206
  ]);
16709
- (0, import_react16.useLayoutEffect)(() => {
17207
+ (0, import_react17.useLayoutEffect)(() => {
16710
17208
  if (!subdomain || isEditMode) {
16711
17209
  setFetchState("done");
16712
17210
  return;
@@ -16806,7 +17304,7 @@ function OhhwellsBridge() {
16806
17304
  cancelled = true;
16807
17305
  };
16808
17306
  }, [subdomain, isEditMode]);
16809
- (0, import_react16.useEffect)(() => {
17307
+ (0, import_react17.useEffect)(() => {
16810
17308
  if (!isEditMode) return;
16811
17309
  const resolveIndex = (form, clientY) => {
16812
17310
  const wrappers = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== fieldDragRef.current?.key);
@@ -16847,7 +17345,7 @@ function OhhwellsBridge() {
16847
17345
  window.removeEventListener("drop", onDrop, true);
16848
17346
  };
16849
17347
  }, [buildFieldDropSlots, isEditMode, persistFields, selectField]);
16850
- (0, import_react16.useEffect)(() => {
17348
+ (0, import_react17.useEffect)(() => {
16851
17349
  if (!isEditMode) return;
16852
17350
  const mark = () => document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
16853
17351
  markFormFields(form);
@@ -16859,7 +17357,7 @@ function OhhwellsBridge() {
16859
17357
  });
16860
17358
  return () => observer.disconnect();
16861
17359
  }, [isEditMode, fetchState, pathname]);
16862
- (0, import_react16.useEffect)(() => {
17360
+ (0, import_react17.useEffect)(() => {
16863
17361
  if (!isEditMode) return;
16864
17362
  let saveTimer = null;
16865
17363
  const onInput = (e) => {
@@ -16881,14 +17379,14 @@ function OhhwellsBridge() {
16881
17379
  document.addEventListener("input", onInput, true);
16882
17380
  return () => document.removeEventListener("input", onInput, true);
16883
17381
  }, [isEditMode, persistFields]);
16884
- (0, import_react16.useEffect)(() => {
17382
+ (0, import_react17.useEffect)(() => {
16885
17383
  if (isEditMode || fetchState !== "done") return;
16886
17384
  const content = contentCache.get(subdomain) ?? {};
16887
17385
  document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
16888
17386
  reconcileFieldsFromContent(form, content);
16889
17387
  });
16890
17388
  }, [isEditMode, fetchState, subdomain]);
16891
- (0, import_react16.useEffect)(() => {
17389
+ (0, import_react17.useEffect)(() => {
16892
17390
  if (!isEditMode) return;
16893
17391
  const swallow = (e) => {
16894
17392
  const target = e.target;
@@ -16897,12 +17395,12 @@ function OhhwellsBridge() {
16897
17395
  document.addEventListener("submit", swallow, true);
16898
17396
  return () => document.removeEventListener("submit", swallow, true);
16899
17397
  }, [isEditMode]);
16900
- (0, import_react16.useEffect)(() => {
17398
+ (0, import_react17.useEffect)(() => {
16901
17399
  if (isEditMode || fetchState !== "done") return;
16902
17400
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
16903
17401
  bindPublishedForms(apiUrl, subdomain, contentCache.get(subdomain) ?? {});
16904
17402
  }, [isEditMode, fetchState, subdomain]);
16905
- (0, import_react16.useEffect)(() => {
17403
+ (0, import_react17.useEffect)(() => {
16906
17404
  if (!subdomain || isEditMode) return;
16907
17405
  let debounceTimer = null;
16908
17406
  let observer = null;
@@ -16988,16 +17486,16 @@ function OhhwellsBridge() {
16988
17486
  if (debounceTimer) clearTimeout(debounceTimer);
16989
17487
  };
16990
17488
  }, [subdomain, isEditMode, pathname]);
16991
- (0, import_react16.useLayoutEffect)(() => {
17489
+ (0, import_react17.useLayoutEffect)(() => {
16992
17490
  const el = document.getElementById("ohw-loader");
16993
17491
  if (!el) return;
16994
17492
  const visible = Boolean(subdomain) && fetchState !== "done";
16995
17493
  el.style.display = visible ? "flex" : "none";
16996
17494
  }, [subdomain, fetchState]);
16997
- (0, import_react16.useEffect)(() => {
17495
+ (0, import_react17.useEffect)(() => {
16998
17496
  postToParent2({ type: "ow:navigation", path: pathname });
16999
17497
  }, [pathname, postToParent2]);
17000
- (0, import_react16.useEffect)(() => {
17498
+ (0, import_react17.useEffect)(() => {
17001
17499
  if (!isEditMode) return;
17002
17500
  if (linkPopoverSessionRef.current?.intent === "add-nav") return;
17003
17501
  if (document.querySelector("[data-ohw-section-picker]")) return;
@@ -17005,7 +17503,7 @@ function OhhwellsBridge() {
17005
17503
  deselectRef.current();
17006
17504
  deactivateRef.current();
17007
17505
  }, [pathname, isEditMode]);
17008
- (0, import_react16.useEffect)(() => {
17506
+ (0, import_react17.useEffect)(() => {
17009
17507
  const contentForNav = () => {
17010
17508
  if (isEditMode) return editContentRef.current;
17011
17509
  if (!subdomain) return {};
@@ -17072,7 +17570,7 @@ function OhhwellsBridge() {
17072
17570
  observer?.disconnect();
17073
17571
  };
17074
17572
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
17075
- (0, import_react16.useEffect)(() => {
17573
+ (0, import_react17.useEffect)(() => {
17076
17574
  if (!isEditMode) return;
17077
17575
  let lastPosted = 0;
17078
17576
  const measure = () => {
@@ -17101,7 +17599,7 @@ function OhhwellsBridge() {
17101
17599
  ro.disconnect();
17102
17600
  };
17103
17601
  }, [pathname, isEditMode, postToParent2]);
17104
- (0, import_react16.useEffect)(() => {
17602
+ (0, import_react17.useEffect)(() => {
17105
17603
  if (!subdomainFromQuery || isEditMode) return;
17106
17604
  const handleClick = (e) => {
17107
17605
  const anchor = e.target.closest("a");
@@ -17117,7 +17615,7 @@ function OhhwellsBridge() {
17117
17615
  document.addEventListener("click", handleClick, true);
17118
17616
  return () => document.removeEventListener("click", handleClick, true);
17119
17617
  }, [subdomainFromQuery, isEditMode, router]);
17120
- (0, import_react16.useEffect)(() => {
17618
+ (0, import_react17.useEffect)(() => {
17121
17619
  if (!isEditMode) {
17122
17620
  editStylesRef.current?.base.remove();
17123
17621
  editStylesRef.current?.forceHover.remove();
@@ -17291,6 +17789,9 @@ function OhhwellsBridge() {
17291
17789
  )) {
17292
17790
  return;
17293
17791
  }
17792
+ if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
17793
+ clearMediaSelectionRef.current();
17794
+ }
17294
17795
  {
17295
17796
  const formEl = getFormElement(target);
17296
17797
  const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
@@ -17438,8 +17939,11 @@ function OhhwellsBridge() {
17438
17939
  if (isMediaEditable(editable) && !buttonOnMedia) {
17439
17940
  e.preventDefault();
17440
17941
  e.stopPropagation();
17441
- aiSectionApiRef.current?.selectFromElement(editable);
17442
- postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
17942
+ if (selectedMediaElRef.current === editable) {
17943
+ postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
17944
+ } else {
17945
+ selectMediaElementRef.current(editable);
17946
+ }
17443
17947
  return;
17444
17948
  }
17445
17949
  const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
@@ -18792,6 +19296,19 @@ function OhhwellsBridge() {
18792
19296
  postAiSectionsChanged();
18793
19297
  };
18794
19298
  window.addEventListener("message", handleAiSetSections);
19299
+ const handleMoveSection = (e) => {
19300
+ if (e.data?.type !== "ow:move-section") return;
19301
+ const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
19302
+ const direction = e.data.direction === "up" || e.data.direction === "down" ? e.data.direction : null;
19303
+ if (!instanceId || !direction) return;
19304
+ const entries = moveSectionInstance(instanceId, direction, window.location.pathname);
19305
+ if (!entries) return;
19306
+ const orderJson = JSON.stringify(entries);
19307
+ editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
19308
+ postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
19309
+ window.dispatchEvent(new Event("resize"));
19310
+ };
19311
+ window.addEventListener("message", handleMoveSection);
18795
19312
  const handleAiSetBrand = (e) => {
18796
19313
  if (e.data?.type !== "ow:ai-set-brand") return;
18797
19314
  const value = typeof e.data.value === "string" ? e.data.value : "";
@@ -18922,6 +19439,10 @@ function OhhwellsBridge() {
18922
19439
  const handleKeyDown = (e) => {
18923
19440
  if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
18924
19441
  if (e.key === "Escape" && document.querySelector("[data-ohw-more-menu]")) return;
19442
+ if (e.key === "Escape" && selectedMediaElRef.current) {
19443
+ clearMediaSelectionRef.current();
19444
+ return;
19445
+ }
18925
19446
  if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
18926
19447
  e.preventDefault();
18927
19448
  selectAllTextInEditable(activeElRef.current);
@@ -19496,6 +20017,7 @@ function OhhwellsBridge() {
19496
20017
  window.removeEventListener("message", handleAiApplyTree);
19497
20018
  window.removeEventListener("message", handleAiDeleteSection);
19498
20019
  window.removeEventListener("message", handleAiSetSections);
20020
+ window.removeEventListener("message", handleMoveSection);
19499
20021
  window.removeEventListener("message", handleAiSetBrand);
19500
20022
  window.removeEventListener("message", handleAiSetStyles);
19501
20023
  window.removeEventListener("message", handleGetBrand);
@@ -19509,7 +20031,7 @@ function OhhwellsBridge() {
19509
20031
  if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
19510
20032
  };
19511
20033
  }, [isEditMode, refreshStateRules]);
19512
- (0, import_react16.useEffect)(() => {
20034
+ (0, import_react17.useEffect)(() => {
19513
20035
  if (!isEditMode) return;
19514
20036
  const THRESHOLD = 10;
19515
20037
  const resolveWasSelected = (el) => {
@@ -19665,7 +20187,7 @@ function OhhwellsBridge() {
19665
20187
  unlockFooterDragInteraction();
19666
20188
  };
19667
20189
  }, [isEditMode]);
19668
- (0, import_react16.useEffect)(() => {
20190
+ (0, import_react17.useEffect)(() => {
19669
20191
  const handler = (e) => {
19670
20192
  if (e.data?.type !== "ow:request-schedule-config") return;
19671
20193
  const insertAfterVal = e.data.insertAfter;
@@ -19681,7 +20203,7 @@ function OhhwellsBridge() {
19681
20203
  window.addEventListener("message", handler);
19682
20204
  return () => window.removeEventListener("message", handler);
19683
20205
  }, [processConfigRequest]);
19684
- (0, import_react16.useEffect)(() => {
20206
+ (0, import_react17.useEffect)(() => {
19685
20207
  if (!isEditMode) return;
19686
20208
  document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
19687
20209
  el.removeAttribute("data-ohw-active-state");
@@ -19705,7 +20227,7 @@ function OhhwellsBridge() {
19705
20227
  postToParent2({
19706
20228
  type: "ow:ready",
19707
20229
  version: "1",
19708
- bridgeVersion: "0.1.66",
20230
+ bridgeVersion: "0.1.67",
19709
20231
  path: pathname,
19710
20232
  nodes: collectEditableNodes(editContentRef.current),
19711
20233
  sections
@@ -19717,13 +20239,13 @@ function OhhwellsBridge() {
19717
20239
  clearTimeout(timer);
19718
20240
  };
19719
20241
  }, [pathname, isEditMode, refreshStateRules, postToParent2]);
19720
- (0, import_react16.useEffect)(() => {
20242
+ (0, import_react17.useEffect)(() => {
19721
20243
  scrollToHashSectionWhenReady();
19722
20244
  const onHashChange = () => scrollToHashSectionWhenReady();
19723
20245
  window.addEventListener("hashchange", onHashChange);
19724
20246
  return () => window.removeEventListener("hashchange", onHashChange);
19725
20247
  }, [pathname]);
19726
- const handleCommand = (0, import_react16.useCallback)((cmd) => {
20248
+ const handleCommand = (0, import_react17.useCallback)((cmd) => {
19727
20249
  const el = activeElRef.current;
19728
20250
  const selBefore = window.getSelection();
19729
20251
  let savedOffsets = null;
@@ -19759,7 +20281,7 @@ function OhhwellsBridge() {
19759
20281
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
19760
20282
  refreshActiveCommandsRef.current();
19761
20283
  }, []);
19762
- const handleStateChange = (0, import_react16.useCallback)((state) => {
20284
+ const handleStateChange = (0, import_react17.useCallback)((state) => {
19763
20285
  if (!activeStateElRef.current) return;
19764
20286
  const el = activeStateElRef.current;
19765
20287
  if (state === "Default") {
@@ -19772,7 +20294,7 @@ function OhhwellsBridge() {
19772
20294
  }
19773
20295
  setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
19774
20296
  }, [deactivate]);
19775
- const reselectAfterLinkPopover = (0, import_react16.useCallback)(
20297
+ const reselectAfterLinkPopover = (0, import_react17.useCallback)(
19776
20298
  (hrefKey) => {
19777
20299
  requestAnimationFrame(() => {
19778
20300
  const el = resolveHrefKeyElement(hrefKey);
@@ -19781,7 +20303,7 @@ function OhhwellsBridge() {
19781
20303
  },
19782
20304
  [resolveHrefKeyElement]
19783
20305
  );
19784
- const closeLinkPopover = (0, import_react16.useCallback)(() => {
20306
+ const closeLinkPopover = (0, import_react17.useCallback)(() => {
19785
20307
  const session = linkPopoverSessionRef.current;
19786
20308
  addNavAfterAnchorRef.current = null;
19787
20309
  setLinkPopover(null);
@@ -19789,9 +20311,9 @@ function OhhwellsBridge() {
19789
20311
  reselectAfterLinkPopover(session.key);
19790
20312
  }
19791
20313
  }, [reselectAfterLinkPopover]);
19792
- const closeLinkPopoverRef = (0, import_react16.useRef)(closeLinkPopover);
20314
+ const closeLinkPopoverRef = (0, import_react17.useRef)(closeLinkPopover);
19793
20315
  closeLinkPopoverRef.current = closeLinkPopover;
19794
- const openLinkPopoverForActive = (0, import_react16.useCallback)(() => {
20316
+ const openLinkPopoverForActive = (0, import_react17.useCallback)(() => {
19795
20317
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
19796
20318
  if (!hrefCtx) return;
19797
20319
  bumpLinkPopoverGrace();
@@ -19802,7 +20324,7 @@ function OhhwellsBridge() {
19802
20324
  });
19803
20325
  deactivate();
19804
20326
  }, [deactivate]);
19805
- const openLinkPopoverForSelected = (0, import_react16.useCallback)(() => {
20327
+ const openLinkPopoverForSelected = (0, import_react17.useCallback)(() => {
19806
20328
  const anchor = selectedElRef.current;
19807
20329
  if (!anchor) return;
19808
20330
  const key = anchor.getAttribute("data-ohw-href-key");
@@ -19819,7 +20341,7 @@ function OhhwellsBridge() {
19819
20341
  });
19820
20342
  deselect();
19821
20343
  }, [deselect]);
19822
- const handleSelectParent = (0, import_react16.useCallback)(() => {
20344
+ const handleSelectParent = (0, import_react17.useCallback)(() => {
19823
20345
  const selected = selectedElRef.current;
19824
20346
  if (!selected) return;
19825
20347
  if (toolbarVariantRef.current === "select-frame") {
@@ -19846,7 +20368,7 @@ function OhhwellsBridge() {
19846
20368
  }
19847
20369
  deselectRef.current();
19848
20370
  }, []);
19849
- const handleDuplicateSelected = (0, import_react16.useCallback)(() => {
20371
+ const handleDuplicateSelected = (0, import_react17.useCallback)(() => {
19850
20372
  const selected = selectedElRef.current;
19851
20373
  if (!selected || !isNavigationItem2(selected)) return;
19852
20374
  const hrefKey = selected.getAttribute("data-ohw-href-key");
@@ -19962,7 +20484,7 @@ function OhhwellsBridge() {
19962
20484
  });
19963
20485
  }
19964
20486
  }, [postToParent2]);
19965
- const runPendingDeleteUndo = (0, import_react16.useCallback)(() => {
20487
+ const runPendingDeleteUndo = (0, import_react17.useCallback)(() => {
19966
20488
  const pending = pendingDeleteUndoRef.current;
19967
20489
  if (!pending) return false;
19968
20490
  pendingDeleteUndoRef.current = null;
@@ -19970,7 +20492,7 @@ function OhhwellsBridge() {
19970
20492
  enforceLinkHrefs();
19971
20493
  return true;
19972
20494
  }, []);
19973
- const handleDeleteSelected = (0, import_react16.useCallback)(() => {
20495
+ const handleDeleteSelected = (0, import_react17.useCallback)(() => {
19974
20496
  const selected = selectedElRef.current;
19975
20497
  if (!selected) return false;
19976
20498
  return deleteSelectedNavFooterItem({
@@ -19991,7 +20513,7 @@ function OhhwellsBridge() {
19991
20513
  }, [postToParent2]);
19992
20514
  handleDeleteSelectedRef.current = handleDeleteSelected;
19993
20515
  runPendingDeleteUndoRef.current = runPendingDeleteUndo;
19994
- const handleLinkPopoverSubmit = (0, import_react16.useCallback)(
20516
+ const handleLinkPopoverSubmit = (0, import_react17.useCallback)(
19995
20517
  (target) => {
19996
20518
  const session = linkPopoverSessionRef.current;
19997
20519
  if (!session) return;
@@ -20057,19 +20579,30 @@ function OhhwellsBridge() {
20057
20579
  const showEditLink = toolbarShowEditLink;
20058
20580
  const currentSections = sectionsByPath[pathname] ?? [];
20059
20581
  linkPopoverOpenRef.current = linkPopover !== null;
20060
- const handleMediaReplace = (0, import_react16.useCallback)(
20582
+ const handleMediaSelect = (0, import_react17.useCallback)((key) => {
20583
+ const el = hoveredImageRef.current?.dataset.ohwKey === key ? hoveredImageRef.current : Array.from(document.querySelectorAll(MEDIA_SELECTOR)).find(
20584
+ (m) => (m.dataset.ohwKey ?? "") === key
20585
+ ) ?? null;
20586
+ if (!el) return;
20587
+ selectMediaElementRef.current(el);
20588
+ }, []);
20589
+ const handleMediaReplace = (0, import_react17.useCallback)(
20061
20590
  (key) => {
20062
- postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
20591
+ postToParent2({
20592
+ type: "ow:image-pick",
20593
+ key,
20594
+ elementType: mediaHover?.elementType ?? selectedMedia?.elementType ?? "image"
20595
+ });
20063
20596
  },
20064
- [postToParent2, mediaHover?.elementType]
20597
+ [postToParent2, mediaHover?.elementType, selectedMedia?.elementType]
20065
20598
  );
20066
- const handleEditCarousel = (0, import_react16.useCallback)(
20599
+ const handleEditCarousel = (0, import_react17.useCallback)(
20067
20600
  (key) => {
20068
20601
  postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
20069
20602
  },
20070
20603
  [postToParent2]
20071
20604
  );
20072
- const handleMediaFadeOutComplete = (0, import_react16.useCallback)((key) => {
20605
+ const handleMediaFadeOutComplete = (0, import_react17.useCallback)((key) => {
20073
20606
  setUploadingRects((prev) => {
20074
20607
  if (!(key in prev)) return prev;
20075
20608
  const next = { ...prev };
@@ -20077,7 +20610,7 @@ function OhhwellsBridge() {
20077
20610
  return next;
20078
20611
  });
20079
20612
  }, []);
20080
- const handleVideoSettingsChange = (0, import_react16.useCallback)(
20613
+ const handleVideoSettingsChange = (0, import_react17.useCallback)(
20081
20614
  (key, settings) => {
20082
20615
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
20083
20616
  const video = getVideoEl2(el);
@@ -20099,465 +20632,498 @@ function OhhwellsBridge() {
20099
20632
  },
20100
20633
  [postToParent2]
20101
20634
  );
20102
- return bridgeRoot ? (0, import_react_dom4.createPortal)(
20103
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
20104
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
20105
- isEditMode && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
20106
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20107
- MediaOverlay,
20108
- {
20109
- hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
20110
- isUploading: true,
20111
- fadingOut,
20112
- onFadeOutComplete: handleMediaFadeOutComplete,
20113
- onReplace: handleMediaReplace
20114
- },
20115
- `uploading-${key}`
20116
- )),
20117
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20118
- MediaOverlay,
20119
- {
20120
- hover: mediaHover,
20121
- isUploading: false,
20122
- onReplace: handleMediaReplace,
20123
- onVideoSettingsChange: handleVideoSettingsChange
20124
- }
20125
- ),
20126
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
20127
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
20128
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
20129
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
20130
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20131
- "div",
20132
- {
20133
- className: "pointer-events-none fixed z-2147483646",
20134
- style: {
20135
- left: slot.left,
20136
- top: slot.top,
20137
- width: slot.width,
20138
- height: slot.height
20635
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
20636
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { id: "ohw-loader", suppressHydrationWarning: true, style: { ...OHW_LOADER_STYLE, display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(OhwLoaderSpinner, {}) }),
20637
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: OHW_LOADER_PREHYDRATE_SCRIPT } }),
20638
+ bridgeRoot ? (0, import_react_dom4.createPortal)(
20639
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
20640
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
20641
+ isEditMode && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
20642
+ isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20643
+ "div",
20644
+ {
20645
+ className: "pointer-events-none fixed z-2147483646",
20646
+ style: { left: slot.left, top: slot.y, width: slot.width, height: 3, transform: "translateY(-50%)" },
20647
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20648
+ DropIndicator,
20649
+ {
20650
+ direction: "horizontal",
20651
+ state: activeSectionDropIndex === i ? "dragActive" : "dragIdle",
20652
+ className: "!h-full !w-full"
20653
+ }
20654
+ )
20139
20655
  },
20140
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20141
- DropIndicator,
20142
- {
20143
- direction: slot.direction,
20144
- state: activeFooterDropIndex === i ? "dragActive" : "dragIdle",
20145
- className: "!h-full !w-full"
20146
- }
20147
- )
20148
- },
20149
- `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
20150
- )),
20151
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20152
- "div",
20153
- {
20154
- className: "pointer-events-none fixed z-2147483646",
20155
- style: {
20156
- left: slot.left,
20157
- top: slot.top,
20158
- width: slot.width,
20159
- height: slot.height
20656
+ `section-drop-${slot.insertIndex}-${i}`
20657
+ )),
20658
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20659
+ MediaOverlay,
20660
+ {
20661
+ hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
20662
+ isUploading: true,
20663
+ fadingOut,
20664
+ onFadeOutComplete: handleMediaFadeOutComplete,
20665
+ onReplace: handleMediaReplace
20160
20666
  },
20161
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20162
- DropIndicator,
20163
- {
20164
- direction: slot.direction,
20165
- state: activeNavDropIndex === i ? "dragActive" : "dragIdle",
20166
- className: "!h-full !w-full"
20167
- }
20168
- )
20169
- },
20170
- `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
20171
- )),
20172
- hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
20173
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
20174
- hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
20175
- formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20176
- ItemInteractionLayer,
20177
- {
20178
- rect: formPickRect,
20179
- state: "active-top",
20180
- itemDragSurface: false,
20181
- toolbarAlign: "left",
20182
- chromeGap: 24,
20183
- toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
20184
- "div",
20185
- {
20186
- "data-ohw-form-toolbar": "",
20187
- className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
20188
- children: [
20189
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20190
- "button",
20191
- {
20192
- type: "button",
20193
- "aria-label": "Add field",
20194
- className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
20195
- onClick: () => setFieldTypePickerOpen((open) => !open),
20196
- "data-ohw-add-field": "",
20197
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Plus, { size: 15, "aria-hidden": true })
20198
- }
20199
- ),
20200
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20201
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
20202
- "button",
20203
- {
20204
- type: "button",
20205
- className: "flex h-7 items-center gap-1.5 whitespace-nowrap rounded-md px-2 text-[13px] font-semibold text-foreground transition-colors hover:bg-muted/80",
20206
- onClick: () => {
20207
- const form = formPickElRef.current;
20208
- if (!form) return;
20209
- postToParent2({
20210
- type: "ow:form-pick",
20211
- formKey: formKeyOf(form),
20212
- hasLongText: formHasLongText(form)
20213
- });
20214
- },
20215
- children: [
20216
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Settings, { size: 14, "aria-hidden": true }),
20217
- "Form settings",
20218
- formPickCount ? (
20219
- // Counter pill, per the design — not a text suffix.
20220
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20221
- "span",
20222
- {
20223
- "data-ohw-form-count": "",
20224
- className: "ml-0.5 inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-full bg-primary px-1.5 text-[11px] font-semibold text-primary-foreground",
20225
- children: formPickCount
20226
- }
20227
- )
20228
- ) : null
20229
- ]
20230
- }
20231
- ),
20232
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20233
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20234
- "button",
20235
- {
20236
- type: "button",
20237
- "aria-pressed": formViewState === state,
20238
- className: "rounded-md px-2.5 py-1 text-[13px] font-semibold capitalize transition-colors " + (formViewState === state ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"),
20239
- onClick: () => {
20240
- const form = formPickElRef.current;
20241
- const key = form ? formKeyOf(form) : null;
20242
- if (!form || !key) return;
20243
- const initial = successInitialFor(form, key, editContentRef.current);
20244
- setFormViewState(form, key, state, initial);
20245
- setFormViewStateUi(state);
20246
- setFormPickRect(form.getBoundingClientRect());
20247
- if (state === "success") {
20248
- const successEl = form.querySelector(`[${SUCCESS_TEXT_ATTR}]`);
20249
- if (successEl) requestAnimationFrame(() => activateRef.current(successEl));
20250
- } else {
20251
- deactivateRef.current();
20252
- }
20253
- },
20254
- children: state
20255
- },
20256
- state
20257
- )) })
20258
- ]
20259
- }
20260
- )
20261
- }
20262
- ),
20263
- formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20264
- ItemInteractionLayer,
20265
- {
20266
- rect: formHoverRect,
20267
- state: "hover",
20268
- chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
20269
- }
20270
- ),
20271
- fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20272
- ItemInteractionLayer,
20273
- {
20274
- rect: fieldPickRect,
20275
- state: fieldDragging ? "dragging" : "active-top",
20276
- itemDragSurface: false,
20277
- toolbarAlign: "left",
20278
- chromeGap: 10,
20279
- showHandle: true,
20280
- dragHandleLabel: "Reorder field",
20281
- onDragHandleDragStart: handleFieldDragStart,
20282
- onDragHandleDragEnd: handleFieldDragEnd,
20283
- toolbar: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20284
- FormFieldToolbar,
20285
- {
20286
- type: fieldPickState.type,
20287
- required: fieldPickState.required,
20288
- onTypeChange: handleFieldTypeChange,
20289
- onRequiredToggle: handleFieldRequiredToggle,
20290
- onDuplicate: handleFieldDuplicate,
20291
- onDelete: handleFieldDelete
20292
- }
20293
- )
20294
- }
20295
- ),
20296
- fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20297
- "div",
20298
- {
20299
- className: "pointer-events-none fixed z-[2147483644]",
20300
- style: { top: slot.top, left: slot.left, width: slot.width },
20301
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20302
- DropIndicator,
20303
- {
20304
- direction: "horizontal",
20305
- state: fieldDropIndex === i ? "dragActive" : "dragIdle",
20306
- className: "!w-full"
20307
- }
20308
- )
20309
- },
20310
- `field-drop-${i}`
20311
- )) : null,
20312
- fieldTypePickerOpen && formPickRect && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20313
- "div",
20314
- {
20315
- className: "pointer-events-none fixed z-[2147483645]",
20316
- style: { top: formPickRect.top + 16, left: formPickRect.left + 24 },
20317
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(FieldTypePicker, { onPick: handleAddField })
20318
- }
20319
- ),
20320
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
20321
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20322
- FooterContainerChrome,
20323
- {
20324
- rect: toolbarRect,
20325
- onAdd: handleAddFooterColumn,
20326
- addDisabled: !canAddFooterColumn()
20327
- }
20328
- ),
20329
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20330
- ItemInteractionLayer,
20331
- {
20332
- rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
20333
- toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
20334
- elRef: glowElRef,
20335
- state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanelRect(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
20336
- showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
20337
- dragDisabled: reorderDragDisabled,
20338
- dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
20339
- onDragHandleDragStart: handleItemDragStart,
20340
- onDragHandleDragEnd: handleItemDragEnd,
20341
- onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
20342
- onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
20343
- itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
20344
- toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20345
- ItemActionToolbar,
20346
- {
20347
- onEditLink: openLinkPopoverForSelected,
20348
- onStyle: () => {
20349
- const row = selectedElRef.current;
20350
- if (!row) return;
20351
- if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
20352
- else openSocialsDisplayPanel(row);
20353
- },
20354
- showStyle: selectedIsSocialsRow,
20355
- styleActive: floatingPanel?.kind === "socials-display",
20356
- onAddItem: handleAddChildItem,
20357
- onSelectParent: handleSelectParent,
20358
- onDuplicate: handleDuplicateSelected,
20359
- onDelete: handleDeleteSelected,
20360
- addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
20361
- const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
20362
- return row ? !canAddSocialItem(row) : false;
20363
- })(),
20364
- editLinkDisabled: false,
20365
- moreDisabled: false,
20366
- duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
20367
- showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
20368
- showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
20369
- selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
20370
- ),
20371
- showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
20372
- dropdownOpen: navDropdownPreviewOpen,
20373
- onDropdownOpenChange: handleNavDropdownOpenChange,
20374
- headingVisible: footerHeadingVisible,
20375
- onHeadingVisibleChange: handleFooterHeadingVisibleChange
20376
- }
20377
- ) : void 0
20378
- }
20379
- ),
20380
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
20381
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20382
- EditGlowChrome,
20667
+ `uploading-${key}`
20668
+ )),
20669
+ mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20670
+ MediaOverlay,
20383
20671
  {
20384
- rect: toolbarRect,
20385
- elRef: glowElRef,
20386
- reorderHrefKey,
20387
- dragDisabled: reorderDragDisabled,
20388
- hideHandle: isItemDragging
20672
+ hover: mediaHover,
20673
+ isUploading: false,
20674
+ onReplace: handleMediaReplace,
20675
+ onSelect: handleMediaSelect,
20676
+ onVideoSettingsChange: handleVideoSettingsChange
20389
20677
  }
20390
20678
  ),
20391
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20392
- FloatingToolbar,
20679
+ selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20680
+ MediaOverlay,
20393
20681
  {
20394
- rect: toolbarRect,
20395
- parentScroll: parentScrollRef.current,
20396
- elRef: toolbarElRef,
20397
- onCommand: handleCommand,
20398
- activeCommands,
20399
- showEditLink,
20400
- onEditLink: openLinkPopoverForActive
20682
+ hover: selectedMedia,
20683
+ selected: true,
20684
+ hovered: mediaHover?.key === selectedMedia.key,
20685
+ isUploading: false,
20686
+ onReplace: handleMediaReplace,
20687
+ onSelect: handleMediaSelect,
20688
+ onVideoSettingsChange: handleVideoSettingsChange
20401
20689
  }
20402
- )
20403
- ] }),
20404
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
20405
- "div",
20406
- {
20407
- "data-ohw-max-badge": "",
20408
- style: {
20409
- position: "fixed",
20410
- top: maxBadge.rect.bottom + 4,
20411
- left: maxBadge.rect.right,
20412
- transform: "translateX(-100%)",
20413
- zIndex: 2147483647,
20414
- background: maxBadge.current > maxBadge.max ? "#FEF2F2" : "#F5F5F4",
20415
- color: maxBadge.current > maxBadge.max ? "#DC2626" : "#78716C",
20416
- border: `1px solid ${maxBadge.current > maxBadge.max ? "#FECACA" : "#E7E5E4"}`,
20417
- borderRadius: 4,
20418
- padding: "2px 6px",
20419
- fontSize: 11,
20420
- fontWeight: 500,
20421
- pointerEvents: "none"
20690
+ ),
20691
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
20692
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
20693
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
20694
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
20695
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20696
+ "div",
20697
+ {
20698
+ className: "pointer-events-none fixed z-2147483646",
20699
+ style: {
20700
+ left: slot.left,
20701
+ top: slot.top,
20702
+ width: slot.width,
20703
+ height: slot.height
20704
+ },
20705
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20706
+ DropIndicator,
20707
+ {
20708
+ direction: slot.direction,
20709
+ state: activeFooterDropIndex === i ? "dragActive" : "dragIdle",
20710
+ className: "!h-full !w-full"
20711
+ }
20712
+ )
20422
20713
  },
20423
- children: [
20424
- maxBadge.current,
20425
- "/",
20426
- maxBadge.max
20427
- ]
20428
- }
20429
- ),
20430
- toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20431
- StateToggle,
20432
- {
20433
- rect: toggleState.rect,
20434
- activeState: toggleState.activeState,
20435
- states: toggleState.states,
20436
- onStateChange: handleStateChange
20437
- }
20438
- ),
20439
- sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
20440
- "div",
20441
- {
20442
- "data-ohw-section-insert-line": "",
20443
- className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
20444
- style: { top: sectionGap.y, transform: "translateY(-50%)" },
20445
- children: [
20446
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
20447
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20448
- Badge,
20714
+ `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
20715
+ )),
20716
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20717
+ "div",
20718
+ {
20719
+ className: "pointer-events-none fixed z-2147483646",
20720
+ style: {
20721
+ left: slot.left,
20722
+ top: slot.top,
20723
+ width: slot.width,
20724
+ height: slot.height
20725
+ },
20726
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20727
+ DropIndicator,
20449
20728
  {
20450
- className: "px-8 py-1 bg-primary hover:bg-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
20451
- onClick: () => {
20452
- window.parent.postMessage(
20729
+ direction: slot.direction,
20730
+ state: activeNavDropIndex === i ? "dragActive" : "dragIdle",
20731
+ className: "!h-full !w-full"
20732
+ }
20733
+ )
20734
+ },
20735
+ `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
20736
+ )),
20737
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
20738
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
20739
+ hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
20740
+ formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20741
+ ItemInteractionLayer,
20742
+ {
20743
+ rect: formPickRect,
20744
+ state: "active-top",
20745
+ itemDragSurface: false,
20746
+ toolbarAlign: "left",
20747
+ chromeGap: 24,
20748
+ toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
20749
+ "div",
20750
+ {
20751
+ "data-ohw-form-toolbar": "",
20752
+ className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
20753
+ children: [
20754
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20755
+ "button",
20756
+ {
20757
+ type: "button",
20758
+ "aria-label": "Add field",
20759
+ className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
20760
+ onClick: () => setFieldTypePickerOpen((open) => !open),
20761
+ "data-ohw-add-field": "",
20762
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Plus, { size: 15, "aria-hidden": true })
20763
+ }
20764
+ ),
20765
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20766
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
20767
+ "button",
20768
+ {
20769
+ type: "button",
20770
+ className: "flex h-7 items-center gap-1.5 whitespace-nowrap rounded-md px-2 text-[13px] font-semibold text-foreground transition-colors hover:bg-muted/80",
20771
+ onClick: () => {
20772
+ const form = formPickElRef.current;
20773
+ if (!form) return;
20774
+ postToParent2({
20775
+ type: "ow:form-pick",
20776
+ formKey: formKeyOf(form),
20777
+ hasLongText: formHasLongText(form)
20778
+ });
20779
+ },
20780
+ children: [
20781
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Settings, { size: 14, "aria-hidden": true }),
20782
+ "Form settings",
20783
+ formPickCount ? (
20784
+ // Counter pill, per the design — not a text suffix.
20785
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20786
+ "span",
20787
+ {
20788
+ "data-ohw-form-count": "",
20789
+ className: "ml-0.5 inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-full bg-primary px-1.5 text-[11px] font-semibold text-primary-foreground",
20790
+ children: formPickCount
20791
+ }
20792
+ )
20793
+ ) : null
20794
+ ]
20795
+ }
20796
+ ),
20797
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20798
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20799
+ "button",
20453
20800
  {
20454
- type: "ow:add-section",
20455
- insertAfter: sectionGap.insertAfter,
20456
- insertBefore: sectionGap.insertBefore
20801
+ type: "button",
20802
+ "aria-pressed": formViewState === state,
20803
+ className: "rounded-md px-2.5 py-1 text-[13px] font-semibold capitalize transition-colors " + (formViewState === state ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"),
20804
+ onClick: () => {
20805
+ const form = formPickElRef.current;
20806
+ const key = form ? formKeyOf(form) : null;
20807
+ if (!form || !key) return;
20808
+ const initial = successInitialFor(form, key, editContentRef.current);
20809
+ setFormViewState(form, key, state, initial);
20810
+ setFormViewStateUi(state);
20811
+ setFormPickRect(form.getBoundingClientRect());
20812
+ if (state === "success") {
20813
+ const successEl = form.querySelector(`[${SUCCESS_TEXT_ATTR}]`);
20814
+ if (successEl) requestAnimationFrame(() => activateRef.current(successEl));
20815
+ } else {
20816
+ deactivateRef.current();
20817
+ }
20818
+ },
20819
+ children: state
20457
20820
  },
20458
- "*"
20459
- );
20821
+ state
20822
+ )) })
20823
+ ]
20824
+ }
20825
+ )
20826
+ }
20827
+ ),
20828
+ formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20829
+ ItemInteractionLayer,
20830
+ {
20831
+ rect: formHoverRect,
20832
+ state: "hover",
20833
+ chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
20834
+ }
20835
+ ),
20836
+ fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20837
+ ItemInteractionLayer,
20838
+ {
20839
+ rect: fieldPickRect,
20840
+ state: fieldDragging ? "dragging" : "active-top",
20841
+ itemDragSurface: false,
20842
+ toolbarAlign: "left",
20843
+ chromeGap: 10,
20844
+ showHandle: true,
20845
+ dragHandleLabel: "Reorder field",
20846
+ onDragHandleDragStart: handleFieldDragStart,
20847
+ onDragHandleDragEnd: handleFieldDragEnd,
20848
+ toolbar: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20849
+ FormFieldToolbar,
20850
+ {
20851
+ type: fieldPickState.type,
20852
+ required: fieldPickState.required,
20853
+ onTypeChange: handleFieldTypeChange,
20854
+ onRequiredToggle: handleFieldRequiredToggle,
20855
+ onDuplicate: handleFieldDuplicate,
20856
+ onDelete: handleFieldDelete
20857
+ }
20858
+ )
20859
+ }
20860
+ ),
20861
+ fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20862
+ "div",
20863
+ {
20864
+ className: "pointer-events-none fixed z-[2147483644]",
20865
+ style: { top: slot.top, left: slot.left, width: slot.width },
20866
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20867
+ DropIndicator,
20868
+ {
20869
+ direction: "horizontal",
20870
+ state: fieldDropIndex === i ? "dragActive" : "dragIdle",
20871
+ className: "!w-full"
20872
+ }
20873
+ )
20874
+ },
20875
+ `field-drop-${i}`
20876
+ )) : null,
20877
+ fieldTypePickerOpen && formPickRect && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20878
+ "div",
20879
+ {
20880
+ className: "pointer-events-none fixed z-[2147483645]",
20881
+ style: { top: formPickRect.top + 16, left: formPickRect.left + 24 },
20882
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(FieldTypePicker, { onPick: handleAddField })
20883
+ }
20884
+ ),
20885
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
20886
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20887
+ FooterContainerChrome,
20888
+ {
20889
+ rect: toolbarRect,
20890
+ onAdd: handleAddFooterColumn,
20891
+ addDisabled: !canAddFooterColumn()
20892
+ }
20893
+ ),
20894
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20895
+ ItemInteractionLayer,
20896
+ {
20897
+ rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
20898
+ toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
20899
+ elRef: glowElRef,
20900
+ state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanelRect(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
20901
+ showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
20902
+ dragDisabled: reorderDragDisabled,
20903
+ dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
20904
+ onDragHandleDragStart: handleItemDragStart,
20905
+ onDragHandleDragEnd: handleItemDragEnd,
20906
+ onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
20907
+ onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
20908
+ itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
20909
+ toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20910
+ ItemActionToolbar,
20911
+ {
20912
+ onEditLink: openLinkPopoverForSelected,
20913
+ onStyle: () => {
20914
+ const row = selectedElRef.current;
20915
+ if (!row) return;
20916
+ if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
20917
+ else openSocialsDisplayPanel(row);
20460
20918
  },
20461
- children: "Add Section"
20919
+ showStyle: selectedIsSocialsRow,
20920
+ styleActive: floatingPanel?.kind === "socials-display",
20921
+ onAddItem: handleAddChildItem,
20922
+ onSelectParent: handleSelectParent,
20923
+ onDuplicate: handleDuplicateSelected,
20924
+ onDelete: handleDeleteSelected,
20925
+ addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
20926
+ const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
20927
+ return row ? !canAddSocialItem(row) : false;
20928
+ })(),
20929
+ editLinkDisabled: false,
20930
+ moreDisabled: false,
20931
+ duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
20932
+ showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
20933
+ showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
20934
+ selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
20935
+ ),
20936
+ showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
20937
+ dropdownOpen: navDropdownPreviewOpen,
20938
+ onDropdownOpenChange: handleNavDropdownOpenChange,
20939
+ headingVisible: footerHeadingVisible,
20940
+ onHeadingVisibleChange: handleFooterHeadingVisibleChange
20462
20941
  }
20463
- ),
20464
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
20465
- ]
20466
- }
20467
- ),
20468
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20469
- LinkPopover,
20470
- {
20471
- panelRef: linkPopoverPanelRef,
20472
- portalContainer: dialogPortalContainer,
20473
- open: true,
20474
- mode: linkPopover.mode ?? "edit",
20475
- pages: sitePages,
20476
- sections: currentSections,
20477
- sectionsByPath,
20478
- initialTarget: linkPopover.target,
20479
- existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
20480
- onClose: closeLinkPopover,
20481
- onSubmit: handleLinkPopoverSubmit
20482
- },
20483
- linkPopover.key
20484
- ) : null,
20485
- floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20486
- FloatingPanel,
20487
- {
20488
- open: true,
20489
- title: floatingPanel.title,
20490
- context: floatingPanel.context,
20491
- position: floatingPanelPos,
20492
- onPositionChange: setFloatingPanelPos,
20493
- parentScroll: parentScrollSnap ?? parentScrollRef.current,
20494
- onClose: closeFloatingPanelOnly,
20495
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20496
- SocialsDisplayPanel,
20942
+ ) : void 0
20943
+ }
20944
+ ),
20945
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
20946
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20947
+ EditGlowChrome,
20497
20948
  {
20498
- display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
20499
- onChange: (next) => {
20500
- changeSocialsDisplay(floatingPanel.row, next);
20501
- setFloatingPanel({ ...floatingPanel });
20502
- }
20949
+ rect: toolbarRect,
20950
+ elRef: glowElRef,
20951
+ reorderHrefKey,
20952
+ dragDisabled: reorderDragDisabled,
20953
+ hideHandle: isItemDragging
20503
20954
  }
20504
- )
20505
- }
20506
- ) : null,
20507
- floatingPanel && floatingPanel.kind === "logo-size" && logoSizeDraft ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20508
- FloatingPanel,
20509
- {
20510
- open: true,
20511
- title: floatingPanel.title,
20512
- context: floatingPanel.context,
20513
- position: floatingPanelPos,
20514
- onPositionChange: setFloatingPanelPos,
20515
- parentScroll: parentScrollSnap ?? parentScrollRef.current,
20516
- onClose: closeFloatingPanelAndDeselect,
20517
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20518
- LogoSizePanel,
20955
+ ),
20956
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20957
+ FloatingToolbar,
20519
20958
  {
20520
- viewport: editorViewport,
20521
- sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
20522
- mobileFollowing: logoSizeDraft.mobileFollowing,
20523
- onSizeChange: (px) => {
20524
- const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
20525
- ...logoSizeDraft,
20526
- desktopPx: px,
20527
- mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
20528
- };
20529
- setLogoSizeDraft(next);
20530
- persistLogoSizeDraft(floatingPanel.placement, next);
20531
- },
20532
- onCustomizeMobile: () => {
20533
- const next = {
20534
- ...logoSizeDraft,
20535
- mobileFollowing: false,
20536
- mobilePx: logoSizeDraft.desktopPx
20537
- };
20538
- setLogoSizeDraft(next);
20539
- persistLogoSizeDraft(floatingPanel.placement, next);
20540
- },
20541
- onResetMobile: () => {
20542
- const next = {
20543
- ...logoSizeDraft,
20544
- mobileFollowing: true,
20545
- mobilePx: logoSizeDraft.desktopPx
20546
- };
20547
- setLogoSizeDraft(next);
20548
- persistLogoSizeDraft(floatingPanel.placement, next);
20549
- },
20550
- onUpdateEverywhere: () => {
20551
- const identity = readLogoIdentityFromDom();
20552
- postToParent2({ type: "ow:open-logo-settings", ...identity });
20553
- }
20959
+ rect: toolbarRect,
20960
+ parentScroll: parentScrollRef.current,
20961
+ elRef: toolbarElRef,
20962
+ onCommand: handleCommand,
20963
+ activeCommands,
20964
+ showEditLink,
20965
+ onEditLink: openLinkPopoverForActive
20554
20966
  }
20555
20967
  )
20556
- }
20557
- ) : null
20558
- ] }),
20559
- bridgeRoot
20560
- ) : null;
20968
+ ] }),
20969
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
20970
+ "div",
20971
+ {
20972
+ "data-ohw-max-badge": "",
20973
+ style: {
20974
+ position: "fixed",
20975
+ top: maxBadge.rect.bottom + 4,
20976
+ left: maxBadge.rect.right,
20977
+ transform: "translateX(-100%)",
20978
+ zIndex: 2147483647,
20979
+ background: maxBadge.current > maxBadge.max ? "#FEF2F2" : "#F5F5F4",
20980
+ color: maxBadge.current > maxBadge.max ? "#DC2626" : "#78716C",
20981
+ border: `1px solid ${maxBadge.current > maxBadge.max ? "#FECACA" : "#E7E5E4"}`,
20982
+ borderRadius: 4,
20983
+ padding: "2px 6px",
20984
+ fontSize: 11,
20985
+ fontWeight: 500,
20986
+ pointerEvents: "none"
20987
+ },
20988
+ children: [
20989
+ maxBadge.current,
20990
+ "/",
20991
+ maxBadge.max
20992
+ ]
20993
+ }
20994
+ ),
20995
+ toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20996
+ StateToggle,
20997
+ {
20998
+ rect: toggleState.rect,
20999
+ activeState: toggleState.activeState,
21000
+ states: toggleState.states,
21001
+ onStateChange: handleStateChange
21002
+ }
21003
+ ),
21004
+ sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
21005
+ "div",
21006
+ {
21007
+ "data-ohw-section-insert-line": "",
21008
+ className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
21009
+ style: { top: sectionGap.y, transform: "translateY(-50%)" },
21010
+ children: [
21011
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
21012
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
21013
+ Badge,
21014
+ {
21015
+ className: "px-8 py-1 bg-primary hover:bg-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
21016
+ onClick: () => {
21017
+ window.parent.postMessage(
21018
+ {
21019
+ type: "ow:add-section",
21020
+ insertAfter: sectionGap.insertAfter,
21021
+ insertBefore: sectionGap.insertBefore
21022
+ },
21023
+ "*"
21024
+ );
21025
+ },
21026
+ children: "Add Section"
21027
+ }
21028
+ ),
21029
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
21030
+ ]
21031
+ }
21032
+ ),
21033
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
21034
+ LinkPopover,
21035
+ {
21036
+ panelRef: linkPopoverPanelRef,
21037
+ portalContainer: dialogPortalContainer,
21038
+ open: true,
21039
+ mode: linkPopover.mode ?? "edit",
21040
+ pages: sitePages,
21041
+ sections: currentSections,
21042
+ sectionsByPath,
21043
+ initialTarget: linkPopover.target,
21044
+ existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
21045
+ onClose: closeLinkPopover,
21046
+ onSubmit: handleLinkPopoverSubmit
21047
+ },
21048
+ linkPopover.key
21049
+ ) : null,
21050
+ floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
21051
+ FloatingPanel,
21052
+ {
21053
+ open: true,
21054
+ title: floatingPanel.title,
21055
+ context: floatingPanel.context,
21056
+ position: floatingPanelPos,
21057
+ onPositionChange: setFloatingPanelPos,
21058
+ parentScroll: parentScrollSnap ?? parentScrollRef.current,
21059
+ onClose: closeFloatingPanelOnly,
21060
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
21061
+ SocialsDisplayPanel,
21062
+ {
21063
+ display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
21064
+ onChange: (next) => {
21065
+ changeSocialsDisplay(floatingPanel.row, next);
21066
+ setFloatingPanel({ ...floatingPanel });
21067
+ }
21068
+ }
21069
+ )
21070
+ }
21071
+ ) : null,
21072
+ floatingPanel && floatingPanel.kind === "logo-size" && logoSizeDraft ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
21073
+ FloatingPanel,
21074
+ {
21075
+ open: true,
21076
+ title: floatingPanel.title,
21077
+ context: floatingPanel.context,
21078
+ position: floatingPanelPos,
21079
+ onPositionChange: setFloatingPanelPos,
21080
+ parentScroll: parentScrollSnap ?? parentScrollRef.current,
21081
+ onClose: closeFloatingPanelAndDeselect,
21082
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
21083
+ LogoSizePanel,
21084
+ {
21085
+ viewport: editorViewport,
21086
+ sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
21087
+ mobileFollowing: logoSizeDraft.mobileFollowing,
21088
+ onSizeChange: (px) => {
21089
+ const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
21090
+ ...logoSizeDraft,
21091
+ desktopPx: px,
21092
+ mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
21093
+ };
21094
+ setLogoSizeDraft(next);
21095
+ persistLogoSizeDraft(floatingPanel.placement, next);
21096
+ },
21097
+ onCustomizeMobile: () => {
21098
+ const next = {
21099
+ ...logoSizeDraft,
21100
+ mobileFollowing: false,
21101
+ mobilePx: logoSizeDraft.desktopPx
21102
+ };
21103
+ setLogoSizeDraft(next);
21104
+ persistLogoSizeDraft(floatingPanel.placement, next);
21105
+ },
21106
+ onResetMobile: () => {
21107
+ const next = {
21108
+ ...logoSizeDraft,
21109
+ mobileFollowing: true,
21110
+ mobilePx: logoSizeDraft.desktopPx
21111
+ };
21112
+ setLogoSizeDraft(next);
21113
+ persistLogoSizeDraft(floatingPanel.placement, next);
21114
+ },
21115
+ onUpdateEverywhere: () => {
21116
+ const identity = readLogoIdentityFromDom();
21117
+ postToParent2({ type: "ow:open-logo-settings", ...identity });
21118
+ }
21119
+ }
21120
+ )
21121
+ }
21122
+ ) : null
21123
+ ] }),
21124
+ bridgeRoot
21125
+ ) : null
21126
+ ] });
20561
21127
  }
20562
21128
 
20563
21129
  // src/ui/EmptySection.tsx