@ohhwells/bridge 0.1.68-next.205 → 0.1.68

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
@@ -46,7 +46,6 @@ __export(index_exports, {
46
46
  DropdownMenuItem: () => DropdownMenuItem,
47
47
  DropdownMenuSeparator: () => DropdownMenuSeparator,
48
48
  DropdownMenuTrigger: () => DropdownMenuTrigger,
49
- EmptySection: () => EmptySection,
50
49
  ItemActionToolbar: () => ItemActionToolbar,
51
50
  ItemInteractionLayer: () => ItemInteractionLayer,
52
51
  LinkEditorPanel: () => LinkEditorPanel,
@@ -75,7 +74,7 @@ __export(index_exports, {
75
74
  module.exports = __toCommonJS(index_exports);
76
75
 
77
76
  // src/OhhwellsBridge.tsx
78
- var import_react17 = __toESM(require("react"), 1);
77
+ var import_react16 = __toESM(require("react"), 1);
79
78
  var import_client2 = require("react-dom/client");
80
79
  var import_react_dom3 = require("react-dom");
81
80
 
@@ -157,12 +156,7 @@ function parseAiSectionsState(raw) {
157
156
  media: entry.media && typeof entry.media === "object" ? entry.media : {}
158
157
  }));
159
158
  const removed = Array.isArray(parsed.removed) ? parsed.removed.filter((id) => typeof id === "string" && id.length > 0) : [];
160
- return {
161
- v: 1,
162
- sections,
163
- ...removed.length ? { removed } : {},
164
- ...parsed.hideTemplate === true ? { hideTemplate: true } : {}
165
- };
159
+ return { v: 1, sections, ...removed.length ? { removed } : {} };
166
160
  } catch {
167
161
  return EMPTY_AI_SECTIONS;
168
162
  }
@@ -175,7 +169,6 @@ function applyTreeToState(state, payload) {
175
169
  const entry = {
176
170
  id: payload.id,
177
171
  label: payload.label ?? "Generated section",
178
- ...typeof payload.path === "string" && payload.path ? { path: payload.path } : {},
179
172
  afterSection: payload.mode === "insert" && !insertBefore ? payload.targetSectionId ?? null : null,
180
173
  ...insertBefore && payload.targetSectionId ? { beforeSection: payload.targetSectionId } : {},
181
174
  ...payload.mode === "replace" && payload.targetSectionId ? { replaces: payload.targetSectionId } : {},
@@ -198,317 +191,6 @@ function deleteSectionFromState(state, sectionId) {
198
191
  return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
199
192
  }
200
193
 
201
- // src/lib/brand-chrome.ts
202
- var BRAND_NAME_KEY = "__ohw_brand_name";
203
- var BRAND_TITLE_KEY = "__ohw_site_title";
204
- var BRAND_FAVICON_LETTER_KEY = "__ohw_favicon_letter";
205
- var BRAND_CHROME_KEYS = /* @__PURE__ */ new Set([
206
- BRAND_NAME_KEY,
207
- BRAND_TITLE_KEY,
208
- BRAND_FAVICON_LETTER_KEY
209
- ]);
210
- function upsertMeta(selector, attr, token, value) {
211
- let el = document.head.querySelector(selector);
212
- if (!el) {
213
- el = document.createElement("meta");
214
- el.setAttribute(attr, token);
215
- document.head.appendChild(el);
216
- }
217
- if (el.getAttribute("content") !== value) el.setAttribute("content", value);
218
- }
219
- function escapeXml(value) {
220
- return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
221
- }
222
- function applyLetterFavicon(letter) {
223
- const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" rx="12" fill="#111827"/><text x="32" y="46" font-family="system-ui,-apple-system,Segoe UI,sans-serif" font-size="40" font-weight="700" text-anchor="middle" fill="#ffffff">${escapeXml(letter)}</text></svg>`;
224
- const href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
225
- let link = document.head.querySelector('link[rel="icon"]');
226
- if (!link) {
227
- link = document.createElement("link");
228
- link.rel = "icon";
229
- document.head.appendChild(link);
230
- }
231
- link.type = "image/svg+xml";
232
- if (link.href !== href) link.href = href;
233
- }
234
- function applyBrandChrome(content) {
235
- const name = content[BRAND_NAME_KEY];
236
- if (typeof name === "string" && name.length > 0) {
237
- document.querySelectorAll("[data-ohw-wordmark]").forEach((el) => {
238
- if (el.textContent !== name) el.textContent = name;
239
- if (el.getAttribute("title") !== name) el.setAttribute("title", name);
240
- });
241
- }
242
- const title = content[BRAND_TITLE_KEY];
243
- if (typeof title === "string" && title.length > 0) {
244
- if (document.title !== title) document.title = title;
245
- upsertMeta('meta[property="og:title"]', "property", "og:title", title);
246
- upsertMeta('meta[name="twitter:title"]', "name", "twitter:title", title);
247
- }
248
- const letter = content[BRAND_FAVICON_LETTER_KEY];
249
- if (typeof letter === "string" && letter.length > 0) {
250
- applyLetterFavicon(letter);
251
- }
252
- }
253
-
254
- // src/lib/brand-kit.ts
255
- var BRAND_KIT_KEY = "__ohw_brand";
256
- var BRAND_VAR_PREFIX = "--ohw-brand-";
257
- var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
258
- (role) => `${BRAND_VAR_PREFIX}${role}`
259
- );
260
- var FONT_VARS = {
261
- heading: ["--font-heading", "--font-display", "--brand-font-heading"],
262
- body: ["--font-body", "--brand-font-body"]
263
- };
264
- var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
265
- function brandColorVars(kit) {
266
- const { dark, primary, accent, light } = kit.palette;
267
- const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
268
- return {
269
- [`${BRAND_VAR_PREFIX}primary`]: primary,
270
- [`${BRAND_VAR_PREFIX}accent`]: accent,
271
- [`${BRAND_VAR_PREFIX}light`]: light,
272
- [`${BRAND_VAR_PREFIX}dark`]: dark,
273
- [`${BRAND_VAR_PREFIX}surface`]: mix(light, 95, dark),
274
- [`${BRAND_VAR_PREFIX}border`]: mix(light, 85, dark),
275
- [`${BRAND_VAR_PREFIX}muted`]: mix(dark, 62, light)
276
- };
277
- }
278
- function parseBrandKit(raw) {
279
- if (!raw) return null;
280
- try {
281
- const parsed = JSON.parse(raw);
282
- const p = parsed?.palette;
283
- const f = parsed?.fonts;
284
- if (!p || !f || typeof p.dark !== "string" || typeof p.primary !== "string" || typeof p.accent !== "string" || typeof p.light !== "string" || typeof f.heading !== "string" || typeof f.body !== "string") {
285
- return null;
286
- }
287
- return {
288
- palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
289
- fonts: { heading: f.heading, body: f.body }
290
- };
291
- } catch {
292
- return null;
293
- }
294
- }
295
- function familyOf(stack) {
296
- const first = stack.split(",")[0]?.trim() ?? "";
297
- return first.replace(/^['"]|['"]$/g, "");
298
- }
299
- function loadBrandFonts(families) {
300
- const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
301
- if (unique.length === 0) return;
302
- const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
303
- const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
304
- let link = document.getElementById(BRAND_FONT_LINK_ID);
305
- if (!link) {
306
- link = document.createElement("link");
307
- link.id = BRAND_FONT_LINK_ID;
308
- link.rel = "stylesheet";
309
- document.head.appendChild(link);
310
- }
311
- if (link.href !== href) link.href = href;
312
- }
313
- function applyBrandToDom(kit) {
314
- const root = document.documentElement;
315
- if (!kit) {
316
- for (const name of BRAND_VAR_NAMES) root.style.removeProperty(name);
317
- for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
318
- document.getElementById(BRAND_FONT_LINK_ID)?.remove();
319
- return;
320
- }
321
- for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
322
- for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
323
- for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
324
- loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
325
- }
326
-
327
- // src/lib/section-styles.ts
328
- var STYLE_STORE_KEY = "__ohw_styles";
329
- var STYLE_SHEET_ID = "ohw-section-styles";
330
- function parseStyleStore(raw) {
331
- if (!raw) return null;
332
- try {
333
- const parsed = JSON.parse(raw);
334
- if (parsed?.v !== 1) return null;
335
- return {
336
- v: 1,
337
- sections: typeof parsed.sections === "object" && parsed.sections ? parsed.sections : {},
338
- nodes: typeof parsed.nodes === "object" && parsed.nodes ? parsed.nodes : {}
339
- };
340
- } catch {
341
- return null;
342
- }
343
- }
344
- var BG_VALUES = {
345
- surface: "color-mix(in srgb, var(--ohw-brand-light, var(--color-light, #ECECEB)) 94%, var(--ohw-brand-dark, var(--color-dark, #0C0A09)))",
346
- accent: "var(--ohw-brand-primary, var(--color-primary, #0078E5))",
347
- "accent-soft": "color-mix(in srgb, var(--ohw-brand-primary, var(--color-primary, #0078E5)) 12%, var(--ohw-brand-light, var(--color-light, #FFFFFF)))"
348
- };
349
- var HEADLINE_SIZES = { md: 24, lg: 32, xl: 40, display: 56 };
350
- function styleSheetCss() {
351
- const rules = [];
352
- for (const [tone, value] of Object.entries(BG_VALUES)) {
353
- rules.push(`[data-ohw-style-bg="${tone}"] { background: ${value} !important; }`);
354
- }
355
- rules.push(
356
- `[data-ohw-style-bg="accent"] { color: var(--ohw-brand-light, var(--color-light, #FFFFFF)) !important; }`
357
- );
358
- rules.push(
359
- `[data-ohw-style-distribution="space-between"] { display: flex !important; flex-direction: column; justify-content: space-between; }`,
360
- `[data-ohw-style-distribution="center"] { display: flex !important; flex-direction: column; justify-content: center; }`
361
- );
362
- for (const [scale, size] of Object.entries(HEADLINE_SIZES)) {
363
- rules.push(
364
- `[data-ohw-style-headline="${scale}"] :is(h1, h2, h3) { font-size: ${size}px !important; line-height: 1.15 !important; }`
365
- );
366
- }
367
- rules.push(
368
- `[data-ohw-style-aspect="fill-height"] img { height: 100% !important; aspect-ratio: auto !important; object-fit: cover; }`
369
- );
370
- for (const aspect of ["1:1", "4:5", "3:4", "3:2", "16:9", "2:1", "3:1"]) {
371
- rules.push(
372
- `[data-ohw-style-aspect="${aspect.replace(":", "-")}"] img { aspect-ratio: ${aspect.replace(":", " / ")} !important; height: auto !important; object-fit: cover; }`
373
- );
374
- }
375
- const pad = { tight: 40, balanced: 64, airy: 96 };
376
- for (const [spacing, px] of Object.entries(pad)) {
377
- rules.push(
378
- `[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
379
- );
380
- }
381
- return rules.join("\n");
382
- }
383
- var STYLE_FONT_LINK_ID = "ohw-style-fonts";
384
- function loadStyleFonts(families) {
385
- const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
386
- const existing = document.getElementById(STYLE_FONT_LINK_ID);
387
- if (unique.length === 0) {
388
- existing?.remove();
389
- return;
390
- }
391
- const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
392
- const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
393
- let link = existing;
394
- if (!link) {
395
- link = document.createElement("link");
396
- link.id = STYLE_FONT_LINK_ID;
397
- link.rel = "stylesheet";
398
- document.head.appendChild(link);
399
- }
400
- if (link.href !== href) link.href = href;
401
- }
402
- var SECTION_ATTRS = {
403
- sectionBackground: "data-ohw-style-bg",
404
- textDistribution: "data-ohw-style-distribution",
405
- headlineScale: "data-ohw-style-headline",
406
- imageAspect: "data-ohw-style-aspect",
407
- spacing: "data-ohw-style-spacing"
408
- };
409
- var NODE_WROTE_ATTR = "data-ohw-style-node";
410
- var NODE_PROPS = ["color", "font-family", "font-size", "background"];
411
- function saveInline(el, prop) {
412
- const attr = `data-ohw-style-prev-${prop}`;
413
- if (!el.hasAttribute(attr)) el.setAttribute(attr, el.style.getPropertyValue(prop));
414
- }
415
- function restoreInline(el, prop) {
416
- const attr = `data-ohw-style-prev-${prop}`;
417
- if (!el.hasAttribute(attr)) return;
418
- const prev = el.getAttribute(attr) ?? "";
419
- if (prev) el.style.setProperty(prop, prev);
420
- else el.style.removeProperty(prop);
421
- el.removeAttribute(attr);
422
- }
423
- function ensureStyleSheet() {
424
- let el = document.getElementById(STYLE_SHEET_ID);
425
- if (!el) {
426
- el = document.createElement("style");
427
- el.id = STYLE_SHEET_ID;
428
- document.head.appendChild(el);
429
- }
430
- const css = styleSheetCss();
431
- if (el.textContent !== css) el.textContent = css;
432
- }
433
- function clearSectionAttrs(root) {
434
- for (const attr of Object.values(SECTION_ATTRS)) {
435
- for (const el of Array.from(root.querySelectorAll(`[${attr}]`))) el.removeAttribute(attr);
436
- }
437
- for (const el of Array.from(root.querySelectorAll("[data-ohw-style-bgcolor]"))) {
438
- restoreInline(el, "background");
439
- el.removeAttribute("data-ohw-style-bgcolor");
440
- }
441
- }
442
- function clearNodeProps(root) {
443
- for (const el of Array.from(root.querySelectorAll(`[${NODE_WROTE_ATTR}]`))) {
444
- const h = el;
445
- for (const prop of NODE_PROPS) restoreInline(h, prop);
446
- h.removeAttribute(NODE_WROTE_ATTR);
447
- }
448
- }
449
- function buttonSurfaceOf(el) {
450
- return el.closest("a, button") ?? el;
451
- }
452
- function applyStylesToDom(store) {
453
- ensureStyleSheet();
454
- clearSectionAttrs(document);
455
- clearNodeProps(document);
456
- loadStyleFonts(
457
- store ? Object.values(store.nodes).flatMap((n) => n.fontFamily ? [n.fontFamily] : []) : []
458
- );
459
- if (!store) return;
460
- for (const [sectionId, override] of Object.entries(store.sections)) {
461
- const sections = document.querySelectorAll(
462
- `[data-ohw-section="${CSS.escape(sectionId)}"]`
463
- );
464
- for (const section of Array.from(sections)) {
465
- for (const [prop, attr] of Object.entries(SECTION_ATTRS)) {
466
- const value = override[prop];
467
- if (value === void 0) continue;
468
- if (prop === "sectionBackground" && override.sectionBackgroundColor !== void 0) continue;
469
- section.setAttribute(attr, String(value).replace(":", "-"));
470
- }
471
- if (override.sectionBackgroundColor !== void 0) {
472
- saveInline(section, "background");
473
- section.style.setProperty("background", override.sectionBackgroundColor, "important");
474
- section.setAttribute("data-ohw-style-bgcolor", "");
475
- }
476
- }
477
- }
478
- for (const [key, override] of Object.entries(store.nodes)) {
479
- const nodes = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
480
- for (const el of Array.from(nodes)) {
481
- if (override.color !== void 0) {
482
- saveInline(el, "color");
483
- el.style.setProperty("color", override.color, "important");
484
- el.setAttribute(NODE_WROTE_ATTR, "");
485
- }
486
- if (override.fontFamily !== void 0) {
487
- saveInline(el, "font-family");
488
- el.style.setProperty("font-family", `'${override.fontFamily}'`, "important");
489
- el.setAttribute(NODE_WROTE_ATTR, "");
490
- }
491
- if (override.fontSize !== void 0) {
492
- saveInline(el, "font-size");
493
- el.style.setProperty("font-size", `${override.fontSize}px`, "important");
494
- el.setAttribute(NODE_WROTE_ATTR, "");
495
- }
496
- if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
497
- const surface = buttonSurfaceOf(el);
498
- if (override.buttonBackground !== void 0) {
499
- saveInline(surface, "background");
500
- surface.style.setProperty("background", override.buttonBackground, "important");
501
- }
502
- if (override.buttonText !== void 0) {
503
- saveInline(surface, "color");
504
- surface.style.setProperty("color", override.buttonText, "important");
505
- }
506
- surface.setAttribute(NODE_WROTE_ATTR, "");
507
- }
508
- }
509
- }
510
- }
511
-
512
194
  // src/ui/ai-tree/aiSectionsManager.tsx
513
195
  var import_react_dom = require("react-dom");
514
196
  var import_client = require("react-dom/client");
@@ -523,8 +205,7 @@ function lucideByName(name) {
523
205
  }
524
206
  var typeStyle = (spec, font) => ({
525
207
  fontFamily: font,
526
- // Headings shrink with the viewport (reaching full size around ~900px wide); body copy stays put.
527
- fontSize: spec.size >= 24 ? `clamp(${Math.max(18, Math.round(spec.size * 0.6))}px, ${(spec.size / 9).toFixed(2)}vw, ${spec.size}px)` : spec.size,
208
+ fontSize: spec.size,
528
209
  lineHeight: spec.line,
529
210
  fontWeight: spec.weight
530
211
  });
@@ -539,36 +220,6 @@ var FEATURE_LINE_CSS = [
539
220
  `background-color:currentColor;-webkit-mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px;`,
540
221
  `mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px}`
541
222
  ].join("");
542
- function hexLuminance(color) {
543
- const m = /^#([0-9a-f]{6})$/i.exec(color.trim());
544
- if (!m) return null;
545
- const [r2, g, b] = [0, 2, 4].map((i) => {
546
- const c = parseInt(m[1].slice(i, i + 2), 16) / 255;
547
- return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
548
- });
549
- return 0.2126 * r2 + 0.7152 * g + 0.0722 * b;
550
- }
551
- function hexContrast(a, b) {
552
- const la = hexLuminance(a);
553
- const lb = hexLuminance(b);
554
- if (la === null || lb === null) return null;
555
- const [hi, lo] = la > lb ? [la, lb] : [lb, la];
556
- return (hi + 0.05) / (lo + 0.05);
557
- }
558
- function accentBandContext(brand) {
559
- const p = brand.palette;
560
- const lightWins = (hexContrast(p.light, p.primary) ?? 99) >= (hexContrast(p.dark, p.primary) ?? 0);
561
- if (lightWins) {
562
- return {
563
- brand: { ...brand, palette: { dark: p.light, primary: p.light, accent: p.light, light: p.primary } },
564
- buttonLabel: p.primary
565
- };
566
- }
567
- return {
568
- brand: { ...brand, palette: { dark: p.dark, primary: p.dark, accent: p.dark, light: p.light } },
569
- buttonLabel: p.light
570
- };
571
- }
572
223
  function textAttrs(ctx, path) {
573
224
  return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
574
225
  }
@@ -581,8 +232,6 @@ var AI_RESPONSIVE_CSS = [
581
232
  " [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
582
233
  " [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
583
234
  " [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
584
- " [data-ai-responsive] { overflow-x: hidden; }",
585
- " [data-ai-responsive] img { max-width: 100%; }",
586
235
  "}"
587
236
  ].join("\n");
588
237
  var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
@@ -660,7 +309,7 @@ function ButtonEl({
660
309
  }) {
661
310
  const secondary = slots.variant === "secondary";
662
311
  const href = str(slots.href);
663
- const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`), "data-ohw-role": "button" } : {};
312
+ const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`) } : {};
664
313
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
665
314
  "a",
666
315
  {
@@ -676,7 +325,7 @@ function ButtonEl({
676
325
  textDecoration: "none",
677
326
  cursor: "pointer",
678
327
  ...typeStyle(AI_TREE_TOKENS.type.button, ctx.brand.fonts.body),
679
- ...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color: ctx.buttonLabel ?? AI_TREE_TOKENS.textPrimaryForeground }
328
+ ...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color: AI_TREE_TOKENS.textPrimaryForeground }
680
329
  },
681
330
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
682
331
  }
@@ -1578,14 +1227,11 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1578
1227
  return null;
1579
1228
  }
1580
1229
  const resolvedBrand = brand ?? AI_DEFAULT_BRAND;
1581
- const band = (tree.settings ?? {}).sectionBackground === "accent" ? accentBandContext(resolvedBrand) : null;
1582
- const blockBrand = band?.brand ?? resolvedBrand;
1583
1230
  const ctx = {
1584
- brand: blockBrand,
1231
+ brand: resolvedBrand,
1585
1232
  resolveMedia: resolveMedia ?? (() => null),
1586
- cardSurface: blockBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${blockBrand.palette.light} 90%, ${blockBrand.palette.dark})`,
1587
- keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
1588
- ...band ? { buttonLabel: band.buttonLabel } : {}
1233
+ cardSurface: resolvedBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${resolvedBrand.palette.light} 90%, ${resolvedBrand.palette.dark})`,
1234
+ keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null
1589
1235
  };
1590
1236
  const settings = tree.settings ?? {};
1591
1237
  const pad = AI_TREE_TOKENS.sectionPadding[settings.spacing ?? "balanced"];
@@ -1593,20 +1239,6 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1593
1239
  const overlayAlpha = { low: 0.25, medium: 0.45, high: 0.65 }[settings.overlayIntensity ?? "medium"];
1594
1240
  const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
1595
1241
  const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
1596
- const toneBackground = (() => {
1597
- const { dark, primary, light } = resolvedBrand.palette;
1598
- switch (settings.sectionBackground) {
1599
- case "surface":
1600
- return `color-mix(in srgb, ${light} 94%, ${dark})`;
1601
- case "accent":
1602
- return primary;
1603
- case "accent-soft":
1604
- return `color-mix(in srgb, ${primary} 12%, ${light})`;
1605
- default:
1606
- return void 0;
1607
- }
1608
- })();
1609
- const distributed = !isOverlay && settings.textDistribution;
1610
1242
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1611
1243
  "section",
1612
1244
  {
@@ -1616,11 +1248,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1616
1248
  style: {
1617
1249
  position: "relative",
1618
1250
  padding: `${pad}px 0`,
1619
- background: toneBackground ?? (isOverlay && !backgroundUrl ? "#DBEAFE" : void 0),
1251
+ background: isOverlay && !backgroundUrl ? "#DBEAFE" : void 0,
1620
1252
  backgroundImage: backgroundUrl ? `url(${backgroundUrl})` : void 0,
1621
1253
  backgroundSize: "cover",
1622
- backgroundPosition: "center",
1623
- color: settings.sectionBackground === "accent" ? blockBrand.palette.dark : void 0
1254
+ backgroundPosition: "center"
1624
1255
  },
1625
1256
  children: [
1626
1257
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
@@ -1644,24 +1275,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1644
1275
  display: "grid",
1645
1276
  gridTemplateColumns: "repeat(12, 1fr)",
1646
1277
  gap: AI_TREE_TOKENS.spacing6,
1647
- alignItems: distributed === "space-between" ? "stretch" : (distributed ?? settings.verticalPosition) === "top" ? "start" : "center",
1278
+ alignItems: settings.verticalPosition === "top" ? "start" : "center",
1648
1279
  marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
1649
1280
  },
1650
- children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1651
- "div",
1652
- {
1653
- "data-ai-cell": "",
1654
- style: {
1655
- gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
1656
- minWidth: 0,
1657
- // space-between: each column becomes a flex column whose content spreads over
1658
- // the full row height instead of clumping at the top.
1659
- ...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
1660
- },
1661
- children: renderNode(block, ctx, `r${r2}.b${b}`)
1662
- },
1663
- b
1664
- ))
1281
+ children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`, minWidth: 0 }, children: renderNode(block, ctx, `r${r2}.b${b}`) }, b))
1665
1282
  },
1666
1283
  r2
1667
1284
  ))
@@ -1677,36 +1294,17 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
1677
1294
  var CONTAINER_ATTR = "data-ohw-ai-generated";
1678
1295
  var REPLACED_ATTR = "data-ohw-ai-replaced-by";
1679
1296
  var REMOVED_ATTR = "data-ohw-ai-removed";
1680
- var TEMPLATE_HIDDEN_ATTR = "data-ohw-ai-template-hidden";
1681
- var CHROME_SECTION_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
1682
- function readRootVar(name) {
1683
- if (typeof document === "undefined") return "";
1684
- return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
1685
- }
1686
- function deriveBrandOverride() {
1687
- const dark = readRootVar("--ohw-brand-dark");
1688
- const primary = readRootVar("--ohw-brand-primary");
1689
- const light = readRootVar("--ohw-brand-light");
1690
- if (!dark || !primary || !light) return null;
1691
- const accent = readRootVar("--ohw-brand-accent");
1692
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1693
- const body = readRootVar("--font-body");
1694
- return {
1695
- palette: { dark, primary, accent: accent || dark, light },
1696
- fonts: {
1697
- heading: heading || AI_DEFAULT_BRAND.fonts.heading,
1698
- body: body || AI_DEFAULT_BRAND.fonts.body
1699
- }
1700
- };
1701
- }
1702
1297
  function deriveTemplateBrand() {
1703
- const dark = readRootVar("--color-dark");
1704
- const primary = readRootVar("--color-primary");
1705
- const light = readRootVar("--color-light");
1298
+ if (typeof document === "undefined") return null;
1299
+ const cs = getComputedStyle(document.documentElement);
1300
+ const read = (name) => cs.getPropertyValue(name).trim();
1301
+ const dark = read("--color-dark");
1302
+ const primary = read("--color-primary");
1303
+ const light = read("--color-light");
1706
1304
  if (!dark || !primary || !light) return null;
1707
- const accent = readRootVar("--color-accent");
1708
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1709
- const body = readRootVar("--font-body");
1305
+ const accent = read("--color-accent");
1306
+ const heading = read("--font-heading") || read("--font-display");
1307
+ const body = read("--font-body");
1710
1308
  return {
1711
1309
  palette: { dark, primary, accent: accent || dark, light },
1712
1310
  fonts: {
@@ -1778,24 +1376,6 @@ function syncRemovedSections(state) {
1778
1376
  }
1779
1377
  }
1780
1378
  }
1781
- function syncTemplateHidden(state, pageHasSections) {
1782
- const hide = state.hideTemplate === true && pageHasSections;
1783
- for (const el of Array.from(document.querySelectorAll(`[${TEMPLATE_HIDDEN_ATTR}]`))) {
1784
- if (!hide) {
1785
- el.style.removeProperty("display");
1786
- el.removeAttribute(TEMPLATE_HIDDEN_ATTR);
1787
- }
1788
- }
1789
- if (!hide) return;
1790
- for (const el of Array.from(document.querySelectorAll("[data-ohw-section]"))) {
1791
- if (el.hasAttribute(CONTAINER_ATTR)) continue;
1792
- if (CHROME_SECTION_IDS.has(el.getAttribute("data-ohw-section") ?? "")) continue;
1793
- if (el.parentElement?.closest("[data-ohw-section]")) continue;
1794
- if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(REMOVED_ATTR)) continue;
1795
- el.style.display = "none";
1796
- el.setAttribute(TEMPLATE_HIDDEN_ATTR, "");
1797
- }
1798
- }
1799
1379
  function syncReplacedOriginals(state) {
1800
1380
  for (const el of document.querySelectorAll(`[${REPLACED_ATTR}]`)) {
1801
1381
  const byId = el.getAttribute(REPLACED_ATTR) ?? "";
@@ -1816,12 +1396,8 @@ function syncReplacedOriginals(state) {
1816
1396
  }
1817
1397
  function applyAiSectionsToDom(state, options) {
1818
1398
  if (typeof document === "undefined") return;
1819
- const brandOverride = deriveBrandOverride();
1820
1399
  const templateBrand = deriveTemplateBrand();
1821
- const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
1822
- const pagePath = window.location.pathname;
1823
- const pageSections = state.sections.filter((entry) => !entry.path || entry.path === pagePath);
1824
- const activeIds = new Set(pageSections.map((entry) => entry.id));
1400
+ const activeIds = new Set(state.sections.map((entry) => entry.id));
1825
1401
  for (const [id, section] of mounted) {
1826
1402
  if (!activeIds.has(id)) {
1827
1403
  section.root.unmount();
@@ -1829,8 +1405,8 @@ function applyAiSectionsToDom(state, options) {
1829
1405
  mounted.delete(id);
1830
1406
  }
1831
1407
  }
1832
- for (const entry of pageSections) {
1833
- const serialized = JSON.stringify(entry) + brandKey;
1408
+ for (const entry of state.sections) {
1409
+ const serialized = JSON.stringify(entry);
1834
1410
  const existing = mounted.get(entry.id);
1835
1411
  if (existing && existing.serialized === serialized && existing.container.isConnected) {
1836
1412
  continue;
@@ -1844,7 +1420,6 @@ function applyAiSectionsToDom(state, options) {
1844
1420
  mounted.delete(entry.id);
1845
1421
  }
1846
1422
  container.setAttribute("data-ohw-section", entry.id);
1847
- container.setAttribute("data-ohw-instance", entry.id);
1848
1423
  container.setAttribute("data-ohw-section-label", entry.label);
1849
1424
  placeContainer(container, entry);
1850
1425
  const root = mounted.get(entry.id)?.root ?? (0, import_client.createRoot)(container);
@@ -1855,7 +1430,7 @@ function applyAiSectionsToDom(state, options) {
1855
1430
  AiTreeRenderer,
1856
1431
  {
1857
1432
  tree: entry.tree,
1858
- brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1433
+ brand: entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1859
1434
  resolveMedia,
1860
1435
  editKeyPrefix: `ai.${entry.id}`
1861
1436
  }
@@ -1866,7 +1441,6 @@ function applyAiSectionsToDom(state, options) {
1866
1441
  }
1867
1442
  syncReplacedOriginals(state);
1868
1443
  syncRemovedSections(state);
1869
- syncTemplateHidden(state, pageSections.length > 0);
1870
1444
  }
1871
1445
 
1872
1446
  // src/useLinkHrefGuardian.ts
@@ -2473,7 +2047,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2473
2047
  const autoId = (0, import_react5.useId)();
2474
2048
  const insertAfter = insertAfterProp ?? autoId;
2475
2049
  const [schedule, setSchedule] = (0, import_react5.useState)(null);
2476
- const [loading, setLoading] = (0, import_react5.useState)(initialScheduleId !== null);
2050
+ const [loading, setLoading] = (0, import_react5.useState)(true);
2477
2051
  const [inEditor, setInEditor] = (0, import_react5.useState)(false);
2478
2052
  const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
2479
2053
  const [modalState, setModalState] = (0, import_react5.useState)(null);
@@ -2647,10 +2221,8 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2647
2221
  "*"
2648
2222
  );
2649
2223
  };
2224
+ if (!inEditor && !loading && !schedule) return null;
2650
2225
  const sectionId = `scheduling-${insertAfter}`;
2651
- if (!inEditor && !loading && !schedule) {
2652
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
2653
- }
2654
2226
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2655
2227
  "section",
2656
2228
  {
@@ -7558,17 +7130,13 @@ function MediaOverlay({
7558
7130
  hover,
7559
7131
  isUploading,
7560
7132
  fadingOut = false,
7561
- selected = false,
7562
- hovered = false,
7563
7133
  onFadeOutComplete,
7564
7134
  onReplace,
7565
- onSelect,
7566
7135
  onVideoSettingsChange
7567
7136
  }) {
7568
7137
  const { rect } = hover;
7569
7138
  const skeletonRef = React7.useRef(null);
7570
7139
  const isVideo = hover.elementType === "video";
7571
- const showChrome = !selected || hovered;
7572
7140
  const autoplay = hover.videoAutoplay ?? true;
7573
7141
  const muted = hover.videoMuted ?? true;
7574
7142
  const box = {
@@ -7603,7 +7171,7 @@ function MediaOverlay({
7603
7171
  }
7604
7172
  );
7605
7173
  }
7606
- const settingsBar = isVideo && !hover.isDragOver && showChrome ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7174
+ const settingsBar = isVideo && !hover.isDragOver ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7607
7175
  "div",
7608
7176
  {
7609
7177
  "data-ohw-bridge": "",
@@ -7673,13 +7241,11 @@ function MediaOverlay({
7673
7241
  // in-document, pointer-events does it natively. The button below opts back in, so
7674
7242
  // Replace still works.
7675
7243
  pointerEvents: hover.hasTextOverlap ? "none" : "auto",
7676
- // Selected: a firm component ring with no wash, so the image reads as chosen rather
7677
- // than hovered. Hover keeps the existing tinted preview.
7678
- boxShadow: selected ? "inset 0 0 0 2px var(--color-primary)" : "inset 0 0 0 1.5px var(--color-primary)",
7679
- background: selected ? "transparent" : "color-mix(in srgb, var(--color-primary) 20%, transparent)"
7244
+ boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
7245
+ background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
7680
7246
  },
7681
- onClick: () => onSelect && !selected ? onSelect(hover.key) : onReplace(hover.key),
7682
- children: showChrome && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7247
+ onClick: () => onReplace(hover.key),
7248
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
7683
7249
  Button,
7684
7250
  {
7685
7251
  "data-ohw-media-overlay": "",
@@ -7768,9 +7334,6 @@ var import_lucide_react7 = require("lucide-react");
7768
7334
 
7769
7335
  // src/lib/sections.ts
7770
7336
  var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
7771
- function isChromeSection(el) {
7772
- return el.matches("header, nav, footer, aside");
7773
- }
7774
7337
  function titleCaseSectionId(id) {
7775
7338
  return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
7776
7339
  }
@@ -7781,8 +7344,6 @@ function parseSectionsFromRoot(root) {
7781
7344
  const id = el.getAttribute("data-ohw-section") ?? "";
7782
7345
  if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
7783
7346
  if (el.parentElement?.closest("[data-ohw-section]")) continue;
7784
- if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
7785
- continue;
7786
7347
  seen.add(id);
7787
7348
  const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
7788
7349
  sections.push({ id, label });
@@ -7800,12 +7361,8 @@ function parseSectionsFromHtml(html) {
7800
7361
 
7801
7362
  // src/ui/ai-section/AiSectionOverlay.tsx
7802
7363
  var import_jsx_runtime17 = require("react/jsx-runtime");
7803
- function findSectionElement(instanceId) {
7804
- const escaped = CSS.escape(instanceId);
7805
- return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
7806
- }
7807
- function readRect(instanceId) {
7808
- const el = findSectionElement(instanceId);
7364
+ function readRect(sectionId) {
7365
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7809
7366
  if (!el) return null;
7810
7367
  const r2 = el.getBoundingClientRect();
7811
7368
  if (r2.width <= 0 || r2.height <= 0) return null;
@@ -7828,7 +7385,7 @@ function useLiveSectionRect(sectionId) {
7828
7385
  const opts = { capture: true, passive: true };
7829
7386
  window.addEventListener("scroll", update, opts);
7830
7387
  window.addEventListener("resize", update);
7831
- const el = findSectionElement(sectionId);
7388
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7832
7389
  const ro = el ? new ResizeObserver(update) : null;
7833
7390
  if (el && ro) ro.observe(el);
7834
7391
  const interval = setInterval(update, 500);
@@ -7841,14 +7398,6 @@ function useLiveSectionRect(sectionId) {
7841
7398
  }, [sectionId]);
7842
7399
  return rect;
7843
7400
  }
7844
- function computeSectionBoundaryFlags(instanceId) {
7845
- const topLevel = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
7846
- (el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
7847
- );
7848
- const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
7849
- if (index === -1) return { isFirst: true, isLast: true };
7850
- return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
7851
- }
7852
7401
  var PRIMARY2 = "#0885FE";
7853
7402
  function edgeAwareRadius(rect) {
7854
7403
  const container = window.innerWidth <= 480 ? 16 : 24;
@@ -7922,7 +7471,6 @@ function AiSectionOverlay({
7922
7471
  }) {
7923
7472
  const [selectedId, setSelectedId] = (0, import_react8.useState)(null);
7924
7473
  const [reviewId, setReviewId] = (0, import_react8.useState)(null);
7925
- const [reviewButtonsHidden, setReviewButtonsHidden] = (0, import_react8.useState)(false);
7926
7474
  const reviewIdRef = (0, import_react8.useRef)(null);
7927
7475
  reviewIdRef.current = reviewId;
7928
7476
  const selectedIdRef = (0, import_react8.useRef)(null);
@@ -7931,7 +7479,7 @@ function AiSectionOverlay({
7931
7479
  (el) => {
7932
7480
  postToParent2({
7933
7481
  type: "ow:section-selected",
7934
- sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
7482
+ sectionId: el?.dataset.ohwSection ?? null,
7935
7483
  sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
7936
7484
  });
7937
7485
  },
@@ -7940,7 +7488,7 @@ function AiSectionOverlay({
7940
7488
  const selectFromElement = (0, import_react8.useCallback)(
7941
7489
  (el, options) => {
7942
7490
  const sectionEl = el?.closest("[data-ohw-section]") ?? null;
7943
- const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
7491
+ const id = sectionEl?.dataset.ohwSection ?? null;
7944
7492
  if (id === selectedIdRef.current) return;
7945
7493
  setSelectedId(id);
7946
7494
  if (options?.report !== false) report(sectionEl);
@@ -7981,10 +7529,9 @@ function AiSectionOverlay({
7981
7529
  }
7982
7530
  const found = readRect(sectionId) != null;
7983
7531
  setReviewId(found ? sectionId : null);
7984
- setReviewButtonsHidden(e.data.hideButtons === true);
7985
7532
  postToParent2({ type: "ow:ai-review-started", sectionId, found });
7986
7533
  if (found) {
7987
- document.querySelector(`[data-ohw-instance="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
7534
+ document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
7988
7535
  }
7989
7536
  }
7990
7537
  };
@@ -8003,7 +7550,7 @@ function AiSectionOverlay({
8003
7550
  return;
8004
7551
  }
8005
7552
  const sec = t.closest("[data-ohw-section]");
8006
- setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
7553
+ setHoveredId(sec?.dataset.ohwSection ?? null);
8007
7554
  };
8008
7555
  const onLeave = () => setHoveredId(null);
8009
7556
  document.addEventListener("mousemove", onMove, { passive: true });
@@ -8035,30 +7582,9 @@ function AiSectionOverlay({
8035
7582
  },
8036
7583
  [postToParent2]
8037
7584
  );
8038
- const activeSelectionId = reviewId ? null : selectedId;
8039
- const selectionRect = useLiveSectionRect(activeSelectionId);
7585
+ const selectionRect = useLiveSectionRect(reviewId ? null : selectedId);
8040
7586
  const reviewRect = useLiveSectionRect(reviewId);
8041
7587
  const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
8042
- (0, import_react8.useEffect)(() => {
8043
- const selectedEl = activeSelectionId ? findSectionElement(activeSelectionId) : null;
8044
- if (!activeSelectionId || !selectionRect || selectedEl && isChromeSection(selectedEl)) {
8045
- postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
8046
- return;
8047
- }
8048
- const { isFirst, isLast } = computeSectionBoundaryFlags(activeSelectionId);
8049
- postToParent2({
8050
- type: "ow:section-rect",
8051
- instanceId: activeSelectionId,
8052
- rect: {
8053
- top: selectionRect.top + window.scrollY,
8054
- left: selectionRect.left + window.scrollX,
8055
- width: selectionRect.width,
8056
- height: selectionRect.height
8057
- },
8058
- isFirst,
8059
- isLast
8060
- });
8061
- }, [activeSelectionId, selectionRect, postToParent2]);
8062
7588
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
8063
7589
  hoverRect && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
8064
7590
  "div",
@@ -8109,16 +7635,13 @@ function AiSectionOverlay({
8109
7635
  border: `2px solid ${PRIMARY2}`,
8110
7636
  borderRadius: edgeAwareRadius(reviewRect),
8111
7637
  zIndex: 2147483200,
8112
- // The veil itself: swallows clicks so the section stays locked until decided. This
8113
- // stopPropagation only guards the bubble phase; the bridge's capture-phase click
8114
- // handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
8115
- // Accept/Discard resolves to the media beneath and opens the file picker.
7638
+ // The veil itself: swallows clicks so the section stays locked until decided.
8116
7639
  background: "rgba(8, 133, 254, 0.04)",
8117
7640
  pointerEvents: "auto",
8118
7641
  cursor: "default"
8119
7642
  },
8120
7643
  onClick: (e) => e.stopPropagation(),
8121
- children: !reviewButtonsHidden && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
7644
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
8122
7645
  "div",
8123
7646
  {
8124
7647
  style: {
@@ -8143,58 +7666,6 @@ function AiSectionOverlay({
8143
7666
 
8144
7667
  // src/lib/section-instances.ts
8145
7668
  var SECTION_ORDER_KEY = "__ohw_section_order";
8146
- function topLevelSections() {
8147
- return Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
8148
- (el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
8149
- );
8150
- }
8151
- function instanceIdOf(el) {
8152
- return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
8153
- }
8154
- function planSectionMove(instanceId, targetIndex, currentPath) {
8155
- const sections = topLevelSections();
8156
- const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
8157
- if (index === -1) return null;
8158
- const dragged = sections[index];
8159
- const others = sections.filter((_, i) => i !== index);
8160
- const clamped = Math.max(0, Math.min(targetIndex, others.length));
8161
- const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
8162
- return reordered.map((el, order) => ({
8163
- instanceId: instanceIdOf(el),
8164
- type: el.getAttribute("data-ohw-section") ?? "",
8165
- order,
8166
- pagePath: currentPath
8167
- }));
8168
- }
8169
- function moveSectionInstance(instanceId, direction, currentPath) {
8170
- const sections = topLevelSections();
8171
- const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
8172
- if (index === -1) return null;
8173
- const siblingIndex = direction === "up" ? index - 1 : index + 1;
8174
- if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
8175
- const entries = planSectionMove(instanceId, siblingIndex, currentPath);
8176
- if (!entries) return null;
8177
- applyPersistedOrder(entries);
8178
- return entries;
8179
- }
8180
- function applyPersistedOrder(entries) {
8181
- if (entries.length === 0) return;
8182
- const sections = topLevelSections();
8183
- if (sections.length === 0) return;
8184
- const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
8185
- const ordered = [...sections].sort((a, b) => {
8186
- const aOrder = orderIndex.get(instanceIdOf(a));
8187
- const bOrder = orderIndex.get(instanceIdOf(b));
8188
- if (aOrder === void 0 && bOrder === void 0) return 0;
8189
- if (aOrder === void 0) return 1;
8190
- if (bOrder === void 0) return -1;
8191
- return aOrder - bOrder;
8192
- });
8193
- const parent = sections[0].parentElement;
8194
- if (!parent) return;
8195
- const anchor = sections[sections.length - 1].nextSibling;
8196
- ordered.forEach((el) => parent.insertBefore(el, anchor));
8197
- }
8198
7669
  function getPageSectionOrderEntries(raw, currentPath) {
8199
7670
  if (!raw) return [];
8200
7671
  try {
@@ -8232,7 +7703,6 @@ function initSectionInstancesFromContent(content, currentPath) {
8232
7703
  rekeySectionSubtree(clone, entry.instanceId);
8233
7704
  original.insertAdjacentElement("afterend", clone);
8234
7705
  }
8235
- applyPersistedOrder(entries);
8236
7706
  }
8237
7707
 
8238
7708
  // src/OhhwellsBridge.tsx
@@ -10857,8 +10327,7 @@ function findSocialsRow(el) {
10857
10327
  }
10858
10328
  function isSocialsRow(el) {
10859
10329
  const anchors = Array.from(el.querySelectorAll("a"));
10860
- if (!anchors.length || !anchors.some((anchor) => isSocialItem(anchor))) return false;
10861
- return findSocialsRow(anchors[0]) === el;
10330
+ return anchors.length > 0 && anchors.every((anchor) => isSocialItem(anchor));
10862
10331
  }
10863
10332
  var MAX_SOCIAL_ITEMS_PER_ROW = 7;
10864
10333
  function canAddSocialItem(row) {
@@ -10896,7 +10365,6 @@ function markSocialsRows(root = document) {
10896
10365
  });
10897
10366
  listSocialsRows(root).forEach((row) => {
10898
10367
  row.setAttribute(SOCIALS_ROW_ATTR, "");
10899
- allowRowToWrap(row);
10900
10368
  const items = listSocialItems(row);
10901
10369
  const firstUnit = items[0] ? socialRowUnit(items[0], row) : null;
10902
10370
  if (firstUnit) rowTemplates.set(rowKeyOf(row), firstUnit.outerHTML);
@@ -11191,29 +10659,7 @@ function applySocialsDisplayToRow(row, display) {
11191
10659
  const icon = item.querySelector(ICON_SELECTOR);
11192
10660
  if (label) label.style.display = display.text ? "" : "none";
11193
10661
  if (icon) icon.style.display = display.icon ? "" : "none";
11194
- layOutIconAndLabel(item, Boolean(display.text && display.icon));
11195
10662
  });
11196
- allowRowToWrap(row);
11197
- }
11198
- function layOutIconAndLabel(item, on) {
11199
- const hasBoth = Boolean(item.querySelector(ICON_SELECTOR)) && Boolean(socialLabelElement(item));
11200
- if (!hasBoth) {
11201
- item.style.display = "";
11202
- item.style.alignItems = "";
11203
- item.style.gap = "";
11204
- item.style.whiteSpace = "";
11205
- item.style.flex = "";
11206
- return;
11207
- }
11208
- item.style.display = on ? "inline-flex" : "";
11209
- item.style.alignItems = on ? "center" : "";
11210
- item.style.gap = on ? "8px" : "";
11211
- item.style.whiteSpace = on ? "nowrap" : "";
11212
- item.style.flex = on ? "0 0 auto" : "";
11213
- }
11214
- function allowRowToWrap(row) {
11215
- const display = row.ownerDocument.defaultView?.getComputedStyle(row).display ?? "";
11216
- if (display === "flex" || display === "inline-flex") row.style.flexWrap = "wrap";
11217
10663
  }
11218
10664
  function applySocialsDisplayFromContent(content, root = document) {
11219
10665
  const stored = parseSocialsDisplay(content[SOCIALS_DISPLAY_KEY]);
@@ -12423,7 +11869,6 @@ function readLogoSizeState(content, placement) {
12423
11869
  function getLogoElement(el) {
12424
11870
  const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
12425
11871
  if (marked) return marked;
12426
- if (el.closest('[data-ohw-editable="icon"]')) return null;
12427
11872
  const root = el.closest("nav, [data-ohw-nav-root], footer");
12428
11873
  if (!root) return null;
12429
11874
  const anchor = el.closest("a");
@@ -13297,449 +12742,122 @@ function useNavItemDrag({
13297
12742
  };
13298
12743
  }
13299
12744
 
13300
- // src/useSectionDrag.ts
13301
- var import_react15 = require("react");
12745
+ // src/ui/footer-container-chrome.tsx
12746
+ var import_lucide_react15 = require("lucide-react");
12747
+ var import_jsx_runtime29 = require("react/jsx-runtime");
12748
+ function FooterContainerChrome({
12749
+ rect,
12750
+ onAdd,
12751
+ addDisabled = false
12752
+ }) {
12753
+ const chromeGap = 6;
12754
+ const buttonMargin = 7;
12755
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12756
+ "div",
12757
+ {
12758
+ "data-ohw-footer-container-chrome": "",
12759
+ "data-ohw-bridge": "",
12760
+ className: "pointer-events-none fixed z-[2147483647]",
12761
+ style: {
12762
+ top: rect.top - chromeGap,
12763
+ left: rect.left - chromeGap,
12764
+ width: rect.width + chromeGap * 2,
12765
+ height: rect.height + chromeGap * 2
12766
+ },
12767
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(Tooltip, { children: [
12768
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12769
+ "button",
12770
+ {
12771
+ type: "button",
12772
+ "data-ohw-footer-add-button": "",
12773
+ disabled: addDisabled,
12774
+ className: "pointer-events-auto absolute left-1/2 flex size-7 -translate-x-1/2 -translate-y-full items-center justify-center rounded-[10px] border border-border bg-background p-0.5 shadow-sm transition-colors hover:bg-muted/80 disabled:pointer-events-none disabled:opacity-40",
12775
+ style: { top: chromeGap - buttonMargin },
12776
+ "aria-label": "Add item",
12777
+ onMouseDown: (e) => {
12778
+ e.preventDefault();
12779
+ e.stopPropagation();
12780
+ },
12781
+ onClick: (e) => {
12782
+ e.preventDefault();
12783
+ e.stopPropagation();
12784
+ if (addDisabled) return;
12785
+ onAdd();
12786
+ },
12787
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12788
+ }
12789
+ ) }),
12790
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
12791
+ ] })
12792
+ }
12793
+ ) });
12794
+ }
13302
12795
 
13303
- // src/lib/section-dnd.ts
13304
- function isFooterSection(el) {
13305
- return el.dataset.ohwSection === "footer";
12796
+ // src/lib/carousel.ts
12797
+ var import_react15 = require("react");
12798
+ var CAROUSEL_ATTR = "data-ohw-carousel";
12799
+ var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
12800
+ var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
12801
+ var CAROUSEL_EVENT = "ohw:carousel-change";
12802
+ function listCarouselKeys() {
12803
+ const keys = /* @__PURE__ */ new Set();
12804
+ document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
12805
+ const key = el.getAttribute("data-ohw-key");
12806
+ if (key) keys.add(key);
12807
+ });
12808
+ return [...keys];
13306
12809
  }
13307
- function buildSectionDropSlots(draggedInstanceId) {
13308
- const sections = topLevelSections().filter(
13309
- (el) => instanceIdOf(el) !== draggedInstanceId && !isFooterSection(el)
12810
+ function containersForKey(key) {
12811
+ return Array.from(
12812
+ document.querySelectorAll(`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`)
13310
12813
  );
13311
- const slots = [];
13312
- if (sections.length === 0) return slots;
13313
- const left = 0;
13314
- const width = document.documentElement.clientWidth;
13315
- for (let i = 0; i <= sections.length; i++) {
13316
- let y;
13317
- if (i === 0) {
13318
- y = sections[0].getBoundingClientRect().top;
13319
- } else if (i === sections.length) {
13320
- y = sections[sections.length - 1].getBoundingClientRect().bottom;
13321
- } else {
13322
- const prev = sections[i - 1].getBoundingClientRect();
13323
- const next = sections[i].getBoundingClientRect();
13324
- y = (prev.bottom + next.top) / 2;
13325
- }
13326
- slots.push({ insertIndex: i, y, left, width });
12814
+ }
12815
+ function isCarouselKey(key) {
12816
+ return containersForKey(key).length > 0;
12817
+ }
12818
+ function parseSlides(raw) {
12819
+ if (!raw) return [];
12820
+ try {
12821
+ const parsed = JSON.parse(raw);
12822
+ if (!Array.isArray(parsed)) return [];
12823
+ return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
12824
+ } catch {
12825
+ return [];
13327
12826
  }
13328
- return slots;
13329
12827
  }
13330
- function hitTestSectionDropSlot(y, slots) {
13331
- let best = null;
13332
- for (const slot of slots) {
13333
- const dist = Math.abs(y - slot.y);
13334
- if (!best || dist < best.dist) best = { slot, dist };
12828
+ function readCarouselValue(key) {
12829
+ const container = containersForKey(key)[0];
12830
+ if (!container) return [];
12831
+ const fromAttr = parseSlides(container.getAttribute(CAROUSEL_VALUE_ATTR));
12832
+ if (fromAttr.length > 0) return fromAttr;
12833
+ return Array.from(container.querySelectorAll(`[${CAROUSEL_SLIDE_ATTR}]`)).filter((slide) => slide.closest(`[${CAROUSEL_ATTR}]`) === container).sort((a, b) => slideIndex(a) - slideIndex(b)).map((slide) => {
12834
+ const img = slide instanceof HTMLImageElement ? slide : slide.querySelector("img");
12835
+ return { src: img?.src ?? "", alt: img?.alt ?? "" };
12836
+ });
12837
+ }
12838
+ function slideIndex(el) {
12839
+ const raw = el.getAttribute(CAROUSEL_SLIDE_ATTR);
12840
+ const n = raw ? parseInt(raw, 10) : NaN;
12841
+ return Number.isFinite(n) ? n : 0;
12842
+ }
12843
+ function applyCarouselValue(key, slides) {
12844
+ const value = JSON.stringify(slides);
12845
+ for (const container of containersForKey(key)) {
12846
+ if (container.getAttribute(CAROUSEL_VALUE_ATTR) === value) continue;
12847
+ container.setAttribute(CAROUSEL_VALUE_ATTR, value);
12848
+ container.dispatchEvent(
12849
+ new CustomEvent(CAROUSEL_EVENT, { detail: { images: slides } })
12850
+ );
13335
12851
  }
13336
- return best?.slot ?? null;
13337
12852
  }
13338
-
13339
- // src/useSectionDrag.ts
13340
- var PRESS_THRESHOLD = 10;
13341
- var EDGE_ZONE = 60;
13342
- var MAX_AUTO_SCROLL_SPEED = 18;
13343
- var SECTION_DRAG_EXCLUDED_SELECTOR = [
13344
- "[data-ohw-toolbar]",
13345
- "[data-ohw-edit-chrome]",
13346
- "[data-ohw-item-interaction]",
13347
- "[data-ohw-drag-handle-container]",
13348
- '[data-slot="drag-handle"]',
13349
- "[data-ohw-item-toolbar-anchor]",
13350
- "[data-ohw-item-drag-surface]",
13351
- "[data-ohw-more-menu]",
13352
- '[data-slot="dropdown-menu-content"]',
13353
- '[data-slot="dropdown-menu-item"]',
13354
- "[data-ohw-state-toggle]",
13355
- "[data-ohw-max-badge]",
13356
- "[data-ohw-floating-panel]",
13357
- "[data-ohw-section-picker]",
13358
- "[data-ohw-link-popover-root]",
13359
- "[data-ohw-link-modal-root]",
13360
- "[data-ohw-link-page-dropdown]",
13361
- '[data-slot="popover-content"]',
13362
- '[data-slot="dialog-content"]',
13363
- '[data-slot="dialog-overlay"]',
13364
- "[data-ohw-ai-review]",
13365
- "[data-ohw-editable]",
13366
- "[data-ohw-editable-state]",
13367
- "[contenteditable]",
13368
- "[data-ohw-href-key]",
13369
- "[data-ohw-footer-col]",
13370
- "[data-ohw-social-label]",
13371
- "a",
13372
- "button",
13373
- '[role="button"]',
13374
- '[data-ohw-role="navbar-button"]',
13375
- '[data-ohw-role="button"]',
13376
- "[data-ohw-carousel]",
13377
- "[data-ohw-carousel-value]",
13378
- "[data-ohw-carousel-slide]",
13379
- "[data-ohw-carousel-overlay]",
13380
- "[data-ohw-media-chrome]",
13381
- "[data-ohw-media-overlay]",
13382
- "[data-ohw-media-skeleton]"
13383
- ].join(", ");
13384
- function visibleClip(ps) {
13385
- if (!ps) return null;
13386
- const top = Math.max(0, ps.headerH - ps.iframeOffsetTop);
13387
- const bottom = Math.min(window.innerHeight, ps.headerH + ps.canvasH - ps.iframeOffsetTop);
13388
- return { top, bottom: Math.max(top, bottom) };
13389
- }
13390
- function useSectionDrag({
13391
- isEditMode,
13392
- editContentRef,
13393
- postToParentRef,
13394
- parentScrollRef,
13395
- navDragRef,
13396
- footerDragRef,
13397
- suppressNextClickRef,
13398
- suppressClickUntilRef
13399
- }) {
13400
- const sectionDragRef = (0, import_react15.useRef)(null);
13401
- const [sectionDropSlots, setSectionDropSlots] = (0, import_react15.useState)([]);
13402
- const [activeSectionDropIndex, setActiveSectionDropIndex] = (0, import_react15.useState)(null);
13403
- const [isSectionDragging, setIsSectionDragging] = (0, import_react15.useState)(false);
13404
- const sectionPointerDragRef = (0, import_react15.useRef)(null);
13405
- const autoScrollRafRef = (0, import_react15.useRef)(null);
13406
- const autoScrollDeltaRef = (0, import_react15.useRef)(0);
13407
- const stopAutoScroll = (0, import_react15.useCallback)(() => {
13408
- if (autoScrollRafRef.current != null) {
13409
- cancelAnimationFrame(autoScrollRafRef.current);
13410
- autoScrollRafRef.current = null;
13411
- }
13412
- autoScrollDeltaRef.current = 0;
13413
- }, []);
13414
- const tickAutoScroll = (0, import_react15.useCallback)(() => {
13415
- if (!sectionDragRef.current) {
13416
- stopAutoScroll();
13417
- return;
13418
- }
13419
- if (autoScrollDeltaRef.current !== 0) {
13420
- postToParentRef.current({ type: "ow:request-scroll", deltaY: autoScrollDeltaRef.current });
13421
- }
13422
- autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
13423
- }, [postToParentRef, stopAutoScroll]);
13424
- const updateAutoScroll = (0, import_react15.useCallback)(
13425
- (clientY) => {
13426
- const clip = visibleClip(parentScrollRef.current);
13427
- let delta = 0;
13428
- if (clip) {
13429
- const distTop = clientY - clip.top;
13430
- const distBottom = clip.bottom - clientY;
13431
- if (distTop >= 0 && distTop < EDGE_ZONE) {
13432
- delta = -MAX_AUTO_SCROLL_SPEED * (1 - distTop / EDGE_ZONE);
13433
- } else if (distBottom >= 0 && distBottom < EDGE_ZONE) {
13434
- delta = MAX_AUTO_SCROLL_SPEED * (1 - distBottom / EDGE_ZONE);
13435
- }
13436
- }
13437
- autoScrollDeltaRef.current = delta;
13438
- if (delta !== 0 && autoScrollRafRef.current == null) {
13439
- autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
13440
- } else if (delta === 0) {
13441
- stopAutoScroll();
13442
- }
13443
- },
13444
- [parentScrollRef, stopAutoScroll, tickAutoScroll]
13445
- );
13446
- const clearSectionDragVisuals = (0, import_react15.useCallback)(() => {
13447
- sectionDragRef.current?.draggedEl.removeAttribute("data-ohw-section-dragging");
13448
- sectionDragRef.current = null;
13449
- setSectionDropSlots([]);
13450
- setActiveSectionDropIndex(null);
13451
- setIsSectionDragging(false);
13452
- stopAutoScroll();
13453
- document.documentElement.removeAttribute("data-ohw-section-dragging-root");
13454
- unlockItemDragInteraction();
13455
- }, [stopAutoScroll]);
13456
- const refreshSectionDragVisuals = (0, import_react15.useCallback)(
13457
- (session, clientX, clientY) => {
13458
- session.lastClientX = clientX;
13459
- session.lastClientY = clientY;
13460
- const slots = buildSectionDropSlots(session.instanceId);
13461
- const activeSlot = hitTestSectionDropSlot(clientY, slots);
13462
- session.activeSlot = activeSlot;
13463
- setSectionDropSlots(slots);
13464
- const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
13465
- setActiveSectionDropIndex(activeIdx >= 0 ? activeIdx : null);
13466
- updateAutoScroll(clientY);
13467
- },
13468
- [updateAutoScroll]
13469
- );
13470
- const beginSectionDrag = (0, import_react15.useCallback)(
13471
- (session) => {
13472
- sectionDragRef.current = session;
13473
- setIsSectionDragging(true);
13474
- lockItemDuringDrag();
13475
- document.documentElement.setAttribute("data-ohw-section-dragging-root", "");
13476
- session.draggedEl.setAttribute("data-ohw-section-dragging", "");
13477
- refreshSectionDragVisuals(session, session.lastClientX, session.lastClientY);
13478
- },
13479
- [refreshSectionDragVisuals]
13480
- );
13481
- const commitSectionDrag = (0, import_react15.useCallback)(() => {
13482
- const session = sectionDragRef.current;
13483
- if (!session) {
13484
- clearSectionDragVisuals();
13485
- return;
13486
- }
13487
- const slot = session.activeSlot ?? hitTestSectionDropSlot(session.lastClientY, buildSectionDropSlots(session.instanceId));
13488
- const entries = slot ? planSectionMove(session.instanceId, slot.insertIndex, window.location.pathname) : null;
13489
- if (!entries) {
13490
- clearSectionDragVisuals();
13491
- return;
13492
- }
13493
- const orderJson = JSON.stringify(entries);
13494
- editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
13495
- postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
13496
- applyPersistedOrder(entries);
13497
- clearSectionDragVisuals();
13498
- requestAnimationFrame(() => {
13499
- if (editContentRef.current[SECTION_ORDER_KEY] === orderJson) {
13500
- applyPersistedOrder(entries);
13501
- }
13502
- requestAnimationFrame(() => {
13503
- window.dispatchEvent(new Event("resize"));
13504
- });
13505
- });
13506
- }, [clearSectionDragVisuals, editContentRef, postToParentRef]);
13507
- const startSectionPressDrag = (0, import_react15.useCallback)(
13508
- (el, clientX, clientY, pointerId) => {
13509
- if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return false;
13510
- const instanceId = instanceIdOf(el);
13511
- if (!instanceId) return false;
13512
- sectionPointerDragRef.current = {
13513
- el,
13514
- instanceId,
13515
- startX: clientX,
13516
- startY: clientY,
13517
- pointerId,
13518
- started: false
13519
- };
13520
- return true;
13521
- },
13522
- [footerDragRef, navDragRef]
13523
- );
13524
- (0, import_react15.useEffect)(() => {
13525
- if (!isEditMode) return;
13526
- const onPointerDown = (e) => {
13527
- if (e.button !== 0) return;
13528
- if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return;
13529
- if (sectionPointerDragRef.current) return;
13530
- const target = e.target;
13531
- if (!(target instanceof HTMLElement)) return;
13532
- if (target.closest(SECTION_DRAG_EXCLUDED_SELECTOR)) return;
13533
- const sectionEl = target.closest("[data-ohw-section]");
13534
- if (!sectionEl || isChromeSection(sectionEl) || sectionEl.dataset.ohwSection === "footer") return;
13535
- if (!topLevelSections().includes(sectionEl)) return;
13536
- startSectionPressDrag(sectionEl, e.clientX, e.clientY, e.pointerId);
13537
- };
13538
- const onPointerMove = (e) => {
13539
- const pending = sectionPointerDragRef.current;
13540
- if (!pending) return;
13541
- if (pending.started) {
13542
- e.preventDefault();
13543
- clearTextSelection();
13544
- const session = sectionDragRef.current;
13545
- if (!session) return;
13546
- refreshSectionDragVisuals(session, e.clientX, e.clientY);
13547
- return;
13548
- }
13549
- const dx = e.clientX - pending.startX;
13550
- const dy = e.clientY - pending.startY;
13551
- if (dx * dx + dy * dy < PRESS_THRESHOLD * PRESS_THRESHOLD) return;
13552
- e.preventDefault();
13553
- pending.started = true;
13554
- armItemPressDrag();
13555
- clearTextSelection();
13556
- try {
13557
- document.body.setPointerCapture(pending.pointerId);
13558
- } catch {
13559
- }
13560
- beginSectionDrag({
13561
- instanceId: pending.instanceId,
13562
- draggedEl: pending.el,
13563
- lastClientX: e.clientX,
13564
- lastClientY: e.clientY,
13565
- activeSlot: null
13566
- });
13567
- };
13568
- const endPointerDrag = (e) => {
13569
- const pending = sectionPointerDragRef.current;
13570
- sectionPointerDragRef.current = null;
13571
- try {
13572
- if (document.body.hasPointerCapture(e.pointerId)) {
13573
- document.body.releasePointerCapture(e.pointerId);
13574
- }
13575
- } catch {
13576
- }
13577
- if (!pending) return;
13578
- if (!pending.started) {
13579
- unlockItemDragInteraction();
13580
- return;
13581
- }
13582
- suppressNextClickRef.current = true;
13583
- suppressClickUntilRef.current = Date.now() + 500;
13584
- commitSectionDrag();
13585
- };
13586
- const onKeyDown = (e) => {
13587
- if (e.key !== "Escape") return;
13588
- if (!sectionDragRef.current && !sectionPointerDragRef.current) return;
13589
- sectionPointerDragRef.current = null;
13590
- clearSectionDragVisuals();
13591
- };
13592
- document.addEventListener("pointerdown", onPointerDown, true);
13593
- document.addEventListener("pointermove", onPointerMove, true);
13594
- document.addEventListener("pointerup", endPointerDrag, true);
13595
- document.addEventListener("pointercancel", endPointerDrag, true);
13596
- document.addEventListener("keydown", onKeyDown, true);
13597
- return () => {
13598
- document.removeEventListener("pointerdown", onPointerDown, true);
13599
- document.removeEventListener("pointermove", onPointerMove, true);
13600
- document.removeEventListener("pointerup", endPointerDrag, true);
13601
- document.removeEventListener("pointercancel", endPointerDrag, true);
13602
- document.removeEventListener("keydown", onKeyDown, true);
13603
- unlockItemDragInteraction();
13604
- stopAutoScroll();
13605
- };
13606
- }, [
13607
- beginSectionDrag,
13608
- clearSectionDragVisuals,
13609
- commitSectionDrag,
13610
- footerDragRef,
13611
- isEditMode,
13612
- navDragRef,
13613
- refreshSectionDragVisuals,
13614
- startSectionPressDrag,
13615
- stopAutoScroll,
13616
- suppressClickUntilRef,
13617
- suppressNextClickRef
13618
- ]);
13619
- return {
13620
- sectionDragRef,
13621
- sectionDropSlots,
13622
- activeSectionDropIndex,
13623
- isSectionDragging
13624
- };
13625
- }
13626
-
13627
- // src/ui/footer-container-chrome.tsx
13628
- var import_lucide_react15 = require("lucide-react");
13629
- var import_jsx_runtime29 = require("react/jsx-runtime");
13630
- function FooterContainerChrome({
13631
- rect,
13632
- onAdd,
13633
- addDisabled = false
13634
- }) {
13635
- const chromeGap = 6;
13636
- const buttonMargin = 7;
13637
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13638
- "div",
13639
- {
13640
- "data-ohw-footer-container-chrome": "",
13641
- "data-ohw-bridge": "",
13642
- className: "pointer-events-none fixed z-[2147483647]",
13643
- style: {
13644
- top: rect.top - chromeGap,
13645
- left: rect.left - chromeGap,
13646
- width: rect.width + chromeGap * 2,
13647
- height: rect.height + chromeGap * 2
13648
- },
13649
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(Tooltip, { children: [
13650
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13651
- "button",
13652
- {
13653
- type: "button",
13654
- "data-ohw-footer-add-button": "",
13655
- disabled: addDisabled,
13656
- className: "pointer-events-auto absolute left-1/2 flex size-7 -translate-x-1/2 -translate-y-full items-center justify-center rounded-[10px] border border-border bg-background p-0.5 shadow-sm transition-colors hover:bg-muted/80 disabled:pointer-events-none disabled:opacity-40",
13657
- style: { top: chromeGap - buttonMargin },
13658
- "aria-label": "Add item",
13659
- onMouseDown: (e) => {
13660
- e.preventDefault();
13661
- e.stopPropagation();
13662
- },
13663
- onClick: (e) => {
13664
- e.preventDefault();
13665
- e.stopPropagation();
13666
- if (addDisabled) return;
13667
- onAdd();
13668
- },
13669
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
13670
- }
13671
- ) }),
13672
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
13673
- ] })
13674
- }
13675
- ) });
13676
- }
13677
-
13678
- // src/lib/carousel.ts
13679
- var import_react16 = require("react");
13680
- var CAROUSEL_ATTR = "data-ohw-carousel";
13681
- var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
13682
- var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
13683
- var CAROUSEL_EVENT = "ohw:carousel-change";
13684
- function listCarouselKeys() {
13685
- const keys = /* @__PURE__ */ new Set();
13686
- document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
13687
- const key = el.getAttribute("data-ohw-key");
13688
- if (key) keys.add(key);
13689
- });
13690
- return [...keys];
13691
- }
13692
- function containersForKey(key) {
13693
- return Array.from(
13694
- document.querySelectorAll(`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`)
13695
- );
13696
- }
13697
- function isCarouselKey(key) {
13698
- return containersForKey(key).length > 0;
13699
- }
13700
- function parseSlides(raw) {
13701
- if (!raw) return [];
13702
- try {
13703
- const parsed = JSON.parse(raw);
13704
- if (!Array.isArray(parsed)) return [];
13705
- return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
13706
- } catch {
13707
- return [];
13708
- }
13709
- }
13710
- function readCarouselValue(key) {
13711
- const container = containersForKey(key)[0];
13712
- if (!container) return [];
13713
- const fromAttr = parseSlides(container.getAttribute(CAROUSEL_VALUE_ATTR));
13714
- if (fromAttr.length > 0) return fromAttr;
13715
- return Array.from(container.querySelectorAll(`[${CAROUSEL_SLIDE_ATTR}]`)).filter((slide) => slide.closest(`[${CAROUSEL_ATTR}]`) === container).sort((a, b) => slideIndex(a) - slideIndex(b)).map((slide) => {
13716
- const img = slide instanceof HTMLImageElement ? slide : slide.querySelector("img");
13717
- return { src: img?.src ?? "", alt: img?.alt ?? "" };
13718
- });
13719
- }
13720
- function slideIndex(el) {
13721
- const raw = el.getAttribute(CAROUSEL_SLIDE_ATTR);
13722
- const n = raw ? parseInt(raw, 10) : NaN;
13723
- return Number.isFinite(n) ? n : 0;
13724
- }
13725
- function applyCarouselValue(key, slides) {
13726
- const value = JSON.stringify(slides);
13727
- for (const container of containersForKey(key)) {
13728
- if (container.getAttribute(CAROUSEL_VALUE_ATTR) === value) continue;
13729
- container.setAttribute(CAROUSEL_VALUE_ATTR, value);
13730
- container.dispatchEvent(
13731
- new CustomEvent(CAROUSEL_EVENT, { detail: { images: slides } })
13732
- );
13733
- }
13734
- }
13735
- function applyCarouselNode(key, val) {
13736
- if (!isCarouselKey(key)) return false;
13737
- applyCarouselValue(key, parseSlides(val));
13738
- return true;
12853
+ function applyCarouselNode(key, val) {
12854
+ if (!isCarouselKey(key)) return false;
12855
+ applyCarouselValue(key, parseSlides(val));
12856
+ return true;
13739
12857
  }
13740
12858
  function useOhwCarousel(key, initial) {
13741
- const [images, setImages] = (0, import_react16.useState)(initial);
13742
- (0, import_react16.useEffect)(() => {
12859
+ const [images, setImages] = (0, import_react15.useState)(initial);
12860
+ (0, import_react15.useEffect)(() => {
13743
12861
  const el = document.querySelector(
13744
12862
  `[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
13745
12863
  );
@@ -13817,7 +12935,7 @@ function collectEditableNodes(extraContent, root = document) {
13817
12935
  nodes.push({ key, type: "link", text: href });
13818
12936
  }
13819
12937
  if (extraContent) {
13820
- for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY, SECTION_ORDER_KEY]) {
12938
+ for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
13821
12939
  const text = extraContent[key];
13822
12940
  if (typeof text === "string" && text.length > 0) {
13823
12941
  nodes.push({ key, type: "meta", text });
@@ -13854,18 +12972,6 @@ function collectEditableNodes(extraContent, root = document) {
13854
12972
  }
13855
12973
  if (extraContent && !isScoped) {
13856
12974
  applyNavFooterDeleteOverrides(byKey, extraContent);
13857
- for (const key of LOGO_IMAGE_KEYS) {
13858
- if (!(key in extraContent)) continue;
13859
- byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
13860
- }
13861
- for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
13862
- if (!(key in extraContent)) continue;
13863
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
13864
- }
13865
- for (const key of LOGO_SIZE_KEYS) {
13866
- if (!(key in extraContent)) continue;
13867
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
13868
- }
13869
12975
  }
13870
12976
  return Array.from(byKey.values());
13871
12977
  }
@@ -14270,7 +13376,6 @@ function fadeInImageElement(img, onReady) {
14270
13376
  function applyEditableImageSrc(img, url) {
14271
13377
  img.removeAttribute("srcset");
14272
13378
  img.removeAttribute("sizes");
14273
- if (img.loading === "lazy") img.loading = "eager";
14274
13379
  img.src = url;
14275
13380
  }
14276
13381
  function fadeInBgImage(el, url, onReady) {
@@ -14335,10 +13440,21 @@ function parseSchedulingInsertAfter(insertAfter) {
14335
13440
  insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
14336
13441
  };
14337
13442
  }
14338
- function resolveEntryAnchor(entry) {
14339
- if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
14340
- const parsed = parseSchedulingInsertAfter(entry.insertAfter);
14341
- return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
13443
+ function resolveSchedulingInsert(insertAfter, explicitInsertBefore) {
13444
+ const parsed = parseSchedulingInsertAfter(insertAfter);
13445
+ const insertBefore = explicitInsertBefore ?? parsed.insertBefore;
13446
+ const effectiveInsertAfter = insertBefore && parsed.insertBefore === null ? `${insertAfter}${INSERT_BEFORE_MARKER}${insertBefore}` : insertAfter;
13447
+ return { effectiveInsertAfter, insertBefore };
13448
+ }
13449
+ function getSchedulingMountPoint(insertAfter) {
13450
+ const { anchor } = parseSchedulingInsertAfter(insertAfter);
13451
+ let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
13452
+ if (!anchorEl && anchor === "scheduling") {
13453
+ const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
13454
+ anchorEl = widgets.at(-1) ?? null;
13455
+ }
13456
+ if (!anchorEl) return null;
13457
+ return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
14342
13458
  }
14343
13459
  function schedulingMountDepth(insertAfter) {
14344
13460
  if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
@@ -14355,7 +13471,8 @@ function getPageSchedulingEntries(raw) {
14355
13471
  }
14356
13472
  }
14357
13473
  function isSchedulingWidgetMissing(entry) {
14358
- return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
13474
+ const { effectiveInsertAfter } = resolveSchedulingInsert(entry.insertAfter);
13475
+ return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
14359
13476
  }
14360
13477
  function hasMissingSchedulingWidgets(entries) {
14361
13478
  return entries.some(isSchedulingWidgetMissing);
@@ -14385,17 +13502,16 @@ function initSectionsFromContent(content, removeExisting = false) {
14385
13502
  } catch {
14386
13503
  }
14387
13504
  }
14388
- function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
14389
- const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
14390
- const sectionId = schedulingSectionId(widgetId);
13505
+ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId, explicitInsertBefore) {
13506
+ const { effectiveInsertAfter, insertBefore } = resolveSchedulingInsert(insertAfter, explicitInsertBefore);
13507
+ const sectionId = schedulingSectionId(effectiveInsertAfter);
14391
13508
  if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
14392
- const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
14393
- if (!anchorEl) return false;
14394
- const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
13509
+ const mountPoint = getSchedulingMountPoint(effectiveInsertAfter);
13510
+ if (!mountPoint) return false;
14395
13511
  const container = document.createElement("div");
14396
13512
  container.dataset.ohwSectionContainer = "scheduling";
14397
- if (beforeId) {
14398
- const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
13513
+ if (insertBefore) {
13514
+ const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
14399
13515
  const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
14400
13516
  if (!beforePoint) return false;
14401
13517
  beforePoint.insertAdjacentElement("beforebegin", container);
@@ -14406,25 +13522,19 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
14406
13522
  }
14407
13523
  tail.insertAdjacentElement("afterend", container);
14408
13524
  }
14409
- try {
14410
- const root = (0, import_client2.createRoot)(container);
14411
- (0, import_react_dom3.flushSync)(() => {
14412
- root.render(
14413
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14414
- SchedulingWidget,
14415
- {
14416
- notifyOnConnect,
14417
- initialScheduleId: scheduleId,
14418
- insertAfter: widgetId
14419
- }
14420
- )
14421
- );
14422
- });
14423
- } catch (err) {
14424
- console.error("[ow:scheduling] render threw", err);
14425
- container.remove();
14426
- return false;
14427
- }
13525
+ const root = (0, import_client2.createRoot)(container);
13526
+ (0, import_react_dom3.flushSync)(() => {
13527
+ root.render(
13528
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13529
+ SchedulingWidget,
13530
+ {
13531
+ notifyOnConnect,
13532
+ initialScheduleId: scheduleId,
13533
+ insertAfter: effectiveInsertAfter
13534
+ }
13535
+ )
13536
+ );
13537
+ });
14428
13538
  const tracker = getSectionsTracker();
14429
13539
  let sections = [];
14430
13540
  try {
@@ -14432,12 +13542,10 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
14432
13542
  } catch {
14433
13543
  }
14434
13544
  const inEditor = typeof window !== "undefined" && window.self !== window.top;
14435
- if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
13545
+ if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === effectiveInsertAfter)) {
14436
13546
  sections.push({
14437
13547
  type: "scheduling",
14438
- insertAfter: widgetId,
14439
- anchorId,
14440
- beforeId: beforeId ?? null,
13548
+ insertAfter: effectiveInsertAfter,
14441
13549
  pagePath: window.location.pathname,
14442
13550
  ...scheduleId ? { scheduleId } : {}
14443
13551
  });
@@ -14451,8 +13559,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
14451
13559
  for (let i = pending.length - 1; i >= 0; i--) {
14452
13560
  const entry = pending[i];
14453
13561
  const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
14454
- const { anchorId, beforeId } = resolveEntryAnchor(entry);
14455
- if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
13562
+ if (mountSchedulingWidget(entry.insertAfter, shouldNotify, entry.scheduleId)) {
14456
13563
  pending.splice(i, 1);
14457
13564
  }
14458
13565
  }
@@ -14600,13 +13707,6 @@ function isInsideLinkEditor(target) {
14600
13707
  target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest("[data-ohw-footer-container-chrome]") || target.closest("[data-ohw-footer-add-button]") || target.closest("[data-ohw-more-menu]") || target.closest('[data-slot="dropdown-menu-content"]') || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
14601
13708
  );
14602
13709
  }
14603
- function isInsideFloatingPanel(target) {
14604
- return Boolean(target.closest("[data-ohw-floating-panel]"));
14605
- }
14606
- function isPointOverFloatingPanel(clientX, clientY) {
14607
- const el = document.elementFromPoint(clientX, clientY);
14608
- return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
14609
- }
14610
13710
  function getHrefKeyFromElement(el) {
14611
13711
  if (!el) return null;
14612
13712
  const anchor = el.closest("[data-ohw-href-key]");
@@ -14852,7 +13952,7 @@ function getNavigationSelectionParent(el) {
14852
13952
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
14853
13953
  return getFooterLinksContainer();
14854
13954
  }
14855
- if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup2(el)) {
13955
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
14856
13956
  return getNavigationRoot(el);
14857
13957
  }
14858
13958
  return null;
@@ -15321,9 +14421,9 @@ function FloatingToolbar({
15321
14421
  showEditLink,
15322
14422
  onEditLink
15323
14423
  }) {
15324
- const localRef = import_react17.default.useRef(null);
15325
- const [measuredW, setMeasuredW] = import_react17.default.useState(330);
15326
- const setRefs = import_react17.default.useCallback(
14424
+ const localRef = import_react16.default.useRef(null);
14425
+ const [measuredW, setMeasuredW] = import_react16.default.useState(330);
14426
+ const setRefs = import_react16.default.useCallback(
15327
14427
  (node) => {
15328
14428
  localRef.current = node;
15329
14429
  if (typeof elRef === "function") elRef(node);
@@ -15335,7 +14435,7 @@ function FloatingToolbar({
15335
14435
  },
15336
14436
  [elRef]
15337
14437
  );
15338
- import_react17.default.useLayoutEffect(() => {
14438
+ import_react16.default.useLayoutEffect(() => {
15339
14439
  const node = localRef.current;
15340
14440
  if (!node) return;
15341
14441
  const update = () => {
@@ -15361,7 +14461,7 @@ function FloatingToolbar({
15361
14461
  pointerEvents: "auto"
15362
14462
  },
15363
14463
  children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(CustomToolbar, { children: [
15364
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react17.default.Fragment, { children: [
14464
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react16.default.Fragment, { children: [
15365
14465
  gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CustomToolbarDivider, {}),
15366
14466
  btns.map((btn) => {
15367
14467
  const isActive = activeCommands.has(btn.cmd);
@@ -15445,45 +14545,6 @@ function StateToggle({
15445
14545
  );
15446
14546
  }
15447
14547
  var contentCache = /* @__PURE__ */ new Map();
15448
- var fetchedContentPaths = /* @__PURE__ */ new Set();
15449
- var OHW_LOADER_STYLE = {
15450
- position: "fixed",
15451
- inset: 0,
15452
- background: "#fff",
15453
- zIndex: 2147483646,
15454
- display: "flex",
15455
- alignItems: "center",
15456
- justifyContent: "center"
15457
- };
15458
- function OhwLoaderSpinner() {
15459
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", "aria-hidden": true, children: [
15460
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("circle", { cx: "14", cy: "14", r: "11", stroke: "#E7E5E4", strokeWidth: "3" }),
15461
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15462
- "circle",
15463
- {
15464
- cx: "14",
15465
- cy: "14",
15466
- r: "11",
15467
- stroke: "#1C1917",
15468
- strokeWidth: "3",
15469
- strokeDasharray: "17 52",
15470
- strokeLinecap: "round",
15471
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15472
- "animateTransform",
15473
- {
15474
- attributeName: "transform",
15475
- type: "rotate",
15476
- from: "0 14 14",
15477
- to: "360 14 14",
15478
- dur: "0.7s",
15479
- repeatCount: "indefinite"
15480
- }
15481
- )
15482
- }
15483
- )
15484
- ] });
15485
- }
15486
- 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){}})();`;
15487
14548
  function resolveSubdomain(subdomainFromQuery) {
15488
14549
  if (subdomainFromQuery) return subdomainFromQuery;
15489
14550
  if (typeof window !== "undefined") {
@@ -15506,8 +14567,8 @@ function OhhwellsBridge() {
15506
14567
  const router = (0, import_navigation3.useRouter)();
15507
14568
  const searchParams = (0, import_navigation3.useSearchParams)();
15508
14569
  const isEditMode = isEditSessionActive();
15509
- const [bridgeRoot, setBridgeRoot] = (0, import_react17.useState)(null);
15510
- (0, import_react17.useEffect)(() => {
14570
+ const [bridgeRoot, setBridgeRoot] = (0, import_react16.useState)(null);
14571
+ (0, import_react16.useEffect)(() => {
15511
14572
  const figtreeFontId = "ohw-figtree-font";
15512
14573
  if (!document.getElementById(figtreeFontId)) {
15513
14574
  const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
@@ -15536,146 +14597,82 @@ function OhhwellsBridge() {
15536
14597
  const subdomain = resolveSubdomain(subdomainFromQuery);
15537
14598
  useLinkHrefGuardian(pathname, subdomain, isEditMode);
15538
14599
  useSavedLinkNavigation(isEditMode);
15539
- const postToParent2 = (0, import_react17.useCallback)((data) => {
14600
+ const postToParent2 = (0, import_react16.useCallback)((data) => {
15540
14601
  if (typeof window !== "undefined" && window.parent !== window) {
15541
14602
  window.parent.postMessage(data, "*");
15542
14603
  }
15543
14604
  }, []);
15544
- const [fetchState, setFetchState] = (0, import_react17.useState)("idle");
15545
- const autoSaveTimers = (0, import_react17.useRef)(/* @__PURE__ */ new Map());
15546
- const activeElRef = (0, import_react17.useRef)(null);
15547
- const pointerHeldRef = (0, import_react17.useRef)(false);
15548
- const selectedElRef = (0, import_react17.useRef)(null);
15549
- const selectedHrefKeyRef = (0, import_react17.useRef)(null);
15550
- const selectedFooterColAttrRef = (0, import_react17.useRef)(null);
15551
- const originalContentRef = (0, import_react17.useRef)(null);
15552
- const activeStateElRef = (0, import_react17.useRef)(null);
15553
- const parentScrollRef = (0, import_react17.useRef)(null);
15554
- const visibleViewportRef = (0, import_react17.useRef)(null);
15555
- const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react17.useState)(null);
15556
- const attachVisibleViewport = (0, import_react17.useCallback)((node) => {
14605
+ const [fetchState, setFetchState] = (0, import_react16.useState)("idle");
14606
+ const autoSaveTimers = (0, import_react16.useRef)(/* @__PURE__ */ new Map());
14607
+ const activeElRef = (0, import_react16.useRef)(null);
14608
+ const pointerHeldRef = (0, import_react16.useRef)(false);
14609
+ const selectedElRef = (0, import_react16.useRef)(null);
14610
+ const selectedHrefKeyRef = (0, import_react16.useRef)(null);
14611
+ const selectedFooterColAttrRef = (0, import_react16.useRef)(null);
14612
+ const originalContentRef = (0, import_react16.useRef)(null);
14613
+ const activeStateElRef = (0, import_react16.useRef)(null);
14614
+ const parentScrollRef = (0, import_react16.useRef)(null);
14615
+ const visibleViewportRef = (0, import_react16.useRef)(null);
14616
+ const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react16.useState)(null);
14617
+ const attachVisibleViewport = (0, import_react16.useCallback)((node) => {
15557
14618
  visibleViewportRef.current = node;
15558
14619
  setDialogPortalContainer(node);
15559
14620
  if (node) applyVisibleViewport(node, parentScrollRef.current);
15560
14621
  }, []);
15561
- const toolbarElRef = (0, import_react17.useRef)(null);
15562
- const glowElRef = (0, import_react17.useRef)(null);
15563
- const hoveredImageRef = (0, import_react17.useRef)(null);
15564
- const hoveredImageHasTextOverlapRef = (0, import_react17.useRef)(false);
15565
- const dragOverElRef = (0, import_react17.useRef)(null);
15566
- const [mediaHover, setMediaHover] = (0, import_react17.useState)(null);
15567
- const [selectedMedia, setSelectedMedia] = (0, import_react17.useState)(null);
15568
- const selectedMediaElRef = (0, import_react17.useRef)(null);
15569
- const clearMediaSelection = (0, import_react17.useCallback)(() => {
15570
- const prev = selectedMediaElRef.current;
15571
- selectedMediaElRef.current = null;
15572
- setSelectedMedia(null);
15573
- const sectionEl = prev?.closest("[data-ohw-section]") ?? null;
15574
- if (sectionEl) {
15575
- postToParentRef.current({
15576
- type: "ow:section-selected",
15577
- sectionId: sectionEl.dataset.ohwSection ?? null,
15578
- sectionLabel: sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? ""),
15579
- key: null
15580
- });
15581
- }
15582
- }, []);
15583
- const clearMediaSelectionRef = (0, import_react17.useRef)(clearMediaSelection);
15584
- clearMediaSelectionRef.current = clearMediaSelection;
15585
- const selectMediaElement = (0, import_react17.useCallback)((el) => {
15586
- const r2 = el.getBoundingClientRect();
15587
- const video = el.dataset.ohwEditable === "video" ? el.querySelector("video") : null;
15588
- selectedMediaElRef.current = el;
15589
- setSelectedMedia({
15590
- key: el.dataset.ohwKey ?? "",
15591
- rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
15592
- elementType: el.dataset.ohwEditable ?? "image",
15593
- hasTextOverlap: false,
15594
- isDragOver: false,
15595
- ...video ? { videoAutoplay: video.autoplay, videoMuted: video.muted } : {}
15596
- });
15597
- const sectionEl = el.closest("[data-ohw-section]");
15598
- aiSectionApiRef.current?.selectFromElement(el, { report: false });
15599
- postToParentRef.current({
15600
- type: "ow:section-selected",
15601
- sectionId: sectionEl?.dataset.ohwSection ?? null,
15602
- sectionLabel: sectionEl ? sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? "") : null,
15603
- key: el.dataset.ohwKey ?? null,
15604
- // Display name for the pill — the raw key prettifies into fragments ("Img"); the
15605
- // bridge knows what the node IS, so it names it.
15606
- keyLabel: el.dataset.ohwEditable === "video" ? "Video" : "Image"
15607
- });
15608
- }, []);
15609
- const selectMediaElementRef = (0, import_react17.useRef)(selectMediaElement);
15610
- selectMediaElementRef.current = selectMediaElement;
15611
- (0, import_react17.useEffect)(() => {
15612
- if (!selectedMedia) return;
15613
- const update = () => {
15614
- const el = selectedMediaElRef.current;
15615
- if (!el || !el.isConnected) {
15616
- clearMediaSelection();
15617
- return;
15618
- }
15619
- const r2 = el.getBoundingClientRect();
15620
- setSelectedMedia(
15621
- (prev) => prev ? { ...prev, rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } } : prev
15622
- );
15623
- };
15624
- window.addEventListener("scroll", update, true);
15625
- window.addEventListener("resize", update);
15626
- return () => {
15627
- window.removeEventListener("scroll", update, true);
15628
- window.removeEventListener("resize", update);
15629
- };
15630
- }, [selectedMedia !== null]);
15631
- const [carouselHover, setCarouselHover] = (0, import_react17.useState)(null);
15632
- const [uploadingRects, setUploadingRects] = (0, import_react17.useState)({});
15633
- const hoveredGapRef = (0, import_react17.useRef)(null);
15634
- const imageUnhoverTimerRef = (0, import_react17.useRef)(null);
15635
- const imageShowTimerRef = (0, import_react17.useRef)(null);
15636
- const editStylesRef = (0, import_react17.useRef)(null);
15637
- const activateRef = (0, import_react17.useRef)(() => {
14622
+ const toolbarElRef = (0, import_react16.useRef)(null);
14623
+ const glowElRef = (0, import_react16.useRef)(null);
14624
+ const hoveredImageRef = (0, import_react16.useRef)(null);
14625
+ const hoveredImageHasTextOverlapRef = (0, import_react16.useRef)(false);
14626
+ const dragOverElRef = (0, import_react16.useRef)(null);
14627
+ const [mediaHover, setMediaHover] = (0, import_react16.useState)(null);
14628
+ const [carouselHover, setCarouselHover] = (0, import_react16.useState)(null);
14629
+ const [uploadingRects, setUploadingRects] = (0, import_react16.useState)({});
14630
+ const hoveredGapRef = (0, import_react16.useRef)(null);
14631
+ const imageUnhoverTimerRef = (0, import_react16.useRef)(null);
14632
+ const imageShowTimerRef = (0, import_react16.useRef)(null);
14633
+ const editStylesRef = (0, import_react16.useRef)(null);
14634
+ const activateRef = (0, import_react16.useRef)(() => {
15638
14635
  });
15639
- const deactivateRef = (0, import_react17.useRef)(() => {
14636
+ const deactivateRef = (0, import_react16.useRef)(() => {
15640
14637
  });
15641
- const selectRef = (0, import_react17.useRef)(() => {
14638
+ const selectRef = (0, import_react16.useRef)(() => {
15642
14639
  });
15643
- const selectFrameRef = (0, import_react17.useRef)(() => {
14640
+ const selectFrameRef = (0, import_react16.useRef)(() => {
15644
14641
  });
15645
- const selectLogoRef = (0, import_react17.useRef)(() => {
14642
+ const selectLogoRef = (0, import_react16.useRef)(() => {
15646
14643
  });
15647
- const openLogoSizePanelRef = (0, import_react17.useRef)(() => {
14644
+ const openLogoSizePanelRef = (0, import_react16.useRef)(() => {
15648
14645
  });
15649
- const deselectRef = (0, import_react17.useRef)(() => {
14646
+ const deselectRef = (0, import_react16.useRef)(() => {
15650
14647
  });
15651
- const closeFloatingPanelOnlyRef = (0, import_react17.useRef)(() => {
14648
+ const closeFloatingPanelOnlyRef = (0, import_react16.useRef)(() => {
15652
14649
  });
15653
- const reselectNavigationItemRef = (0, import_react17.useRef)(() => {
14650
+ const reselectNavigationItemRef = (0, import_react16.useRef)(() => {
15654
14651
  });
15655
- const commitNavigationTextEditRef = (0, import_react17.useRef)(() => {
14652
+ const commitNavigationTextEditRef = (0, import_react16.useRef)(() => {
15656
14653
  });
15657
- const handleDeleteSelectedRef = (0, import_react17.useRef)(() => false);
15658
- const runPendingDeleteUndoRef = (0, import_react17.useRef)(() => false);
15659
- const isFooterFrameSelectionRef = (0, import_react17.useRef)(false);
15660
- const refreshActiveCommandsRef = (0, import_react17.useRef)(() => {
14654
+ const handleDeleteSelectedRef = (0, import_react16.useRef)(() => false);
14655
+ const runPendingDeleteUndoRef = (0, import_react16.useRef)(() => false);
14656
+ const isFooterFrameSelectionRef = (0, import_react16.useRef)(false);
14657
+ const refreshActiveCommandsRef = (0, import_react16.useRef)(() => {
15661
14658
  });
15662
- const postToParentRef = (0, import_react17.useRef)(postToParent2);
14659
+ const postToParentRef = (0, import_react16.useRef)(postToParent2);
15663
14660
  postToParentRef.current = postToParent2;
15664
- const aiSectionApiRef = (0, import_react17.useRef)(null);
15665
- const sectionsLoadedRef = (0, import_react17.useRef)(false);
15666
- const pendingScheduleConfigRequests = (0, import_react17.useRef)([]);
15667
- const [toolbarRect, setToolbarRect] = (0, import_react17.useState)(null);
15668
- const [formPickRect, setFormPickRect] = (0, import_react17.useState)(null);
15669
- const formPickElRef = (0, import_react17.useRef)(null);
15670
- const [formViewState, setFormViewStateUi] = (0, import_react17.useState)("default");
15671
- const [formPickCount, setFormPickCount] = (0, import_react17.useState)(null);
15672
- const [formHoverRect, setFormHoverRect] = (0, import_react17.useState)(null);
15673
- const formHoverElRef = (0, import_react17.useRef)(null);
15674
- const [fieldPickRect, setFieldPickRect] = (0, import_react17.useState)(null);
15675
- const fieldPickElRef = (0, import_react17.useRef)(null);
15676
- const [fieldPickState, setFieldPickState] = (0, import_react17.useState)(null);
15677
- const [fieldTypePickerOpen, setFieldTypePickerOpen] = (0, import_react17.useState)(false);
15678
- const clearFormPick = (0, import_react17.useCallback)(() => {
14661
+ const aiSectionApiRef = (0, import_react16.useRef)(null);
14662
+ const sectionsLoadedRef = (0, import_react16.useRef)(false);
14663
+ const pendingScheduleConfigRequests = (0, import_react16.useRef)([]);
14664
+ const [toolbarRect, setToolbarRect] = (0, import_react16.useState)(null);
14665
+ const [formPickRect, setFormPickRect] = (0, import_react16.useState)(null);
14666
+ const formPickElRef = (0, import_react16.useRef)(null);
14667
+ const [formViewState, setFormViewStateUi] = (0, import_react16.useState)("default");
14668
+ const [formPickCount, setFormPickCount] = (0, import_react16.useState)(null);
14669
+ const [formHoverRect, setFormHoverRect] = (0, import_react16.useState)(null);
14670
+ const formHoverElRef = (0, import_react16.useRef)(null);
14671
+ const [fieldPickRect, setFieldPickRect] = (0, import_react16.useState)(null);
14672
+ const fieldPickElRef = (0, import_react16.useRef)(null);
14673
+ const [fieldPickState, setFieldPickState] = (0, import_react16.useState)(null);
14674
+ const [fieldTypePickerOpen, setFieldTypePickerOpen] = (0, import_react16.useState)(false);
14675
+ const clearFormPick = (0, import_react16.useCallback)(() => {
15679
14676
  const form = formPickElRef.current;
15680
14677
  const editing = fieldPickElRef.current;
15681
14678
  if (commitPlaceholderEdit(editing) && editing) {
@@ -15695,7 +14692,7 @@ function OhhwellsBridge() {
15695
14692
  formPickElRef.current = null;
15696
14693
  setFormPickRect(null);
15697
14694
  }, []);
15698
- const clearFieldPick = (0, import_react17.useCallback)(() => {
14695
+ const clearFieldPick = (0, import_react16.useCallback)(() => {
15699
14696
  const wrapper = fieldPickElRef.current;
15700
14697
  if (commitPlaceholderEdit(wrapper) && wrapper) {
15701
14698
  const form = wrapper.closest('[data-ohw-editable="form"]');
@@ -15705,9 +14702,9 @@ function OhhwellsBridge() {
15705
14702
  setFieldPickRect(null);
15706
14703
  setFieldPickState(null);
15707
14704
  }, []);
15708
- const persistFieldsRef = (0, import_react17.useRef)(() => {
14705
+ const persistFieldsRef = (0, import_react16.useRef)(() => {
15709
14706
  });
15710
- const persistFields = (0, import_react17.useCallback)(
14707
+ const persistFields = (0, import_react16.useCallback)(
15711
14708
  (form) => {
15712
14709
  const key = formKeyOf(form);
15713
14710
  if (!key) return;
@@ -15718,7 +14715,7 @@ function OhhwellsBridge() {
15718
14715
  []
15719
14716
  );
15720
14717
  persistFieldsRef.current = persistFields;
15721
- const selectField = (0, import_react17.useCallback)((wrapper) => {
14718
+ const selectField = (0, import_react16.useCallback)((wrapper) => {
15722
14719
  if (fieldPickElRef.current && fieldPickElRef.current !== wrapper) {
15723
14720
  commitPlaceholderEdit(fieldPickElRef.current);
15724
14721
  }
@@ -15731,7 +14728,7 @@ function OhhwellsBridge() {
15731
14728
  setFieldPickState({ type: fieldTypeOf(wrapper), required: isFieldRequired(wrapper) });
15732
14729
  setFieldTypePickerOpen(false);
15733
14730
  }, []);
15734
- const withSelectedField = (0, import_react17.useCallback)(
14731
+ const withSelectedField = (0, import_react16.useCallback)(
15735
14732
  (run) => {
15736
14733
  const wrapper = fieldPickElRef.current;
15737
14734
  const form = formPickElRef.current;
@@ -15744,28 +14741,28 @@ function OhhwellsBridge() {
15744
14741
  },
15745
14742
  [persistFields]
15746
14743
  );
15747
- const handleFieldTypeChange = (0, import_react17.useCallback)(
14744
+ const handleFieldTypeChange = (0, import_react16.useCallback)(
15748
14745
  (type) => withSelectedField((_form, wrapper) => {
15749
14746
  applyFieldType(wrapper, type);
15750
14747
  selectField(wrapper);
15751
14748
  }),
15752
14749
  [selectField, withSelectedField]
15753
14750
  );
15754
- const handleFieldRequiredToggle = (0, import_react17.useCallback)(
14751
+ const handleFieldRequiredToggle = (0, import_react16.useCallback)(
15755
14752
  () => withSelectedField((_form, wrapper) => {
15756
14753
  setFieldRequired(wrapper, !isFieldRequired(wrapper));
15757
14754
  selectField(wrapper);
15758
14755
  }),
15759
14756
  [selectField, withSelectedField]
15760
14757
  );
15761
- const handleFieldDuplicate = (0, import_react17.useCallback)(
14758
+ const handleFieldDuplicate = (0, import_react16.useCallback)(
15762
14759
  () => withSelectedField((form, wrapper) => {
15763
14760
  const copy = duplicateField(form, wrapper);
15764
14761
  selectField(copy);
15765
14762
  }),
15766
14763
  [selectField, withSelectedField]
15767
14764
  );
15768
- const handleFieldDelete = (0, import_react17.useCallback)(
14765
+ const handleFieldDelete = (0, import_react16.useCallback)(
15769
14766
  () => withSelectedField((_form, wrapper) => {
15770
14767
  removeField(wrapper);
15771
14768
  clearFieldPick();
@@ -15773,7 +14770,7 @@ function OhhwellsBridge() {
15773
14770
  }),
15774
14771
  [clearFieldPick, withSelectedField]
15775
14772
  );
15776
- const handleAddField = (0, import_react17.useCallback)(
14773
+ const handleAddField = (0, import_react16.useCallback)(
15777
14774
  (type) => {
15778
14775
  const form = formPickElRef.current;
15779
14776
  if (!form) return;
@@ -15789,8 +14786,8 @@ function OhhwellsBridge() {
15789
14786
  },
15790
14787
  [persistFields, selectField]
15791
14788
  );
15792
- const fieldDragRef = (0, import_react17.useRef)(null);
15793
- const buildFieldDropSlots = (0, import_react17.useCallback)((form, draggedKey) => {
14789
+ const fieldDragRef = (0, import_react16.useRef)(null);
14790
+ const buildFieldDropSlots = (0, import_react16.useCallback)((form, draggedKey) => {
15794
14791
  const others = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== draggedKey);
15795
14792
  const slots = others.map((el) => {
15796
14793
  const rect = el.getBoundingClientRect();
@@ -15803,7 +14800,7 @@ function OhhwellsBridge() {
15803
14800
  }
15804
14801
  return slots;
15805
14802
  }, []);
15806
- const handleFieldDragStart = (0, import_react17.useCallback)(() => {
14803
+ const handleFieldDragStart = (0, import_react16.useCallback)(() => {
15807
14804
  const wrapper = fieldPickElRef.current;
15808
14805
  const form = formPickElRef.current;
15809
14806
  if (!wrapper || !form) return;
@@ -15812,18 +14809,18 @@ function OhhwellsBridge() {
15812
14809
  setFieldDragging(true);
15813
14810
  setFieldDropSlots(buildFieldDropSlots(form, key));
15814
14811
  }, [buildFieldDropSlots]);
15815
- const handleFieldDragEnd = (0, import_react17.useCallback)(() => {
14812
+ const handleFieldDragEnd = (0, import_react16.useCallback)(() => {
15816
14813
  fieldDragRef.current = null;
15817
14814
  setFieldDropIndex(null);
15818
14815
  setFieldDropSlots([]);
15819
14816
  setFieldDragging(false);
15820
14817
  }, []);
15821
- const [fieldDropIndex, setFieldDropIndex] = (0, import_react17.useState)(null);
15822
- const [fieldDropSlots, setFieldDropSlots] = (0, import_react17.useState)([]);
15823
- const [fieldDragging, setFieldDragging] = (0, import_react17.useState)(false);
15824
- const clearFormPickRef = (0, import_react17.useRef)(clearFormPick);
14818
+ const [fieldDropIndex, setFieldDropIndex] = (0, import_react16.useState)(null);
14819
+ const [fieldDropSlots, setFieldDropSlots] = (0, import_react16.useState)([]);
14820
+ const [fieldDragging, setFieldDragging] = (0, import_react16.useState)(false);
14821
+ const clearFormPickRef = (0, import_react16.useRef)(clearFormPick);
15825
14822
  clearFormPickRef.current = clearFormPick;
15826
- (0, import_react17.useEffect)(() => {
14823
+ (0, import_react16.useEffect)(() => {
15827
14824
  const el = fieldPickElRef.current;
15828
14825
  if (!el || fieldPickRect === null) return;
15829
14826
  const observer = new ResizeObserver(() => {
@@ -15832,7 +14829,7 @@ function OhhwellsBridge() {
15832
14829
  observer.observe(el);
15833
14830
  return () => observer.disconnect();
15834
14831
  }, [fieldPickRect !== null, fieldPickState]);
15835
- (0, import_react17.useEffect)(() => {
14832
+ (0, import_react16.useEffect)(() => {
15836
14833
  const el = formPickElRef.current;
15837
14834
  if (!el || formPickRect === null) return;
15838
14835
  const observer = new ResizeObserver(() => {
@@ -15841,25 +14838,25 @@ function OhhwellsBridge() {
15841
14838
  observer.observe(el);
15842
14839
  return () => observer.disconnect();
15843
14840
  }, [formPickRect !== null, formViewState]);
15844
- const [toolbarVariant, setToolbarVariant] = (0, import_react17.useState)("none");
15845
- const toolbarVariantRef = (0, import_react17.useRef)("none");
14841
+ const [toolbarVariant, setToolbarVariant] = (0, import_react16.useState)("none");
14842
+ const toolbarVariantRef = (0, import_react16.useRef)("none");
15846
14843
  toolbarVariantRef.current = toolbarVariant;
15847
- const [selectedIsCta, setSelectedIsCta] = (0, import_react17.useState)(false);
15848
- const [selectedIsSocial, setSelectedIsSocial] = (0, import_react17.useState)(false);
15849
- const [selectedIsSocialsRow, setSelectedIsSocialsRow] = (0, import_react17.useState)(false);
15850
- const [reorderHrefKey, setReorderHrefKey] = (0, import_react17.useState)(null);
15851
- const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react17.useState)(false);
15852
- const [toggleState, setToggleState] = (0, import_react17.useState)(null);
15853
- const [maxBadge, setMaxBadge] = (0, import_react17.useState)(null);
15854
- const [activeCommands, setActiveCommands] = (0, import_react17.useState)(/* @__PURE__ */ new Set());
15855
- const [sectionGap, setSectionGap] = (0, import_react17.useState)(null);
15856
- const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react17.useState)(false);
15857
- const hoveredNavContainerRef = (0, import_react17.useRef)(null);
15858
- const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react17.useState)(null);
15859
- const hoveredItemElRef = (0, import_react17.useRef)(null);
15860
- const [hoveredItemRect, setHoveredItemRect] = (0, import_react17.useState)(null);
15861
- const [hoveredTextRect, setHoveredTextRect] = (0, import_react17.useState)(null);
15862
- (0, import_react17.useEffect)(() => {
14844
+ const [selectedIsCta, setSelectedIsCta] = (0, import_react16.useState)(false);
14845
+ const [selectedIsSocial, setSelectedIsSocial] = (0, import_react16.useState)(false);
14846
+ const [selectedIsSocialsRow, setSelectedIsSocialsRow] = (0, import_react16.useState)(false);
14847
+ const [reorderHrefKey, setReorderHrefKey] = (0, import_react16.useState)(null);
14848
+ const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react16.useState)(false);
14849
+ const [toggleState, setToggleState] = (0, import_react16.useState)(null);
14850
+ const [maxBadge, setMaxBadge] = (0, import_react16.useState)(null);
14851
+ const [activeCommands, setActiveCommands] = (0, import_react16.useState)(/* @__PURE__ */ new Set());
14852
+ const [sectionGap, setSectionGap] = (0, import_react16.useState)(null);
14853
+ const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react16.useState)(false);
14854
+ const hoveredNavContainerRef = (0, import_react16.useRef)(null);
14855
+ const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react16.useState)(null);
14856
+ const hoveredItemElRef = (0, import_react16.useRef)(null);
14857
+ const [hoveredItemRect, setHoveredItemRect] = (0, import_react16.useState)(null);
14858
+ const [hoveredTextRect, setHoveredTextRect] = (0, import_react16.useState)(null);
14859
+ (0, import_react16.useEffect)(() => {
15863
14860
  const sync = () => {
15864
14861
  const el = document.querySelector(
15865
14862
  '[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]):not([data-ohw-editable="form"] *)'
@@ -15880,56 +14877,43 @@ function OhhwellsBridge() {
15880
14877
  });
15881
14878
  return () => observer.disconnect();
15882
14879
  }, []);
15883
- const siblingHintElRef = (0, import_react17.useRef)(null);
15884
- const [siblingHintRect, setSiblingHintRect] = (0, import_react17.useState)(null);
15885
- const [siblingHintRects, setSiblingHintRects] = (0, import_react17.useState)([]);
15886
- const [isItemDragging, setIsItemDragging] = (0, import_react17.useState)(false);
15887
- const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react17.useState)(false);
14880
+ const siblingHintElRef = (0, import_react16.useRef)(null);
14881
+ const [siblingHintRect, setSiblingHintRect] = (0, import_react16.useState)(null);
14882
+ const [siblingHintRects, setSiblingHintRects] = (0, import_react16.useState)([]);
14883
+ const [isItemDragging, setIsItemDragging] = (0, import_react16.useState)(false);
14884
+ const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react16.useState)(false);
15888
14885
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
15889
- const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react17.useState)(null);
15890
- const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react17.useState)(null);
15891
- const footerDragRef = (0, import_react17.useRef)(null);
15892
- const [footerDropSlots, setFooterDropSlots] = (0, import_react17.useState)([]);
15893
- const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react17.useState)(null);
15894
- const [draggedItemRect, setDraggedItemRect] = (0, import_react17.useState)(null);
15895
- const footerPointerDragRef = (0, import_react17.useRef)(null);
15896
- const suppressNextClickRef = (0, import_react17.useRef)(false);
15897
- const suppressClickUntilRef = (0, import_react17.useRef)(0);
15898
- const [linkPopover, setLinkPopover] = (0, import_react17.useState)(null);
15899
- const linkPopoverSessionRef = (0, import_react17.useRef)(null);
15900
- const addNavAfterAnchorRef = (0, import_react17.useRef)(null);
15901
- const editContentRef = (0, import_react17.useRef)({});
15902
- const aiSectionsRef = (0, import_react17.useRef)("");
15903
- const brandKitRef = (0, import_react17.useRef)("");
15904
- const stylesRef = (0, import_react17.useRef)("");
15905
- const pendingDeleteUndoRef = (0, import_react17.useRef)(null);
15906
- const [floatingPanel, setFloatingPanel] = (0, import_react17.useState)(null);
15907
- const floatingPanelOpenRef = (0, import_react17.useRef)(false);
15908
- const setFloatingPanelRef = (0, import_react17.useRef)(setFloatingPanel);
15909
- const [floatingPanelPos, setFloatingPanelPos] = (0, import_react17.useState)(null);
15910
- const [logoSizeDraft, setLogoSizeDraft] = (0, import_react17.useState)(null);
15911
- const [editorViewport, setEditorViewport] = (0, import_react17.useState)("desktop");
15912
- const [parentScrollSnap, setParentScrollSnap] = (0, import_react17.useState)(null);
15913
- const [sitePages, setSitePages] = (0, import_react17.useState)([]);
15914
- const [sectionsByPath, setSectionsByPath] = (0, import_react17.useState)({});
15915
- const sectionsPrefetchGenRef = (0, import_react17.useRef)(0);
15916
- const setLinkPopoverRef = (0, import_react17.useRef)(setLinkPopover);
15917
- const linkPopoverPanelRef = (0, import_react17.useRef)(null);
15918
- const linkPopoverOpenRef = (0, import_react17.useRef)(false);
15919
- const linkPopoverGraceUntilRef = (0, import_react17.useRef)(0);
14886
+ const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
14887
+ const floatingPanelOpenRef = (0, import_react16.useRef)(false);
14888
+ floatingPanelOpenRef.current = floatingPanel !== null;
14889
+ const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
14890
+ const [logoSizeDraft, setLogoSizeDraft] = (0, import_react16.useState)(null);
14891
+ const [editorViewport, setEditorViewport] = (0, import_react16.useState)("desktop");
14892
+ const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
14893
+ const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react16.useState)(null);
14894
+ const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react16.useState)(null);
14895
+ const footerDragRef = (0, import_react16.useRef)(null);
14896
+ const [footerDropSlots, setFooterDropSlots] = (0, import_react16.useState)([]);
14897
+ const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react16.useState)(null);
14898
+ const [draggedItemRect, setDraggedItemRect] = (0, import_react16.useState)(null);
14899
+ const footerPointerDragRef = (0, import_react16.useRef)(null);
14900
+ const suppressNextClickRef = (0, import_react16.useRef)(false);
14901
+ const suppressClickUntilRef = (0, import_react16.useRef)(0);
14902
+ const [linkPopover, setLinkPopover] = (0, import_react16.useState)(null);
14903
+ const linkPopoverSessionRef = (0, import_react16.useRef)(null);
14904
+ const addNavAfterAnchorRef = (0, import_react16.useRef)(null);
14905
+ const editContentRef = (0, import_react16.useRef)({});
14906
+ const aiSectionsRef = (0, import_react16.useRef)("");
14907
+ const pendingDeleteUndoRef = (0, import_react16.useRef)(null);
14908
+ const [sitePages, setSitePages] = (0, import_react16.useState)([]);
14909
+ const [sectionsByPath, setSectionsByPath] = (0, import_react16.useState)({});
14910
+ const sectionsPrefetchGenRef = (0, import_react16.useRef)(0);
14911
+ const setLinkPopoverRef = (0, import_react16.useRef)(setLinkPopover);
14912
+ const linkPopoverPanelRef = (0, import_react16.useRef)(null);
14913
+ const linkPopoverOpenRef = (0, import_react16.useRef)(false);
14914
+ const linkPopoverGraceUntilRef = (0, import_react16.useRef)(0);
15920
14915
  setLinkPopoverRef.current = setLinkPopover;
15921
- setFloatingPanelRef.current = setFloatingPanel;
15922
14916
  linkPopoverSessionRef.current = linkPopover;
15923
- floatingPanelOpenRef.current = Boolean(floatingPanel);
15924
- (0, import_react17.useEffect)(() => {
15925
- const syncViewport = () => {
15926
- const next = window.innerWidth <= 480 ? "mobile" : "desktop";
15927
- setEditorViewport((prev) => prev === next ? prev : next);
15928
- };
15929
- syncViewport();
15930
- window.addEventListener("resize", syncViewport);
15931
- return () => window.removeEventListener("resize", syncViewport);
15932
- }, []);
15933
14917
  const {
15934
14918
  navDragRef,
15935
14919
  navDropSlots,
@@ -15962,20 +14946,10 @@ function OhhwellsBridge() {
15962
14946
  getNavigationItemAnchor,
15963
14947
  isDragHandleDisabled
15964
14948
  });
15965
- const { sectionDropSlots, activeSectionDropIndex, isSectionDragging } = useSectionDrag({
15966
- isEditMode,
15967
- editContentRef,
15968
- postToParentRef,
15969
- parentScrollRef,
15970
- navDragRef,
15971
- footerDragRef,
15972
- suppressNextClickRef,
15973
- suppressClickUntilRef
15974
- });
15975
14949
  const bumpLinkPopoverGrace = () => {
15976
14950
  linkPopoverGraceUntilRef.current = Date.now() + 350;
15977
14951
  };
15978
- const runSectionsPrefetch = (0, import_react17.useCallback)((pages) => {
14952
+ const runSectionsPrefetch = (0, import_react16.useCallback)((pages) => {
15979
14953
  if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
15980
14954
  const gen = ++sectionsPrefetchGenRef.current;
15981
14955
  const paths = pages.map((p) => p.path);
@@ -15994,9 +14968,9 @@ function OhhwellsBridge() {
15994
14968
  );
15995
14969
  });
15996
14970
  }, [isEditMode, pathname]);
15997
- const runSectionsPrefetchRef = (0, import_react17.useRef)(runSectionsPrefetch);
14971
+ const runSectionsPrefetchRef = (0, import_react16.useRef)(runSectionsPrefetch);
15998
14972
  runSectionsPrefetchRef.current = runSectionsPrefetch;
15999
- (0, import_react17.useEffect)(() => {
14973
+ (0, import_react16.useEffect)(() => {
16000
14974
  if (!linkPopover) {
16001
14975
  document.documentElement.removeAttribute("data-ohw-link-popover-open");
16002
14976
  return;
@@ -16024,7 +14998,7 @@ function OhhwellsBridge() {
16024
14998
  document.documentElement.removeAttribute("data-ohw-link-popover-open");
16025
14999
  };
16026
15000
  }, [linkPopover, postToParent2]);
16027
- (0, import_react17.useEffect)(() => {
15001
+ (0, import_react16.useEffect)(() => {
16028
15002
  if (!isEditMode) return;
16029
15003
  const useFixtures = shouldUseDevFixtures();
16030
15004
  if (useFixtures) {
@@ -16048,14 +15022,14 @@ function OhhwellsBridge() {
16048
15022
  if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
16049
15023
  return () => window.removeEventListener("message", onSitePages);
16050
15024
  }, [isEditMode, postToParent2]);
16051
- (0, import_react17.useEffect)(() => {
15025
+ (0, import_react16.useEffect)(() => {
16052
15026
  if (!isEditMode || shouldUseDevFixtures()) return;
16053
15027
  void loadAllSectionsManifest().then((manifest) => {
16054
15028
  if (Object.keys(manifest).length === 0) return;
16055
15029
  setSectionsByPath((prev) => ({ ...manifest, ...prev }));
16056
15030
  });
16057
15031
  }, [isEditMode]);
16058
- (0, import_react17.useEffect)(() => {
15032
+ (0, import_react16.useEffect)(() => {
16059
15033
  const update = () => {
16060
15034
  const el = activeElRef.current ?? selectedElRef.current;
16061
15035
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
@@ -16079,10 +15053,10 @@ function OhhwellsBridge() {
16079
15053
  vvp.removeEventListener("resize", update);
16080
15054
  };
16081
15055
  }, []);
16082
- const refreshStateRules = (0, import_react17.useCallback)(() => {
15056
+ const refreshStateRules = (0, import_react16.useCallback)(() => {
16083
15057
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
16084
15058
  }, []);
16085
- const processConfigRequest = (0, import_react17.useCallback)((insertAfterVal) => {
15059
+ const processConfigRequest = (0, import_react16.useCallback)((insertAfterVal) => {
16086
15060
  const tracker = getSectionsTracker();
16087
15061
  let entries = [];
16088
15062
  try {
@@ -16105,7 +15079,7 @@ function OhhwellsBridge() {
16105
15079
  }
16106
15080
  window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
16107
15081
  }, [isEditMode]);
16108
- const deactivate = (0, import_react17.useCallback)(() => {
15082
+ const deactivate = (0, import_react16.useCallback)(() => {
16109
15083
  const el = activeElRef.current;
16110
15084
  if (!el) return;
16111
15085
  const isFormBlock = el.dataset.ohwEditable === "form";
@@ -16146,12 +15120,12 @@ function OhhwellsBridge() {
16146
15120
  setToolbarShowEditLink(false);
16147
15121
  postToParent2({ type: "ow:exit-edit" });
16148
15122
  }, [postToParent2]);
16149
- const clearSelectedAttr = (0, import_react17.useCallback)(() => {
15123
+ const clearSelectedAttr = (0, import_react16.useCallback)(() => {
16150
15124
  document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
16151
15125
  el.removeAttribute("data-ohw-selected");
16152
15126
  });
16153
15127
  }, []);
16154
- const deselect = (0, import_react17.useCallback)(() => {
15128
+ const deselect = (0, import_react16.useCallback)(() => {
16155
15129
  clearSelectedAttr();
16156
15130
  selectedElRef.current = null;
16157
15131
  selectedHrefKeyRef.current = null;
@@ -16180,12 +15154,11 @@ function OhhwellsBridge() {
16180
15154
  setToolbarVariant("none");
16181
15155
  }
16182
15156
  }, [clearSelectedAttr]);
16183
- const markSelected = (0, import_react17.useCallback)((el) => {
15157
+ const markSelected = (0, import_react16.useCallback)((el) => {
16184
15158
  clearSelectedAttr();
16185
- el.removeAttribute("data-ohw-hovered");
16186
15159
  el.setAttribute("data-ohw-selected", "");
16187
15160
  }, [clearSelectedAttr]);
16188
- const resolveHrefKeyElement = (0, import_react17.useCallback)((hrefKey) => {
15161
+ const resolveHrefKeyElement = (0, import_react16.useCallback)((hrefKey) => {
16189
15162
  if (isFooterHrefKey(hrefKey)) {
16190
15163
  return document.querySelector(
16191
15164
  `footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
@@ -16200,7 +15173,7 @@ function OhhwellsBridge() {
16200
15173
  `[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
16201
15174
  );
16202
15175
  }, []);
16203
- const resyncSelectedNavigationItem = (0, import_react17.useCallback)(() => {
15176
+ const resyncSelectedNavigationItem = (0, import_react16.useCallback)(() => {
16204
15177
  const hrefKey = selectedHrefKeyRef.current;
16205
15178
  if (hrefKey) {
16206
15179
  const link = resolveHrefKeyElement(hrefKey);
@@ -16238,7 +15211,7 @@ function OhhwellsBridge() {
16238
15211
  );
16239
15212
  }
16240
15213
  }, [resolveHrefKeyElement]);
16241
- const reselectNavigationItem = (0, import_react17.useCallback)((navAnchor) => {
15214
+ const reselectNavigationItem = (0, import_react16.useCallback)((navAnchor) => {
16242
15215
  selectedElRef.current = navAnchor;
16243
15216
  selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
16244
15217
  selectedFooterColAttrRef.current = null;
@@ -16269,7 +15242,7 @@ function OhhwellsBridge() {
16269
15242
  setToolbarShowEditLink(false);
16270
15243
  setActiveCommands(/* @__PURE__ */ new Set());
16271
15244
  }, [markSelected]);
16272
- const commitNavigationTextEdit = (0, import_react17.useCallback)((navAnchor) => {
15245
+ const commitNavigationTextEdit = (0, import_react16.useCallback)((navAnchor) => {
16273
15246
  const el = activeElRef.current;
16274
15247
  if (!el) return;
16275
15248
  const key = el.dataset.ohwKey;
@@ -16302,7 +15275,7 @@ function OhhwellsBridge() {
16302
15275
  postToParent2({ type: "ow:exit-edit" });
16303
15276
  reselectNavigationItem(navAnchor);
16304
15277
  }, [postToParent2, reselectNavigationItem]);
16305
- const handleAddTopLevelNavItem = (0, import_react17.useCallback)(() => {
15278
+ const handleAddTopLevelNavItem = (0, import_react16.useCallback)(() => {
16306
15279
  const items = listNavbarRootItems();
16307
15280
  addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
16308
15281
  deselectRef.current();
@@ -16314,7 +15287,7 @@ function OhhwellsBridge() {
16314
15287
  intent: "add-nav"
16315
15288
  });
16316
15289
  }, []);
16317
- const maybeWarnNavLinkDropdownConflict = (0, import_react17.useCallback)(
15290
+ const maybeWarnNavLinkDropdownConflict = (0, import_react16.useCallback)(
16318
15291
  (anchor) => {
16319
15292
  if (!isNavbarHrefKey(anchor.getAttribute("data-ohw-href-key"))) return;
16320
15293
  if (!navDropdownsOpenOnClick()) return;
@@ -16327,7 +15300,7 @@ function OhhwellsBridge() {
16327
15300
  },
16328
15301
  [postToParent2]
16329
15302
  );
16330
- const handleNavDropdownOpenChange = (0, import_react17.useCallback)((open) => {
15303
+ const handleNavDropdownOpenChange = (0, import_react16.useCallback)((open) => {
16331
15304
  const selected = selectedElRef.current;
16332
15305
  if (!selected || !isNavigationItem2(selected)) return;
16333
15306
  setNavGroupForceOpen(selected, open);
@@ -16339,7 +15312,7 @@ function OhhwellsBridge() {
16339
15312
  }
16340
15313
  });
16341
15314
  }, []);
16342
- const handleFooterHeadingVisibleChange = (0, import_react17.useCallback)(
15315
+ const handleFooterHeadingVisibleChange = (0, import_react16.useCallback)(
16343
15316
  (visible) => {
16344
15317
  const selected = selectedElRef.current;
16345
15318
  if (!selected || !isFooterFrameSelectionRef.current) return;
@@ -16363,7 +15336,7 @@ function OhhwellsBridge() {
16363
15336
  },
16364
15337
  [postToParent2]
16365
15338
  );
16366
- const enterEditOnNewItem = (0, import_react17.useCallback)((anchor) => {
15339
+ const enterEditOnNewItem = (0, import_react16.useCallback)((anchor) => {
16367
15340
  const label = anchor.querySelector('[data-ohw-editable="text"]');
16368
15341
  if (!label) {
16369
15342
  selectRef.current(anchor);
@@ -16372,7 +15345,7 @@ function OhhwellsBridge() {
16372
15345
  setNavGroupForceOpen(anchor, true);
16373
15346
  activateRef.current(label);
16374
15347
  }, []);
16375
- const handleAddChildItem = (0, import_react17.useCallback)(() => {
15348
+ const handleAddChildItem = (0, import_react16.useCallback)(() => {
16376
15349
  const selected = selectedElRef.current;
16377
15350
  if (!selected) return;
16378
15351
  const socialsRow = isSocialsRow(selected) ? selected : findSocialsRow(selected);
@@ -16484,7 +15457,7 @@ function OhhwellsBridge() {
16484
15457
  enterEditOnNewItem(result.anchor);
16485
15458
  });
16486
15459
  }, [enterEditOnNewItem, isFooterFrameSelection, maybeWarnNavLinkDropdownConflict, postToParent2]);
16487
- const handleAddFooterColumn = (0, import_react17.useCallback)(() => {
15460
+ const handleAddFooterColumn = (0, import_react16.useCallback)(() => {
16488
15461
  if (!canAddFooterColumn()) {
16489
15462
  postToParent2({
16490
15463
  type: "ow:toast",
@@ -16505,7 +15478,7 @@ function OhhwellsBridge() {
16505
15478
  selectRef.current(result.firstLink);
16506
15479
  });
16507
15480
  }, [postToParent2]);
16508
- const clearFooterDragVisuals = (0, import_react17.useCallback)(() => {
15481
+ const clearFooterDragVisuals = (0, import_react16.useCallback)(() => {
16509
15482
  footerDragRef.current = null;
16510
15483
  setSiblingHintRects([]);
16511
15484
  setFooterDropSlots([]);
@@ -16514,7 +15487,7 @@ function OhhwellsBridge() {
16514
15487
  setIsItemDragging(false);
16515
15488
  unlockFooterDragInteraction();
16516
15489
  }, []);
16517
- const refreshFooterDragVisuals = (0, import_react17.useCallback)((session, activeSlot, clientX, clientY) => {
15490
+ const refreshFooterDragVisuals = (0, import_react16.useCallback)((session, activeSlot, clientX, clientY) => {
16518
15491
  const dragged = session.draggedEl;
16519
15492
  setDraggedItemRect(dragged.getBoundingClientRect());
16520
15493
  if (typeof clientX === "number" && typeof clientY === "number") {
@@ -16546,13 +15519,13 @@ function OhhwellsBridge() {
16546
15519
  const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
16547
15520
  setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
16548
15521
  }, []);
16549
- const refreshFooterDragVisualsRef = (0, import_react17.useRef)(refreshFooterDragVisuals);
15522
+ const refreshFooterDragVisualsRef = (0, import_react16.useRef)(refreshFooterDragVisuals);
16550
15523
  refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
16551
- const commitFooterDragRef = (0, import_react17.useRef)(() => {
15524
+ const commitFooterDragRef = (0, import_react16.useRef)(() => {
16552
15525
  });
16553
- const beginFooterDragRef = (0, import_react17.useRef)(() => {
15526
+ const beginFooterDragRef = (0, import_react16.useRef)(() => {
16554
15527
  });
16555
- const beginFooterDrag = (0, import_react17.useCallback)(
15528
+ const beginFooterDrag = (0, import_react16.useCallback)(
16556
15529
  (session) => {
16557
15530
  const rect = session.draggedEl.getBoundingClientRect();
16558
15531
  session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
@@ -16572,7 +15545,7 @@ function OhhwellsBridge() {
16572
15545
  [refreshFooterDragVisuals]
16573
15546
  );
16574
15547
  beginFooterDragRef.current = beginFooterDrag;
16575
- const commitFooterDrag = (0, import_react17.useCallback)(
15548
+ const commitFooterDrag = (0, import_react16.useCallback)(
16576
15549
  (clientX, clientY) => {
16577
15550
  const session = footerDragRef.current;
16578
15551
  if (!session) {
@@ -16700,7 +15673,7 @@ function OhhwellsBridge() {
16700
15673
  [clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
16701
15674
  );
16702
15675
  commitFooterDragRef.current = commitFooterDrag;
16703
- const startFooterLinkDrag = (0, import_react17.useCallback)(
15676
+ const startFooterLinkDrag = (0, import_react16.useCallback)(
16704
15677
  (anchor, clientX, clientY, wasSelected) => {
16705
15678
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
16706
15679
  if (!hrefKey) return false;
@@ -16736,7 +15709,7 @@ function OhhwellsBridge() {
16736
15709
  },
16737
15710
  [beginFooterDrag]
16738
15711
  );
16739
- const startFooterColumnDrag = (0, import_react17.useCallback)(
15712
+ const startFooterColumnDrag = (0, import_react16.useCallback)(
16740
15713
  (columnEl, clientX, clientY, wasSelected) => {
16741
15714
  const columns = listFooterColumns();
16742
15715
  const idx = columns.indexOf(columnEl);
@@ -16756,7 +15729,7 @@ function OhhwellsBridge() {
16756
15729
  },
16757
15730
  [beginFooterDrag]
16758
15731
  );
16759
- const handleItemDragStart = (0, import_react17.useCallback)(
15732
+ const handleItemDragStart = (0, import_react16.useCallback)(
16760
15733
  (e) => {
16761
15734
  const selected = selectedElRef.current;
16762
15735
  if (!selected) {
@@ -16776,7 +15749,7 @@ function OhhwellsBridge() {
16776
15749
  },
16777
15750
  [startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
16778
15751
  );
16779
- const handleItemDragEnd = (0, import_react17.useCallback)(
15752
+ const handleItemDragEnd = (0, import_react16.useCallback)(
16780
15753
  (e) => {
16781
15754
  if (footerDragRef.current) {
16782
15755
  const x = e?.clientX;
@@ -16802,7 +15775,7 @@ function OhhwellsBridge() {
16802
15775
  },
16803
15776
  [commitFooterDrag, commitNavDrag, navDragRef]
16804
15777
  );
16805
- const handleItemChromePointerDown = (0, import_react17.useCallback)((e) => {
15778
+ const handleItemChromePointerDown = (0, import_react16.useCallback)((e) => {
16806
15779
  if (e.button !== 0) return;
16807
15780
  const selected = selectedElRef.current;
16808
15781
  if (!selected) return;
@@ -16833,7 +15806,7 @@ function OhhwellsBridge() {
16833
15806
  }
16834
15807
  if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
16835
15808
  }, [armNavPressFromChrome]);
16836
- const handleItemChromeClick = (0, import_react17.useCallback)((clientX, clientY) => {
15809
+ const handleItemChromeClick = (0, import_react16.useCallback)((clientX, clientY) => {
16837
15810
  if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
16838
15811
  suppressNextClickRef.current = false;
16839
15812
  return;
@@ -16846,7 +15819,7 @@ function OhhwellsBridge() {
16846
15819
  }, []);
16847
15820
  reselectNavigationItemRef.current = reselectNavigationItem;
16848
15821
  commitNavigationTextEditRef.current = commitNavigationTextEdit;
16849
- const select = (0, import_react17.useCallback)((anchor) => {
15822
+ const select = (0, import_react16.useCallback)((anchor) => {
16850
15823
  if (!isNavigationItem2(anchor)) return;
16851
15824
  if (activeElRef.current) deactivate();
16852
15825
  aiSectionApiRef.current?.selectFromElement(anchor);
@@ -16889,7 +15862,7 @@ function OhhwellsBridge() {
16889
15862
  setFloatingPanel(null);
16890
15863
  setLogoSizeDraft(null);
16891
15864
  }, [deactivate, markSelected]);
16892
- const selectFrame = (0, import_react17.useCallback)((el) => {
15865
+ const selectFrame = (0, import_react16.useCallback)((el) => {
16893
15866
  if (!isNavigationContainer(el)) return;
16894
15867
  if (activeElRef.current) deactivate();
16895
15868
  aiSectionApiRef.current?.selectFromElement(el);
@@ -16940,7 +15913,7 @@ function OhhwellsBridge() {
16940
15913
  setFloatingPanel(null);
16941
15914
  setLogoSizeDraft(null);
16942
15915
  }, [deactivate, markSelected, postToParent2]);
16943
- const selectLogo = (0, import_react17.useCallback)(
15916
+ const selectLogo = (0, import_react16.useCallback)(
16944
15917
  (logoEl) => {
16945
15918
  if (activeElRef.current) deactivate();
16946
15919
  selectedElRef.current = logoEl;
@@ -16969,7 +15942,7 @@ function OhhwellsBridge() {
16969
15942
  },
16970
15943
  [deactivate, markSelected]
16971
15944
  );
16972
- const openLogoSizePanel = (0, import_react17.useCallback)((logoEl) => {
15945
+ const openLogoSizePanel = (0, import_react16.useCallback)((logoEl) => {
16973
15946
  const placement = getLogoPlacement(logoEl);
16974
15947
  const draft = readLogoSizeState(editContentRef.current, placement);
16975
15948
  setLogoSizeDraft(draft);
@@ -16982,7 +15955,7 @@ function OhhwellsBridge() {
16982
15955
  placement
16983
15956
  });
16984
15957
  }, []);
16985
- const openSocialsDisplayPanel = (0, import_react17.useCallback)((row) => {
15958
+ const openSocialsDisplayPanel = (0, import_react16.useCallback)((row) => {
16986
15959
  setParentScrollSnap(parentScrollRef.current);
16987
15960
  setFloatingPanel({
16988
15961
  key: "socials-display",
@@ -16992,7 +15965,7 @@ function OhhwellsBridge() {
16992
15965
  row
16993
15966
  });
16994
15967
  }, []);
16995
- const changeSocialsDisplay = (0, import_react17.useCallback)(
15968
+ const changeSocialsDisplay = (0, import_react16.useCallback)(
16996
15969
  (row, next) => {
16997
15970
  if (next.icon) {
16998
15971
  const missing = socialsMissingIcons(row);
@@ -17015,17 +15988,17 @@ function OhhwellsBridge() {
17015
15988
  },
17016
15989
  []
17017
15990
  );
17018
- const closeFloatingPanelOnly = (0, import_react17.useCallback)(() => {
15991
+ const closeFloatingPanelOnly = (0, import_react16.useCallback)(() => {
17019
15992
  setFloatingPanel(null);
17020
15993
  setLogoSizeDraft(null);
17021
15994
  }, []);
17022
15995
  closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
17023
- const closeFloatingPanelAndDeselect = (0, import_react17.useCallback)(() => {
15996
+ const closeFloatingPanelAndDeselect = (0, import_react16.useCallback)(() => {
17024
15997
  setFloatingPanel(null);
17025
15998
  setLogoSizeDraft(null);
17026
15999
  deselectRef.current();
17027
16000
  }, []);
17028
- (0, import_react17.useEffect)(() => {
16001
+ (0, import_react16.useEffect)(() => {
17029
16002
  const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
17030
16003
  if (!session || !logoSizeDraft) {
17031
16004
  postToParentRef.current({ type: "ow:logo-size-panel", open: false });
@@ -17044,7 +16017,7 @@ function OhhwellsBridge() {
17044
16017
  max: LOGO_SIZE_MAX
17045
16018
  });
17046
16019
  }, [floatingPanel, logoSizeDraft, editorViewport]);
17047
- const persistLogoSizeDraft = (0, import_react17.useCallback)(
16020
+ const persistLogoSizeDraft = (0, import_react16.useCallback)(
17048
16021
  (placement, draft) => {
17049
16022
  const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
17050
16023
  const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
@@ -17084,7 +16057,7 @@ function OhhwellsBridge() {
17084
16057
  },
17085
16058
  [postToParent2]
17086
16059
  );
17087
- const activate = (0, import_react17.useCallback)((el, options) => {
16060
+ const activate = (0, import_react16.useCallback)((el, options) => {
17088
16061
  if (activeElRef.current === el) return;
17089
16062
  if (isIconEditable(el)) return;
17090
16063
  if (el.hasAttribute("data-ohw-social-label")) return;
@@ -17168,8 +16141,8 @@ function OhhwellsBridge() {
17168
16141
  openLogoSizePanelRef.current = openLogoSizePanel;
17169
16142
  deselectRef.current = deselect;
17170
16143
  closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
17171
- const lastSiteWideScopeRef = (0, import_react17.useRef)(null);
17172
- (0, import_react17.useEffect)(() => {
16144
+ const lastSiteWideScopeRef = (0, import_react16.useRef)(null);
16145
+ (0, import_react16.useEffect)(() => {
17173
16146
  if (!isEditMode) {
17174
16147
  if (lastSiteWideScopeRef.current !== false) {
17175
16148
  lastSiteWideScopeRef.current = false;
@@ -17195,34 +16168,22 @@ function OhhwellsBridge() {
17195
16168
  isFooterFrameSelection,
17196
16169
  postToParent2
17197
16170
  ]);
17198
- (0, import_react17.useLayoutEffect)(() => {
16171
+ (0, import_react16.useLayoutEffect)(() => {
17199
16172
  if (!subdomain || isEditMode) {
17200
16173
  setFetchState("done");
17201
16174
  return;
17202
16175
  }
17203
16176
  const applyContent = (content) => {
17204
16177
  const imageLoads = [];
17205
- if (typeof content[BRAND_KIT_KEY] === "string") {
17206
- brandKitRef.current = content[BRAND_KIT_KEY];
17207
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
17208
- }
17209
16178
  if (typeof content[AI_SECTIONS_KEY] === "string") {
17210
16179
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
17211
16180
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
17212
16181
  }
17213
- if (typeof content[STYLE_STORE_KEY] === "string") {
17214
- stylesRef.current = content[STYLE_STORE_KEY];
17215
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
17216
- }
17217
- applyBrandChrome(content);
17218
16182
  for (const [key, val] of Object.entries(content)) {
17219
16183
  if (key === "__ohw_sections") continue;
17220
16184
  if (key === AI_SECTIONS_KEY) continue;
17221
16185
  if (key === LOGO_PLACEHOLDER_KEY) continue;
17222
16186
  if (LOGO_IMAGE_KEYS.includes(key)) continue;
17223
- if (key === BRAND_KIT_KEY) continue;
17224
- if (key === STYLE_STORE_KEY) continue;
17225
- if (BRAND_CHROME_KEYS.has(key)) continue;
17226
16187
  if (applyVideoSettingNode(key, val)) continue;
17227
16188
  if (applyCarouselNode(key, val)) continue;
17228
16189
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -17280,9 +16241,7 @@ function OhhwellsBridge() {
17280
16241
  let cancelled = false;
17281
16242
  setFetchState("loading");
17282
16243
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
17283
- const initialPath = pathname;
17284
- fetchedContentPaths.add(`${subdomain}::${initialPath}`);
17285
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
16244
+ fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
17286
16245
  if (cancelled) return;
17287
16246
  const content = data?.content ?? {};
17288
16247
  contentCache.set(subdomain, content);
@@ -17295,7 +16254,7 @@ function OhhwellsBridge() {
17295
16254
  cancelled = true;
17296
16255
  };
17297
16256
  }, [subdomain, isEditMode]);
17298
- (0, import_react17.useEffect)(() => {
16257
+ (0, import_react16.useEffect)(() => {
17299
16258
  if (!isEditMode) return;
17300
16259
  const resolveIndex = (form, clientY) => {
17301
16260
  const wrappers = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== fieldDragRef.current?.key);
@@ -17336,7 +16295,7 @@ function OhhwellsBridge() {
17336
16295
  window.removeEventListener("drop", onDrop, true);
17337
16296
  };
17338
16297
  }, [buildFieldDropSlots, isEditMode, persistFields, selectField]);
17339
- (0, import_react17.useEffect)(() => {
16298
+ (0, import_react16.useEffect)(() => {
17340
16299
  if (!isEditMode) return;
17341
16300
  const mark = () => document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
17342
16301
  markFormFields(form);
@@ -17348,7 +16307,7 @@ function OhhwellsBridge() {
17348
16307
  });
17349
16308
  return () => observer.disconnect();
17350
16309
  }, [isEditMode, fetchState, pathname]);
17351
- (0, import_react17.useEffect)(() => {
16310
+ (0, import_react16.useEffect)(() => {
17352
16311
  if (!isEditMode) return;
17353
16312
  let saveTimer = null;
17354
16313
  const onInput = (e) => {
@@ -17370,14 +16329,14 @@ function OhhwellsBridge() {
17370
16329
  document.addEventListener("input", onInput, true);
17371
16330
  return () => document.removeEventListener("input", onInput, true);
17372
16331
  }, [isEditMode, persistFields]);
17373
- (0, import_react17.useEffect)(() => {
16332
+ (0, import_react16.useEffect)(() => {
17374
16333
  if (isEditMode || fetchState !== "done") return;
17375
16334
  const content = contentCache.get(subdomain) ?? {};
17376
16335
  document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
17377
16336
  reconcileFieldsFromContent(form, content);
17378
16337
  });
17379
16338
  }, [isEditMode, fetchState, subdomain]);
17380
- (0, import_react17.useEffect)(() => {
16339
+ (0, import_react16.useEffect)(() => {
17381
16340
  if (!isEditMode) return;
17382
16341
  const swallow = (e) => {
17383
16342
  const target = e.target;
@@ -17386,12 +16345,12 @@ function OhhwellsBridge() {
17386
16345
  document.addEventListener("submit", swallow, true);
17387
16346
  return () => document.removeEventListener("submit", swallow, true);
17388
16347
  }, [isEditMode]);
17389
- (0, import_react17.useEffect)(() => {
16348
+ (0, import_react16.useEffect)(() => {
17390
16349
  if (isEditMode || fetchState !== "done") return;
17391
16350
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
17392
16351
  bindPublishedForms(apiUrl, subdomain, contentCache.get(subdomain) ?? {});
17393
16352
  }, [isEditMode, fetchState, subdomain]);
17394
- (0, import_react17.useEffect)(() => {
16353
+ (0, import_react16.useEffect)(() => {
17395
16354
  if (!subdomain || isEditMode) return;
17396
16355
  let debounceTimer = null;
17397
16356
  let observer = null;
@@ -17402,21 +16361,10 @@ function OhhwellsBridge() {
17402
16361
  initSectionInstancesFromContent(content, window.location.pathname);
17403
16362
  observer?.disconnect();
17404
16363
  try {
17405
- applyBrandChrome(content);
17406
- if (typeof content[BRAND_KIT_KEY] === "string") {
17407
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
17408
- }
17409
- if (typeof content[STYLE_STORE_KEY] === "string") {
17410
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
17411
- }
17412
16364
  for (const [key, val] of Object.entries(content)) {
17413
16365
  if (key === "__ohw_sections") continue;
17414
16366
  if (key === LOGO_PLACEHOLDER_KEY) continue;
17415
16367
  if (LOGO_IMAGE_KEYS.includes(key)) continue;
17416
- if (key === BRAND_KIT_KEY) continue;
17417
- if (key === STYLE_STORE_KEY) continue;
17418
- if (key === STYLE_STORE_KEY) continue;
17419
- if (BRAND_CHROME_KEYS.has(key)) continue;
17420
16368
  if (applyVideoSettingNode(key, val)) continue;
17421
16369
  if (applyCarouselNode(key, val)) continue;
17422
16370
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -17459,17 +16407,6 @@ function OhhwellsBridge() {
17459
16407
  debounceTimer = setTimeout(applyFromCache, 150);
17460
16408
  };
17461
16409
  applyFromCache();
17462
- const pathCacheKey = `${subdomain}::${pathname}`;
17463
- if (!fetchedContentPaths.has(pathCacheKey)) {
17464
- fetchedContentPaths.add(pathCacheKey);
17465
- const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
17466
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
17467
- if (!data?.content) return;
17468
- contentCache.set(subdomain, data.content);
17469
- applyFromCache();
17470
- }).catch(() => {
17471
- });
17472
- }
17473
16410
  observer = new MutationObserver(scheduleApply);
17474
16411
  observer.observe(document.body, { childList: true, subtree: true });
17475
16412
  return () => {
@@ -17477,16 +16414,16 @@ function OhhwellsBridge() {
17477
16414
  if (debounceTimer) clearTimeout(debounceTimer);
17478
16415
  };
17479
16416
  }, [subdomain, isEditMode, pathname]);
17480
- (0, import_react17.useLayoutEffect)(() => {
16417
+ (0, import_react16.useLayoutEffect)(() => {
17481
16418
  const el = document.getElementById("ohw-loader");
17482
16419
  if (!el) return;
17483
16420
  const visible = Boolean(subdomain) && fetchState !== "done";
17484
16421
  el.style.display = visible ? "flex" : "none";
17485
16422
  }, [subdomain, fetchState]);
17486
- (0, import_react17.useEffect)(() => {
16423
+ (0, import_react16.useEffect)(() => {
17487
16424
  postToParent2({ type: "ow:navigation", path: pathname });
17488
16425
  }, [pathname, postToParent2]);
17489
- (0, import_react17.useEffect)(() => {
16426
+ (0, import_react16.useEffect)(() => {
17490
16427
  if (!isEditMode) return;
17491
16428
  if (linkPopoverSessionRef.current?.intent === "add-nav") return;
17492
16429
  if (document.querySelector("[data-ohw-section-picker]")) return;
@@ -17494,7 +16431,7 @@ function OhhwellsBridge() {
17494
16431
  deselectRef.current();
17495
16432
  deactivateRef.current();
17496
16433
  }, [pathname, isEditMode]);
17497
- (0, import_react17.useEffect)(() => {
16434
+ (0, import_react16.useEffect)(() => {
17498
16435
  const contentForNav = () => {
17499
16436
  if (isEditMode) return editContentRef.current;
17500
16437
  if (!subdomain) return {};
@@ -17561,36 +16498,31 @@ function OhhwellsBridge() {
17561
16498
  observer?.disconnect();
17562
16499
  };
17563
16500
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
17564
- (0, import_react17.useEffect)(() => {
16501
+ (0, import_react16.useEffect)(() => {
17565
16502
  if (!isEditMode) return;
17566
- let lastPosted = 0;
17567
16503
  const measure = () => {
17568
16504
  const h = document.body.scrollHeight;
17569
- if (h > 50 && Math.abs(h - lastPosted) > 1) {
17570
- lastPosted = h;
17571
- postToParent2({ type: "ow:height", height: h });
17572
- }
17573
- };
17574
- let raf = null;
17575
- const schedule = () => {
17576
- if (raf != null) return;
17577
- raf = requestAnimationFrame(() => {
17578
- raf = null;
17579
- measure();
17580
- });
16505
+ if (h > 50) postToParent2({ type: "ow:height", height: h });
17581
16506
  };
17582
16507
  const t1 = setTimeout(measure, 50);
17583
16508
  const t2 = setTimeout(measure, 500);
17584
- const ro = new ResizeObserver(schedule);
17585
- ro.observe(document.body);
16509
+ let lastWidth = window.innerWidth;
16510
+ let resizeTimer = null;
16511
+ const handleResize = () => {
16512
+ if (window.innerWidth === lastWidth) return;
16513
+ lastWidth = window.innerWidth;
16514
+ if (resizeTimer) clearTimeout(resizeTimer);
16515
+ resizeTimer = setTimeout(measure, 150);
16516
+ };
16517
+ window.addEventListener("resize", handleResize);
17586
16518
  return () => {
17587
16519
  clearTimeout(t1);
17588
16520
  clearTimeout(t2);
17589
- if (raf != null) cancelAnimationFrame(raf);
17590
- ro.disconnect();
16521
+ if (resizeTimer) clearTimeout(resizeTimer);
16522
+ window.removeEventListener("resize", handleResize);
17591
16523
  };
17592
16524
  }, [pathname, isEditMode, postToParent2]);
17593
- (0, import_react17.useEffect)(() => {
16525
+ (0, import_react16.useEffect)(() => {
17594
16526
  if (!subdomainFromQuery || isEditMode) return;
17595
16527
  const handleClick = (e) => {
17596
16528
  const anchor = e.target.closest("a");
@@ -17606,7 +16538,7 @@ function OhhwellsBridge() {
17606
16538
  document.addEventListener("click", handleClick, true);
17607
16539
  return () => document.removeEventListener("click", handleClick, true);
17608
16540
  }, [subdomainFromQuery, isEditMode, router]);
17609
- (0, import_react17.useEffect)(() => {
16541
+ (0, import_react16.useEffect)(() => {
17610
16542
  if (!isEditMode) {
17611
16543
  editStylesRef.current?.base.remove();
17612
16544
  editStylesRef.current?.forceHover.remove();
@@ -17768,21 +16700,16 @@ function OhhwellsBridge() {
17768
16700
  return;
17769
16701
  }
17770
16702
  const target = e.target;
17771
- if (target.closest("[data-ohw-ai-review]")) return;
17772
16703
  if (target.closest("[data-ohw-toolbar]")) return;
17773
16704
  if (target.closest("[data-ohw-state-toggle]")) return;
17774
16705
  if (target.closest("[data-ohw-max-badge]")) return;
17775
16706
  if (isInsideLinkEditor(target)) return;
17776
- if (isInsideFloatingPanel(target)) return;
17777
16707
  if (target.closest("[data-ohw-form-toolbar]")) return;
17778
16708
  if (target.closest(
17779
16709
  '[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
17780
16710
  )) {
17781
16711
  return;
17782
16712
  }
17783
- if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
17784
- clearMediaSelectionRef.current();
17785
- }
17786
16713
  {
17787
16714
  const formEl = getFormElement(target);
17788
16715
  const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
@@ -17930,11 +16857,8 @@ function OhhwellsBridge() {
17930
16857
  if (isMediaEditable(editable) && !buttonOnMedia) {
17931
16858
  e.preventDefault();
17932
16859
  e.stopPropagation();
17933
- if (selectedMediaElRef.current === editable) {
17934
- postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
17935
- } else {
17936
- selectMediaElementRef.current(editable);
17937
- }
16860
+ aiSectionApiRef.current?.selectFromElement(editable);
16861
+ postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
17938
16862
  return;
17939
16863
  }
17940
16864
  const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
@@ -18053,12 +16977,10 @@ function OhhwellsBridge() {
18053
16977
  };
18054
16978
  const handleDblClick = (e) => {
18055
16979
  const target = e.target;
18056
- if (target.closest("[data-ohw-ai-review]")) return;
18057
16980
  if (target.closest("[data-ohw-toolbar]")) return;
18058
16981
  if (target.closest("[data-ohw-state-toggle]")) return;
18059
16982
  if (target.closest("[data-ohw-max-badge]")) return;
18060
16983
  if (isInsideLinkEditor(target)) return;
18061
- if (isInsideFloatingPanel(target)) return;
18062
16984
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
18063
16985
  return;
18064
16986
  }
@@ -18099,14 +17021,11 @@ function OhhwellsBridge() {
18099
17021
  setSiblingHintRects([]);
18100
17022
  return;
18101
17023
  }
18102
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
17024
+ if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || target.closest("[data-ohw-floating-panel]")) {
18103
17025
  hoveredItemElRef.current = null;
18104
17026
  setHoveredItemRect(null);
18105
17027
  hoveredNavContainerRef.current = null;
18106
17028
  setHoveredNavContainerRect(null);
18107
- siblingHintElRef.current = null;
18108
- setSiblingHintRect(null);
18109
- setSiblingHintRects([]);
18110
17029
  return;
18111
17030
  }
18112
17031
  {
@@ -18124,16 +17043,6 @@ function OhhwellsBridge() {
18124
17043
  return;
18125
17044
  }
18126
17045
  }
18127
- if (allowNavContainerHover) {
18128
- const socialsRow = isSocialsRow(target) ? target : null;
18129
- if (socialsRow && !getSocialItem(target) && selected2 !== socialsRow) {
18130
- hoveredNavContainerRef.current = socialsRow;
18131
- setHoveredNavContainerRect(socialsRow.getBoundingClientRect());
18132
- hoveredItemElRef.current = null;
18133
- setHoveredItemRect(null);
18134
- return;
18135
- }
18136
- }
18137
17046
  if (allowFooterLinksHover) {
18138
17047
  const navContainer = target.closest("[data-ohw-nav-container]");
18139
17048
  if (!navContainer) {
@@ -18219,12 +17128,13 @@ function OhhwellsBridge() {
18219
17128
  clearHrefKeyHover(hoverTarget);
18220
17129
  hoveredItemElRef.current = hoverTarget;
18221
17130
  setHoveredItemRect(hoverTarget.getBoundingClientRect());
18222
- } else if (!isInsideNavigationItem(editable) && hoverTarget !== selectedElRef.current) {
17131
+ } else if (!isInsideNavigationItem(editable)) {
18223
17132
  hoverTarget.setAttribute("data-ohw-hovered", "");
18224
17133
  if (editable.closest("footer") || editable.closest('[data-ohw-section="footer"]')) {
18225
17134
  hoveredNavContainerRef.current = null;
18226
17135
  setHoveredNavContainerRect(null);
18227
17136
  hoveredItemElRef.current = editable;
17137
+ setHoveredItemRect(editable.getBoundingClientRect());
18228
17138
  }
18229
17139
  }
18230
17140
  }
@@ -18521,7 +17431,7 @@ function OhhwellsBridge() {
18521
17431
  }
18522
17432
  };
18523
17433
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
18524
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
17434
+ if (linkPopoverOpenRef.current) {
18525
17435
  if (hoveredImageRef.current) {
18526
17436
  hoveredImageRef.current = null;
18527
17437
  hoveredImageHasTextOverlapRef.current = false;
@@ -18780,7 +17690,7 @@ function OhhwellsBridge() {
18780
17690
  }
18781
17691
  };
18782
17692
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
18783
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
17693
+ if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
18784
17694
  if (activeStateElRef.current) {
18785
17695
  activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
18786
17696
  activeStateElRef.current = null;
@@ -18817,35 +17727,6 @@ function OhhwellsBridge() {
18817
17727
  }
18818
17728
  }
18819
17729
  };
18820
- const probeSocialsRowAt = (clientX, clientY, fromParentViewport = false) => {
18821
- const wasSocialsRow = Boolean(hoveredNavContainerRef.current?.hasAttribute(SOCIALS_ROW_ATTR));
18822
- const clear = () => {
18823
- if (!wasSocialsRow) return false;
18824
- hoveredNavContainerRef.current = null;
18825
- setHoveredNavContainerRect(null);
18826
- return false;
18827
- };
18828
- if (linkPopoverOpenRef.current || toolbarVariantRef.current === "select-frame") return clear();
18829
- const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
18830
- const SLACK = 6;
18831
- for (const row of Array.from(document.querySelectorAll(`[${SOCIALS_ROW_ATTR}]`))) {
18832
- const rect = row.getBoundingClientRect();
18833
- const inside = x >= rect.left - SLACK && x <= rect.right + SLACK && y >= rect.top - SLACK && y <= rect.bottom + SLACK;
18834
- if (!inside) continue;
18835
- if (selectedElRef.current === row) return clear();
18836
- const overItem = listSocialItems(row).some((item) => {
18837
- const box = item.getBoundingClientRect();
18838
- return x >= box.left && x <= box.right && y >= box.top && y <= box.bottom;
18839
- });
18840
- if (overItem) return clear();
18841
- hoveredNavContainerRef.current = row;
18842
- setHoveredNavContainerRect(rect);
18843
- hoveredItemElRef.current = null;
18844
- setHoveredItemRect(null);
18845
- return true;
18846
- }
18847
- return clear();
18848
- };
18849
17730
  const probeSectionGapAt = (clientX, clientY, fromParentViewport = false) => {
18850
17731
  if (linkPopoverOpenRef.current) {
18851
17732
  if (hoveredGapRef.current) {
@@ -18855,9 +17736,7 @@ function OhhwellsBridge() {
18855
17736
  return;
18856
17737
  }
18857
17738
  const { y } = toProbeCoords(clientX, clientY, fromParentViewport);
18858
- const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
18859
- (el) => !el.hasAttribute("data-ohw-ai-template-hidden") && !el.hasAttribute("data-ohw-ai-removed") && !el.hasAttribute("data-ohw-ai-replaced-by") && el.getBoundingClientRect().height > 0
18860
- ).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
17739
+ const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
18861
17740
  const ZONE = 20;
18862
17741
  for (let i = 0; i < sections.length; i++) {
18863
17742
  const a = sections[i];
@@ -18886,7 +17765,8 @@ function OhhwellsBridge() {
18886
17765
  };
18887
17766
  const handleMouseMove = (e) => {
18888
17767
  const { clientX, clientY } = e;
18889
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
17768
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
17769
+ if (isOverEditorChrome(clientX, clientY)) {
18890
17770
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
18891
17771
  formHoverElRef.current = null;
18892
17772
  setFormHoverRect(null);
@@ -18894,15 +17774,8 @@ function OhhwellsBridge() {
18894
17774
  setHoveredItemRect(null);
18895
17775
  hoveredNavContainerRef.current = null;
18896
17776
  setHoveredNavContainerRect(null);
18897
- siblingHintElRef.current = null;
18898
- setSiblingHintRect(null);
18899
- setSiblingHintRects([]);
18900
- dismissImageHover();
18901
- clearImageHover();
18902
- setSectionGap(null);
18903
17777
  return;
18904
17778
  }
18905
- if (probeSocialsRowAt(clientX, clientY)) return;
18906
17779
  probeSectionGapAt(clientX, clientY);
18907
17780
  probeImageAt(clientX, clientY);
18908
17781
  probeHoverCardsAt(clientX, clientY);
@@ -18911,12 +17784,7 @@ function OhhwellsBridge() {
18911
17784
  if (e.data?.type !== "ow:pointer-sync") return;
18912
17785
  const { clientX, clientY } = e.data;
18913
17786
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
18914
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
18915
- dismissImageHover();
18916
- clearImageHover();
18917
- return;
18918
- }
18919
- if (probeSocialsRowAt(clientX, clientY)) return;
17787
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
18920
17788
  probeSectionGapAt(clientX, clientY);
18921
17789
  probeImageAt(clientX, clientY);
18922
17790
  probeHoverCardsAt(clientX, clientY);
@@ -19162,19 +18030,10 @@ function OhhwellsBridge() {
19162
18030
  if (e.data?.type !== "ow:hydrate") return;
19163
18031
  const content = e.data.content;
19164
18032
  if (!content) return;
19165
- if (typeof content[BRAND_KIT_KEY] === "string") {
19166
- brandKitRef.current = content[BRAND_KIT_KEY];
19167
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
19168
- }
19169
18033
  if (typeof content[AI_SECTIONS_KEY] === "string") {
19170
18034
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
19171
18035
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
19172
18036
  }
19173
- if (typeof content[STYLE_STORE_KEY] === "string") {
19174
- stylesRef.current = content[STYLE_STORE_KEY];
19175
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
19176
- }
19177
- applyBrandChrome(content);
19178
18037
  let sectionsJson = null;
19179
18038
  for (const [key, val] of Object.entries(content)) {
19180
18039
  if (key === "__ohw_sections") {
@@ -19184,9 +18043,6 @@ function OhhwellsBridge() {
19184
18043
  if (key === AI_SECTIONS_KEY) continue;
19185
18044
  if (key === LOGO_PLACEHOLDER_KEY) continue;
19186
18045
  if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
19187
- if (key === BRAND_KIT_KEY) continue;
19188
- if (key === STYLE_STORE_KEY) continue;
19189
- if (BRAND_CHROME_KEYS.has(key)) continue;
19190
18046
  if (applyVideoSettingNode(key, val)) continue;
19191
18047
  if (applyCarouselNode(key, val)) continue;
19192
18048
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -19283,21 +18139,12 @@ function OhhwellsBridge() {
19283
18139
  nodes: collectEditableNodes(editContentRef.current)
19284
18140
  });
19285
18141
  };
19286
- const clearInteractionChrome = () => {
19287
- deactivateRef.current();
19288
- deselectRef.current();
19289
- clearMediaSelectionRef.current();
19290
- };
19291
18142
  const handleAiApplyTree = (e) => {
19292
18143
  if (e.data?.type !== "ow:ai-apply-tree") return;
19293
18144
  const payload = e.data.payload;
19294
18145
  if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
19295
- clearInteractionChrome();
19296
18146
  const previous = aiSectionsRef.current;
19297
- const nextState = applyTreeToState(parseAiSectionsState(previous), {
19298
- ...payload,
19299
- path: payload.path ?? window.location.pathname
19300
- });
18147
+ const nextState = applyTreeToState(parseAiSectionsState(previous), payload);
19301
18148
  const nextValue = serializeAiSectionsState(nextState);
19302
18149
  aiSectionsRef.current = nextValue;
19303
18150
  applyAiSectionsToDom(nextState);
@@ -19317,7 +18164,6 @@ function OhhwellsBridge() {
19317
18164
  if (!sectionId || sectionId === "navbar" || sectionId === "footer") return;
19318
18165
  const exists = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
19319
18166
  if (!exists) return;
19320
- clearInteractionChrome();
19321
18167
  const previous = aiSectionsRef.current;
19322
18168
  const nextState = deleteSectionFromState(parseAiSectionsState(previous), sectionId);
19323
18169
  const nextValue = serializeAiSectionsState(nextState);
@@ -19333,58 +18179,14 @@ function OhhwellsBridge() {
19333
18179
  const handleAiSetSections = (e) => {
19334
18180
  if (e.data?.type !== "ow:ai-set-sections") return;
19335
18181
  const value = typeof e.data.value === "string" ? e.data.value : "";
19336
- clearInteractionChrome();
19337
18182
  aiSectionsRef.current = value;
19338
18183
  applyAiSectionsToDom(parseAiSectionsState(value));
19339
- applyStylesToDom(parseStyleStore(stylesRef.current));
19340
18184
  const restoredHeight = document.documentElement.scrollHeight;
19341
18185
  if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
19342
18186
  postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
19343
18187
  postAiSectionsChanged();
19344
18188
  };
19345
18189
  window.addEventListener("message", handleAiSetSections);
19346
- const handleMoveSection = (e) => {
19347
- if (e.data?.type !== "ow:move-section") return;
19348
- const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
19349
- const direction = e.data.direction === "up" || e.data.direction === "down" ? e.data.direction : null;
19350
- if (!instanceId || !direction) return;
19351
- const entries = moveSectionInstance(instanceId, direction, window.location.pathname);
19352
- if (!entries) return;
19353
- const orderJson = JSON.stringify(entries);
19354
- editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
19355
- postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
19356
- window.dispatchEvent(new Event("resize"));
19357
- };
19358
- window.addEventListener("message", handleMoveSection);
19359
- const handleAiSetBrand = (e) => {
19360
- if (e.data?.type !== "ow:ai-set-brand") return;
19361
- const value = typeof e.data.value === "string" ? e.data.value : "";
19362
- const previous = brandKitRef.current;
19363
- brandKitRef.current = value;
19364
- applyBrandToDom(parseBrandKit(value));
19365
- if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
19366
- applyStylesToDom(parseStyleStore(stylesRef.current));
19367
- postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
19368
- postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
19369
- };
19370
- window.addEventListener("message", handleAiSetBrand);
19371
- const handleAiSetStyles = (e) => {
19372
- if (e.data?.type !== "ow:ai-set-styles") return;
19373
- const value = typeof e.data.value === "string" ? e.data.value : "";
19374
- const previous = stylesRef.current;
19375
- stylesRef.current = value;
19376
- applyStylesToDom(parseStyleStore(value));
19377
- postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
19378
- postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
19379
- };
19380
- window.addEventListener("message", handleAiSetStyles);
19381
- const handleGetBrand = (e) => {
19382
- if (e.data?.type !== "ow:get-brand") return;
19383
- const template = deriveTemplateBrand();
19384
- const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
19385
- postToParentRef.current({ type: "ow:brand-value", value });
19386
- };
19387
- window.addEventListener("message", handleGetBrand);
19388
18190
  const handlePanelDragging = (e) => {
19389
18191
  if (e.data?.type !== "ow:panel-dragging") return;
19390
18192
  if (e.data.dragging) document.documentElement.setAttribute("data-ohw-panel-dragging", "");
@@ -19400,12 +18202,6 @@ function OhhwellsBridge() {
19400
18202
  closeLinkPopoverRef.current();
19401
18203
  return;
19402
18204
  }
19403
- if (floatingPanelOpenRef.current) {
19404
- setFloatingPanelRef.current(null);
19405
- deselectRef.current();
19406
- deactivateRef.current();
19407
- return;
19408
- }
19409
18205
  deselectRef.current();
19410
18206
  deactivateRef.current();
19411
18207
  };
@@ -19493,10 +18289,6 @@ function OhhwellsBridge() {
19493
18289
  const handleKeyDown = (e) => {
19494
18290
  if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
19495
18291
  if (e.key === "Escape" && document.querySelector("[data-ohw-more-menu]")) return;
19496
- if (e.key === "Escape" && selectedMediaElRef.current) {
19497
- clearMediaSelectionRef.current();
19498
- return;
19499
- }
19500
18292
  if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
19501
18293
  e.preventDefault();
19502
18294
  selectAllTextInEditable(activeElRef.current);
@@ -19656,12 +18448,6 @@ function OhhwellsBridge() {
19656
18448
  if (aiSectionsRef.current) {
19657
18449
  nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
19658
18450
  }
19659
- if (stylesRef.current) {
19660
- nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
19661
- }
19662
- if (brandKitRef.current) {
19663
- nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
19664
- }
19665
18451
  document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
19666
18452
  const formKey = formKeyOf(form);
19667
18453
  if (!formKey) return;
@@ -19679,12 +18465,8 @@ function OhhwellsBridge() {
19679
18465
  if (inserted) {
19680
18466
  const tracker = getSectionsTracker();
19681
18467
  postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
19682
- const reportHeight = () => {
19683
- const h = document.body.scrollHeight;
19684
- if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
19685
- };
19686
- reportHeight();
19687
- setTimeout(reportHeight, 500);
18468
+ const h = document.documentElement.scrollHeight;
18469
+ if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
19688
18470
  }
19689
18471
  };
19690
18472
  const handleSwitchSchedule = (e) => {
@@ -20071,23 +18853,19 @@ function OhhwellsBridge() {
20071
18853
  window.removeEventListener("message", handleAiApplyTree);
20072
18854
  window.removeEventListener("message", handleAiDeleteSection);
20073
18855
  window.removeEventListener("message", handleAiSetSections);
20074
- window.removeEventListener("message", handleMoveSection);
20075
- window.removeEventListener("message", handleAiSetBrand);
20076
- window.removeEventListener("message", handleAiSetStyles);
20077
- window.removeEventListener("message", handleGetBrand);
20078
18856
  window.removeEventListener("message", handlePanelDragging);
20079
18857
  window.removeEventListener("message", handleDeactivate);
18858
+ document.documentElement.removeAttribute("data-ohw-panel-dragging");
20080
18859
  window.removeEventListener("message", handleToastAction);
20081
18860
  window.removeEventListener("message", handleFormCount);
20082
18861
  window.removeEventListener("message", handleUiEscape);
20083
- document.documentElement.removeAttribute("data-ohw-panel-dragging");
20084
18862
  autoSaveTimers.current.forEach(clearTimeout);
20085
18863
  autoSaveTimers.current.clear();
20086
18864
  if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
20087
18865
  if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
20088
18866
  };
20089
18867
  }, [isEditMode, refreshStateRules]);
20090
- (0, import_react17.useEffect)(() => {
18868
+ (0, import_react16.useEffect)(() => {
20091
18869
  if (!isEditMode) return;
20092
18870
  const THRESHOLD = 10;
20093
18871
  const resolveWasSelected = (el) => {
@@ -20243,7 +19021,7 @@ function OhhwellsBridge() {
20243
19021
  unlockFooterDragInteraction();
20244
19022
  };
20245
19023
  }, [isEditMode]);
20246
- (0, import_react17.useEffect)(() => {
19024
+ (0, import_react16.useEffect)(() => {
20247
19025
  const handler = (e) => {
20248
19026
  if (e.data?.type !== "ow:request-schedule-config") return;
20249
19027
  const insertAfterVal = e.data.insertAfter;
@@ -20259,7 +19037,7 @@ function OhhwellsBridge() {
20259
19037
  window.addEventListener("message", handler);
20260
19038
  return () => window.removeEventListener("message", handler);
20261
19039
  }, [processConfigRequest]);
20262
- (0, import_react17.useEffect)(() => {
19040
+ (0, import_react16.useEffect)(() => {
20263
19041
  if (!isEditMode) return;
20264
19042
  document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
20265
19043
  el.removeAttribute("data-ohw-active-state");
@@ -20283,7 +19061,7 @@ function OhhwellsBridge() {
20283
19061
  postToParent2({
20284
19062
  type: "ow:ready",
20285
19063
  version: "1",
20286
- bridgeVersion: "0.1.68",
19064
+ bridgeVersion: "0.1.67",
20287
19065
  path: pathname,
20288
19066
  nodes: collectEditableNodes(editContentRef.current),
20289
19067
  sections
@@ -20295,13 +19073,13 @@ function OhhwellsBridge() {
20295
19073
  clearTimeout(timer);
20296
19074
  };
20297
19075
  }, [pathname, isEditMode, refreshStateRules, postToParent2]);
20298
- (0, import_react17.useEffect)(() => {
19076
+ (0, import_react16.useEffect)(() => {
20299
19077
  scrollToHashSectionWhenReady();
20300
19078
  const onHashChange = () => scrollToHashSectionWhenReady();
20301
19079
  window.addEventListener("hashchange", onHashChange);
20302
19080
  return () => window.removeEventListener("hashchange", onHashChange);
20303
19081
  }, [pathname]);
20304
- const handleCommand = (0, import_react17.useCallback)((cmd) => {
19082
+ const handleCommand = (0, import_react16.useCallback)((cmd) => {
20305
19083
  const el = activeElRef.current;
20306
19084
  const selBefore = window.getSelection();
20307
19085
  let savedOffsets = null;
@@ -20337,7 +19115,7 @@ function OhhwellsBridge() {
20337
19115
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
20338
19116
  refreshActiveCommandsRef.current();
20339
19117
  }, []);
20340
- (0, import_react17.useEffect)(() => {
19118
+ (0, import_react16.useEffect)(() => {
20341
19119
  const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
20342
19120
  if (!session || !logoSizeDraft) return;
20343
19121
  const onPanelAction = (e) => {
@@ -20375,7 +19153,7 @@ function OhhwellsBridge() {
20375
19153
  window.addEventListener("message", onPanelAction);
20376
19154
  return () => window.removeEventListener("message", onPanelAction);
20377
19155
  }, [floatingPanel, logoSizeDraft, editorViewport, persistLogoSizeDraft, closeFloatingPanelAndDeselect]);
20378
- const handleStateChange = (0, import_react17.useCallback)((state) => {
19156
+ const handleStateChange = (0, import_react16.useCallback)((state) => {
20379
19157
  if (!activeStateElRef.current) return;
20380
19158
  const el = activeStateElRef.current;
20381
19159
  if (state === "Default") {
@@ -20388,7 +19166,7 @@ function OhhwellsBridge() {
20388
19166
  }
20389
19167
  setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
20390
19168
  }, [deactivate]);
20391
- const reselectAfterLinkPopover = (0, import_react17.useCallback)(
19169
+ const reselectAfterLinkPopover = (0, import_react16.useCallback)(
20392
19170
  (hrefKey) => {
20393
19171
  requestAnimationFrame(() => {
20394
19172
  const el = resolveHrefKeyElement(hrefKey);
@@ -20397,7 +19175,7 @@ function OhhwellsBridge() {
20397
19175
  },
20398
19176
  [resolveHrefKeyElement]
20399
19177
  );
20400
- const closeLinkPopover = (0, import_react17.useCallback)(() => {
19178
+ const closeLinkPopover = (0, import_react16.useCallback)(() => {
20401
19179
  const session = linkPopoverSessionRef.current;
20402
19180
  addNavAfterAnchorRef.current = null;
20403
19181
  setLinkPopover(null);
@@ -20405,9 +19183,9 @@ function OhhwellsBridge() {
20405
19183
  reselectAfterLinkPopover(session.key);
20406
19184
  }
20407
19185
  }, [reselectAfterLinkPopover]);
20408
- const closeLinkPopoverRef = (0, import_react17.useRef)(closeLinkPopover);
19186
+ const closeLinkPopoverRef = (0, import_react16.useRef)(closeLinkPopover);
20409
19187
  closeLinkPopoverRef.current = closeLinkPopover;
20410
- const openLinkPopoverForActive = (0, import_react17.useCallback)(() => {
19188
+ const openLinkPopoverForActive = (0, import_react16.useCallback)(() => {
20411
19189
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
20412
19190
  if (!hrefCtx) return;
20413
19191
  bumpLinkPopoverGrace();
@@ -20418,7 +19196,7 @@ function OhhwellsBridge() {
20418
19196
  });
20419
19197
  deactivate();
20420
19198
  }, [deactivate]);
20421
- const openLinkPopoverForSelected = (0, import_react17.useCallback)(() => {
19199
+ const openLinkPopoverForSelected = (0, import_react16.useCallback)(() => {
20422
19200
  const anchor = selectedElRef.current;
20423
19201
  if (!anchor) return;
20424
19202
  const key = anchor.getAttribute("data-ohw-href-key");
@@ -20435,7 +19213,7 @@ function OhhwellsBridge() {
20435
19213
  });
20436
19214
  deselect();
20437
19215
  }, [deselect]);
20438
- const handleSelectParent = (0, import_react17.useCallback)(() => {
19216
+ const handleSelectParent = (0, import_react16.useCallback)(() => {
20439
19217
  const selected = selectedElRef.current;
20440
19218
  if (!selected) return;
20441
19219
  if (toolbarVariantRef.current === "select-frame") {
@@ -20462,7 +19240,7 @@ function OhhwellsBridge() {
20462
19240
  }
20463
19241
  deselectRef.current();
20464
19242
  }, []);
20465
- const handleDuplicateSelected = (0, import_react17.useCallback)(() => {
19243
+ const handleDuplicateSelected = (0, import_react16.useCallback)(() => {
20466
19244
  const selected = selectedElRef.current;
20467
19245
  if (!selected || !isNavigationItem2(selected)) return;
20468
19246
  const hrefKey = selected.getAttribute("data-ohw-href-key");
@@ -20578,7 +19356,7 @@ function OhhwellsBridge() {
20578
19356
  });
20579
19357
  }
20580
19358
  }, [postToParent2]);
20581
- const runPendingDeleteUndo = (0, import_react17.useCallback)(() => {
19359
+ const runPendingDeleteUndo = (0, import_react16.useCallback)(() => {
20582
19360
  const pending = pendingDeleteUndoRef.current;
20583
19361
  if (!pending) return false;
20584
19362
  pendingDeleteUndoRef.current = null;
@@ -20586,7 +19364,7 @@ function OhhwellsBridge() {
20586
19364
  enforceLinkHrefs();
20587
19365
  return true;
20588
19366
  }, []);
20589
- const handleDeleteSelected = (0, import_react17.useCallback)(() => {
19367
+ const handleDeleteSelected = (0, import_react16.useCallback)(() => {
20590
19368
  const selected = selectedElRef.current;
20591
19369
  if (!selected) return false;
20592
19370
  return deleteSelectedNavFooterItem({
@@ -20607,7 +19385,7 @@ function OhhwellsBridge() {
20607
19385
  }, [postToParent2]);
20608
19386
  handleDeleteSelectedRef.current = handleDeleteSelected;
20609
19387
  runPendingDeleteUndoRef.current = runPendingDeleteUndo;
20610
- const handleLinkPopoverSubmit = (0, import_react17.useCallback)(
19388
+ const handleLinkPopoverSubmit = (0, import_react16.useCallback)(
20611
19389
  (target) => {
20612
19390
  const session = linkPopoverSessionRef.current;
20613
19391
  if (!session) return;
@@ -20673,30 +19451,19 @@ function OhhwellsBridge() {
20673
19451
  const showEditLink = toolbarShowEditLink;
20674
19452
  const currentSections = sectionsByPath[pathname] ?? [];
20675
19453
  linkPopoverOpenRef.current = linkPopover !== null;
20676
- const handleMediaSelect = (0, import_react17.useCallback)((key) => {
20677
- const el = hoveredImageRef.current?.dataset.ohwKey === key ? hoveredImageRef.current : Array.from(document.querySelectorAll(MEDIA_SELECTOR)).find(
20678
- (m) => (m.dataset.ohwKey ?? "") === key
20679
- ) ?? null;
20680
- if (!el) return;
20681
- selectMediaElementRef.current(el);
20682
- }, []);
20683
- const handleMediaReplace = (0, import_react17.useCallback)(
19454
+ const handleMediaReplace = (0, import_react16.useCallback)(
20684
19455
  (key) => {
20685
- postToParent2({
20686
- type: "ow:image-pick",
20687
- key,
20688
- elementType: mediaHover?.elementType ?? selectedMedia?.elementType ?? "image"
20689
- });
19456
+ postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
20690
19457
  },
20691
- [postToParent2, mediaHover?.elementType, selectedMedia?.elementType]
19458
+ [postToParent2, mediaHover?.elementType]
20692
19459
  );
20693
- const handleEditCarousel = (0, import_react17.useCallback)(
19460
+ const handleEditCarousel = (0, import_react16.useCallback)(
20694
19461
  (key) => {
20695
19462
  postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
20696
19463
  },
20697
19464
  [postToParent2]
20698
19465
  );
20699
- const handleMediaFadeOutComplete = (0, import_react17.useCallback)((key) => {
19466
+ const handleMediaFadeOutComplete = (0, import_react16.useCallback)((key) => {
20700
19467
  setUploadingRects((prev) => {
20701
19468
  if (!(key in prev)) return prev;
20702
19469
  const next = { ...prev };
@@ -20704,7 +19471,7 @@ function OhhwellsBridge() {
20704
19471
  return next;
20705
19472
  });
20706
19473
  }, []);
20707
- const handleVideoSettingsChange = (0, import_react17.useCallback)(
19474
+ const handleVideoSettingsChange = (0, import_react16.useCallback)(
20708
19475
  (key, settings) => {
20709
19476
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
20710
19477
  const video = getVideoEl2(el);
@@ -20726,506 +19493,420 @@ function OhhwellsBridge() {
20726
19493
  },
20727
19494
  [postToParent2]
20728
19495
  );
20729
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
20730
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { id: "ohw-loader", suppressHydrationWarning: true, style: { ...OHW_LOADER_STYLE, display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(OhwLoaderSpinner, {}) }),
20731
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: OHW_LOADER_PREHYDRATE_SCRIPT } }),
20732
- bridgeRoot ? (0, import_react_dom4.createPortal)(
20733
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
20734
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
20735
- isEditMode && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
20736
- isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20737
- "div",
20738
- {
20739
- className: "pointer-events-none fixed z-2147483646",
20740
- style: { left: slot.left, top: slot.y, width: slot.width, height: 3, transform: "translateY(-50%)" },
20741
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20742
- DropIndicator,
20743
- {
20744
- direction: "horizontal",
20745
- state: activeSectionDropIndex === i ? "dragActive" : "dragIdle",
20746
- className: "!h-full !w-full"
20747
- }
20748
- )
20749
- },
20750
- `section-drop-${slot.insertIndex}-${i}`
20751
- )),
20752
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20753
- MediaOverlay,
20754
- {
20755
- hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
20756
- isUploading: true,
20757
- fadingOut,
20758
- onFadeOutComplete: handleMediaFadeOutComplete,
20759
- onReplace: handleMediaReplace
20760
- },
20761
- `uploading-${key}`
20762
- )),
20763
- mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20764
- MediaOverlay,
20765
- {
20766
- hover: mediaHover,
20767
- isUploading: false,
20768
- onReplace: handleMediaReplace,
20769
- onSelect: handleMediaSelect,
20770
- onVideoSettingsChange: handleVideoSettingsChange
20771
- }
20772
- ),
20773
- selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20774
- MediaOverlay,
20775
- {
20776
- hover: selectedMedia,
20777
- selected: true,
20778
- hovered: mediaHover?.key === selectedMedia.key,
20779
- isUploading: false,
20780
- onReplace: handleMediaReplace,
20781
- onSelect: handleMediaSelect,
20782
- onVideoSettingsChange: handleVideoSettingsChange
20783
- }
20784
- ),
20785
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
20786
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
20787
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
20788
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
20789
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20790
- "div",
20791
- {
20792
- className: "pointer-events-none fixed z-2147483646",
20793
- style: {
20794
- left: slot.left,
20795
- top: slot.top,
20796
- width: slot.width,
20797
- height: slot.height
20798
- },
20799
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20800
- DropIndicator,
20801
- {
20802
- direction: slot.direction,
20803
- state: activeFooterDropIndex === i ? "dragActive" : "dragIdle",
20804
- className: "!h-full !w-full"
20805
- }
20806
- )
20807
- },
20808
- `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
20809
- )),
20810
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20811
- "div",
20812
- {
20813
- className: "pointer-events-none fixed z-2147483646",
20814
- style: {
20815
- left: slot.left,
20816
- top: slot.top,
20817
- width: slot.width,
20818
- height: slot.height
20819
- },
20820
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20821
- DropIndicator,
20822
- {
20823
- direction: slot.direction,
20824
- state: activeNavDropIndex === i ? "dragActive" : "dragIdle",
20825
- className: "!h-full !w-full"
20826
- }
20827
- )
19496
+ return bridgeRoot ? (0, import_react_dom4.createPortal)(
19497
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
19498
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
19499
+ isEditMode && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
19500
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19501
+ MediaOverlay,
19502
+ {
19503
+ hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
19504
+ isUploading: true,
19505
+ fadingOut,
19506
+ onFadeOutComplete: handleMediaFadeOutComplete,
19507
+ onReplace: handleMediaReplace
19508
+ },
19509
+ `uploading-${key}`
19510
+ )),
19511
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19512
+ MediaOverlay,
19513
+ {
19514
+ hover: mediaHover,
19515
+ isUploading: false,
19516
+ onReplace: handleMediaReplace,
19517
+ onVideoSettingsChange: handleVideoSettingsChange
19518
+ }
19519
+ ),
19520
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
19521
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
19522
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
19523
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
19524
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19525
+ "div",
19526
+ {
19527
+ className: "pointer-events-none fixed z-2147483646",
19528
+ style: {
19529
+ left: slot.left,
19530
+ top: slot.top,
19531
+ width: slot.width,
19532
+ height: slot.height
20828
19533
  },
20829
- `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
20830
- )),
20831
- hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
20832
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
20833
- hoveredTextRect && !hoveredNavContainerRect && !hoveredItemRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
20834
- formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20835
- ItemInteractionLayer,
20836
- {
20837
- rect: formPickRect,
20838
- state: "active-top",
20839
- itemDragSurface: false,
20840
- toolbarAlign: "left",
20841
- chromeGap: 24,
20842
- toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
20843
- "div",
20844
- {
20845
- "data-ohw-form-toolbar": "",
20846
- className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
20847
- children: [
20848
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20849
- "button",
20850
- {
20851
- type: "button",
20852
- "aria-label": "Add field",
20853
- className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
20854
- onClick: () => setFieldTypePickerOpen((open) => !open),
20855
- "data-ohw-add-field": "",
20856
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Plus, { size: 15, "aria-hidden": true })
20857
- }
20858
- ),
20859
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20860
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
20861
- "button",
20862
- {
20863
- type: "button",
20864
- 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",
20865
- onClick: () => {
20866
- const form = formPickElRef.current;
20867
- if (!form) return;
20868
- postToParent2({
20869
- type: "ow:form-pick",
20870
- formKey: formKeyOf(form),
20871
- hasLongText: formHasLongText(form)
20872
- });
20873
- },
20874
- children: [
20875
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Settings, { size: 14, "aria-hidden": true }),
20876
- "Form settings",
20877
- formPickCount ? (
20878
- // Counter pill, per the design — not a text suffix.
20879
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20880
- "span",
20881
- {
20882
- "data-ohw-form-count": "",
20883
- 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",
20884
- children: formPickCount
20885
- }
20886
- )
20887
- ) : null
20888
- ]
20889
- }
20890
- ),
20891
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20892
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20893
- "button",
20894
- {
20895
- type: "button",
20896
- "aria-pressed": formViewState === state,
20897
- 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"),
20898
- onClick: () => {
20899
- const form = formPickElRef.current;
20900
- const key = form ? formKeyOf(form) : null;
20901
- if (!form || !key) return;
20902
- const initial = successInitialFor(form, key, editContentRef.current);
20903
- setFormViewState(form, key, state, initial);
20904
- setFormViewStateUi(state);
20905
- setFormPickRect(form.getBoundingClientRect());
20906
- if (state === "success") {
20907
- const successEl = form.querySelector(`[${SUCCESS_TEXT_ATTR}]`);
20908
- if (successEl) requestAnimationFrame(() => activateRef.current(successEl));
20909
- } else {
20910
- deactivateRef.current();
20911
- }
20912
- },
20913
- children: state
20914
- },
20915
- state
20916
- )) })
20917
- ]
20918
- }
20919
- )
20920
- }
20921
- ),
20922
- formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20923
- ItemInteractionLayer,
20924
- {
20925
- rect: formHoverRect,
20926
- state: "hover",
20927
- chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
20928
- }
20929
- ),
20930
- fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20931
- ItemInteractionLayer,
20932
- {
20933
- rect: fieldPickRect,
20934
- state: fieldDragging ? "dragging" : "active-top",
20935
- itemDragSurface: false,
20936
- toolbarAlign: "left",
20937
- chromeGap: 10,
20938
- showHandle: true,
20939
- dragHandleLabel: "Reorder field",
20940
- onDragHandleDragStart: handleFieldDragStart,
20941
- onDragHandleDragEnd: handleFieldDragEnd,
20942
- toolbar: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20943
- FormFieldToolbar,
20944
- {
20945
- type: fieldPickState.type,
20946
- required: fieldPickState.required,
20947
- onTypeChange: handleFieldTypeChange,
20948
- onRequiredToggle: handleFieldRequiredToggle,
20949
- onDuplicate: handleFieldDuplicate,
20950
- onDelete: handleFieldDelete
20951
- }
20952
- )
20953
- }
20954
- ),
20955
- fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20956
- "div",
20957
- {
20958
- className: "pointer-events-none fixed z-[2147483644]",
20959
- style: { top: slot.top, left: slot.left, width: slot.width },
20960
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20961
- DropIndicator,
20962
- {
20963
- direction: "horizontal",
20964
- state: fieldDropIndex === i ? "dragActive" : "dragIdle",
20965
- className: "!w-full"
20966
- }
20967
- )
19534
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19535
+ DropIndicator,
19536
+ {
19537
+ direction: slot.direction,
19538
+ state: activeFooterDropIndex === i ? "dragActive" : "dragIdle",
19539
+ className: "!h-full !w-full"
19540
+ }
19541
+ )
19542
+ },
19543
+ `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
19544
+ )),
19545
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19546
+ "div",
19547
+ {
19548
+ className: "pointer-events-none fixed z-2147483646",
19549
+ style: {
19550
+ left: slot.left,
19551
+ top: slot.top,
19552
+ width: slot.width,
19553
+ height: slot.height
20968
19554
  },
20969
- `field-drop-${i}`
20970
- )) : null,
20971
- fieldTypePickerOpen && formPickRect ? (() => {
20972
- const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
20973
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20974
- "div",
19555
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19556
+ DropIndicator,
20975
19557
  {
20976
- className: "pointer-events-none fixed z-[2147483645]",
20977
- style: {
20978
- top: toolbar ? toolbar.bottom + 6 : formPickRect.top + 16,
20979
- left: toolbar ? toolbar.left : formPickRect.left + 24
20980
- },
20981
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FieldTypePicker, { onPick: handleAddField })
19558
+ direction: slot.direction,
19559
+ state: activeNavDropIndex === i ? "dragActive" : "dragIdle",
19560
+ className: "!h-full !w-full"
20982
19561
  }
20983
- );
20984
- })() : null,
20985
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
20986
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20987
- FooterContainerChrome,
20988
- {
20989
- rect: toolbarRect,
20990
- onAdd: handleAddFooterColumn,
20991
- addDisabled: !canAddFooterColumn()
20992
- }
20993
- ),
20994
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20995
- ItemInteractionLayer,
20996
- {
20997
- rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
20998
- toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
20999
- elRef: glowElRef,
21000
- state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanelRect(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
21001
- showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
21002
- dragDisabled: reorderDragDisabled,
21003
- dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
21004
- onDragHandleDragStart: handleItemDragStart,
21005
- onDragHandleDragEnd: handleItemDragEnd,
21006
- onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
21007
- onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
21008
- itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
21009
- toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
21010
- ItemActionToolbar,
21011
- {
21012
- onEditLink: openLinkPopoverForSelected,
21013
- onStyle: () => {
21014
- const row = selectedElRef.current;
21015
- if (!row) return;
21016
- if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
21017
- else openSocialsDisplayPanel(row);
21018
- },
21019
- showStyle: selectedIsSocialsRow,
21020
- styleActive: floatingPanel?.kind === "socials-display",
21021
- onAddItem: handleAddChildItem,
21022
- onSelectParent: handleSelectParent,
21023
- onDuplicate: handleDuplicateSelected,
21024
- onDelete: handleDeleteSelected,
21025
- addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
21026
- const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
21027
- return row ? !canAddSocialItem(row) : false;
21028
- })(),
21029
- editLinkDisabled: false,
21030
- moreDisabled: false,
21031
- duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
21032
- showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
21033
- showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
21034
- selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
19562
+ )
19563
+ },
19564
+ `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
19565
+ )),
19566
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
19567
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
19568
+ hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
19569
+ formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19570
+ ItemInteractionLayer,
19571
+ {
19572
+ rect: formPickRect,
19573
+ state: "active-top",
19574
+ itemDragSurface: false,
19575
+ toolbarAlign: "left",
19576
+ chromeGap: 24,
19577
+ toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
19578
+ "div",
19579
+ {
19580
+ "data-ohw-form-toolbar": "",
19581
+ className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
19582
+ children: [
19583
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19584
+ "button",
19585
+ {
19586
+ type: "button",
19587
+ "aria-label": "Add field",
19588
+ className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
19589
+ onClick: () => setFieldTypePickerOpen((open) => !open),
19590
+ "data-ohw-add-field": "",
19591
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Plus, { size: 15, "aria-hidden": true })
19592
+ }
21035
19593
  ),
21036
- showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
21037
- dropdownOpen: navDropdownPreviewOpen,
21038
- onDropdownOpenChange: handleNavDropdownOpenChange,
21039
- headingVisible: footerHeadingVisible,
21040
- onHeadingVisibleChange: handleFooterHeadingVisibleChange
21041
- }
21042
- ) : void 0
21043
- }
21044
- ),
21045
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
21046
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
21047
- EditGlowChrome,
19594
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
19595
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
19596
+ "button",
19597
+ {
19598
+ type: "button",
19599
+ 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",
19600
+ onClick: () => {
19601
+ const form = formPickElRef.current;
19602
+ if (!form) return;
19603
+ postToParent2({
19604
+ type: "ow:form-pick",
19605
+ formKey: formKeyOf(form),
19606
+ hasLongText: formHasLongText(form)
19607
+ });
19608
+ },
19609
+ children: [
19610
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Settings, { size: 14, "aria-hidden": true }),
19611
+ "Form settings",
19612
+ formPickCount ? (
19613
+ // Counter pill, per the design — not a text suffix.
19614
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19615
+ "span",
19616
+ {
19617
+ "data-ohw-form-count": "",
19618
+ 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",
19619
+ children: formPickCount
19620
+ }
19621
+ )
19622
+ ) : null
19623
+ ]
19624
+ }
19625
+ ),
19626
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
19627
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19628
+ "button",
19629
+ {
19630
+ type: "button",
19631
+ "aria-pressed": formViewState === state,
19632
+ 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"),
19633
+ onClick: () => {
19634
+ const form = formPickElRef.current;
19635
+ const key = form ? formKeyOf(form) : null;
19636
+ if (!form || !key) return;
19637
+ const initial = successInitialFor(form, key, editContentRef.current);
19638
+ setFormViewState(form, key, state, initial);
19639
+ setFormViewStateUi(state);
19640
+ setFormPickRect(form.getBoundingClientRect());
19641
+ if (state === "success") {
19642
+ const successEl = form.querySelector(`[${SUCCESS_TEXT_ATTR}]`);
19643
+ if (successEl) requestAnimationFrame(() => activateRef.current(successEl));
19644
+ } else {
19645
+ deactivateRef.current();
19646
+ }
19647
+ },
19648
+ children: state
19649
+ },
19650
+ state
19651
+ )) })
19652
+ ]
19653
+ }
19654
+ )
19655
+ }
19656
+ ),
19657
+ formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19658
+ ItemInteractionLayer,
19659
+ {
19660
+ rect: formHoverRect,
19661
+ state: "hover",
19662
+ chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
19663
+ }
19664
+ ),
19665
+ fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19666
+ ItemInteractionLayer,
19667
+ {
19668
+ rect: fieldPickRect,
19669
+ state: fieldDragging ? "dragging" : "active-top",
19670
+ itemDragSurface: false,
19671
+ toolbarAlign: "left",
19672
+ chromeGap: 10,
19673
+ showHandle: true,
19674
+ dragHandleLabel: "Reorder field",
19675
+ onDragHandleDragStart: handleFieldDragStart,
19676
+ onDragHandleDragEnd: handleFieldDragEnd,
19677
+ toolbar: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19678
+ FormFieldToolbar,
21048
19679
  {
21049
- rect: toolbarRect,
21050
- elRef: glowElRef,
21051
- reorderHrefKey,
21052
- dragDisabled: reorderDragDisabled,
21053
- hideHandle: isItemDragging
19680
+ type: fieldPickState.type,
19681
+ required: fieldPickState.required,
19682
+ onTypeChange: handleFieldTypeChange,
19683
+ onRequiredToggle: handleFieldRequiredToggle,
19684
+ onDuplicate: handleFieldDuplicate,
19685
+ onDelete: handleFieldDelete
21054
19686
  }
21055
- ),
21056
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
21057
- FloatingToolbar,
19687
+ )
19688
+ }
19689
+ ),
19690
+ fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19691
+ "div",
19692
+ {
19693
+ className: "pointer-events-none fixed z-[2147483644]",
19694
+ style: { top: slot.top, left: slot.left, width: slot.width },
19695
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19696
+ DropIndicator,
21058
19697
  {
21059
- rect: toolbarRect,
21060
- parentScroll: parentScrollRef.current,
21061
- elRef: toolbarElRef,
21062
- onCommand: handleCommand,
21063
- activeCommands,
21064
- showEditLink,
21065
- onEditLink: openLinkPopoverForActive
19698
+ direction: "horizontal",
19699
+ state: fieldDropIndex === i ? "dragActive" : "dragIdle",
19700
+ className: "!w-full"
21066
19701
  }
21067
19702
  )
21068
- ] }),
21069
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
19703
+ },
19704
+ `field-drop-${i}`
19705
+ )) : null,
19706
+ fieldTypePickerOpen && formPickRect ? (() => {
19707
+ const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
19708
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
21070
19709
  "div",
21071
19710
  {
21072
- "data-ohw-max-badge": "",
19711
+ className: "pointer-events-none fixed z-[2147483645]",
21073
19712
  style: {
21074
- position: "fixed",
21075
- top: maxBadge.rect.bottom + 4,
21076
- left: maxBadge.rect.right,
21077
- transform: "translateX(-100%)",
21078
- zIndex: 2147483647,
21079
- background: maxBadge.current > maxBadge.max ? "#FEF2F2" : "#F5F5F4",
21080
- color: maxBadge.current > maxBadge.max ? "#DC2626" : "#78716C",
21081
- border: `1px solid ${maxBadge.current > maxBadge.max ? "#FECACA" : "#E7E5E4"}`,
21082
- borderRadius: 4,
21083
- padding: "2px 6px",
21084
- fontSize: 11,
21085
- fontWeight: 500,
21086
- pointerEvents: "none"
19713
+ top: toolbar ? toolbar.bottom + 6 : formPickRect.top + 16,
19714
+ left: toolbar ? toolbar.left : formPickRect.left + 24
21087
19715
  },
21088
- children: [
21089
- maxBadge.current,
21090
- "/",
21091
- maxBadge.max
21092
- ]
19716
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FieldTypePicker, { onPick: handleAddField })
21093
19717
  }
21094
- ),
21095
- toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
21096
- StateToggle,
19718
+ );
19719
+ })() : null,
19720
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
19721
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19722
+ FooterContainerChrome,
19723
+ {
19724
+ rect: toolbarRect,
19725
+ onAdd: handleAddFooterColumn,
19726
+ addDisabled: !canAddFooterColumn()
19727
+ }
19728
+ ),
19729
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19730
+ ItemInteractionLayer,
19731
+ {
19732
+ rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
19733
+ toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
19734
+ elRef: glowElRef,
19735
+ state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanelRect(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
19736
+ showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
19737
+ dragDisabled: reorderDragDisabled,
19738
+ dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
19739
+ onDragHandleDragStart: handleItemDragStart,
19740
+ onDragHandleDragEnd: handleItemDragEnd,
19741
+ onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
19742
+ onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
19743
+ itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
19744
+ toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19745
+ ItemActionToolbar,
19746
+ {
19747
+ onEditLink: openLinkPopoverForSelected,
19748
+ onStyle: () => {
19749
+ const row = selectedElRef.current;
19750
+ if (!row) return;
19751
+ if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
19752
+ else openSocialsDisplayPanel(row);
19753
+ },
19754
+ showStyle: selectedIsSocialsRow,
19755
+ styleActive: floatingPanel?.kind === "socials-display",
19756
+ onAddItem: handleAddChildItem,
19757
+ onSelectParent: handleSelectParent,
19758
+ onDuplicate: handleDuplicateSelected,
19759
+ onDelete: handleDeleteSelected,
19760
+ addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
19761
+ const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
19762
+ return row ? !canAddSocialItem(row) : false;
19763
+ })(),
19764
+ editLinkDisabled: false,
19765
+ moreDisabled: false,
19766
+ duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
19767
+ showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
19768
+ showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
19769
+ selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
19770
+ ),
19771
+ showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
19772
+ dropdownOpen: navDropdownPreviewOpen,
19773
+ onDropdownOpenChange: handleNavDropdownOpenChange,
19774
+ headingVisible: footerHeadingVisible,
19775
+ onHeadingVisibleChange: handleFooterHeadingVisibleChange
19776
+ }
19777
+ ) : void 0
19778
+ }
19779
+ ),
19780
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
19781
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19782
+ EditGlowChrome,
21097
19783
  {
21098
- rect: toggleState.rect,
21099
- activeState: toggleState.activeState,
21100
- states: toggleState.states,
21101
- onStateChange: handleStateChange
19784
+ rect: toolbarRect,
19785
+ elRef: glowElRef,
19786
+ reorderHrefKey,
19787
+ dragDisabled: reorderDragDisabled,
19788
+ hideHandle: isItemDragging
21102
19789
  }
21103
19790
  ),
21104
- sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
21105
- "div",
19791
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19792
+ FloatingToolbar,
21106
19793
  {
21107
- "data-ohw-section-insert-line": "",
21108
- className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
21109
- style: { top: sectionGap.y, transform: "translateY(-50%)" },
21110
- children: [
21111
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
21112
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
21113
- Badge,
21114
- {
21115
- 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",
21116
- onClick: () => {
21117
- window.parent.postMessage(
21118
- {
21119
- type: "ow:add-section",
21120
- insertAfter: sectionGap.insertAfter,
21121
- insertBefore: sectionGap.insertBefore
21122
- },
21123
- "*"
21124
- );
21125
- },
21126
- children: "Add Section"
21127
- }
21128
- ),
21129
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
21130
- ]
19794
+ rect: toolbarRect,
19795
+ parentScroll: parentScrollRef.current,
19796
+ elRef: toolbarElRef,
19797
+ onCommand: handleCommand,
19798
+ activeCommands,
19799
+ showEditLink,
19800
+ onEditLink: openLinkPopoverForActive
21131
19801
  }
21132
- ),
21133
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
21134
- LinkPopover,
21135
- {
21136
- panelRef: linkPopoverPanelRef,
21137
- portalContainer: dialogPortalContainer,
21138
- open: true,
21139
- mode: linkPopover.mode ?? "edit",
21140
- pages: sitePages,
21141
- sections: currentSections,
21142
- sectionsByPath,
21143
- initialTarget: linkPopover.target,
21144
- existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
21145
- onClose: closeLinkPopover,
21146
- onSubmit: handleLinkPopoverSubmit
19802
+ )
19803
+ ] }),
19804
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
19805
+ "div",
19806
+ {
19807
+ "data-ohw-max-badge": "",
19808
+ style: {
19809
+ position: "fixed",
19810
+ top: maxBadge.rect.bottom + 4,
19811
+ left: maxBadge.rect.right,
19812
+ transform: "translateX(-100%)",
19813
+ zIndex: 2147483647,
19814
+ background: maxBadge.current > maxBadge.max ? "#FEF2F2" : "#F5F5F4",
19815
+ color: maxBadge.current > maxBadge.max ? "#DC2626" : "#78716C",
19816
+ border: `1px solid ${maxBadge.current > maxBadge.max ? "#FECACA" : "#E7E5E4"}`,
19817
+ borderRadius: 4,
19818
+ padding: "2px 6px",
19819
+ fontSize: 11,
19820
+ fontWeight: 500,
19821
+ pointerEvents: "none"
21147
19822
  },
21148
- linkPopover.key
21149
- ) : null,
21150
- floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
21151
- FloatingPanel,
21152
- {
21153
- open: true,
21154
- title: floatingPanel.title,
21155
- context: floatingPanel.context,
21156
- position: floatingPanelPos,
21157
- onPositionChange: setFloatingPanelPos,
21158
- parentScroll: parentScrollSnap ?? parentScrollRef.current,
21159
- onClose: closeFloatingPanelOnly,
21160
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
21161
- SocialsDisplayPanel,
19823
+ children: [
19824
+ maxBadge.current,
19825
+ "/",
19826
+ maxBadge.max
19827
+ ]
19828
+ }
19829
+ ),
19830
+ toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19831
+ StateToggle,
19832
+ {
19833
+ rect: toggleState.rect,
19834
+ activeState: toggleState.activeState,
19835
+ states: toggleState.states,
19836
+ onStateChange: handleStateChange
19837
+ }
19838
+ ),
19839
+ sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
19840
+ "div",
19841
+ {
19842
+ "data-ohw-section-insert-line": "",
19843
+ className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
19844
+ style: { top: sectionGap.y, transform: "translateY(-50%)" },
19845
+ children: [
19846
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
19847
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19848
+ Badge,
21162
19849
  {
21163
- display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
21164
- onChange: (next) => {
21165
- changeSocialsDisplay(floatingPanel.row, next);
21166
- setFloatingPanel({ ...floatingPanel });
21167
- }
19850
+ 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",
19851
+ onClick: () => {
19852
+ window.parent.postMessage(
19853
+ {
19854
+ type: "ow:add-section",
19855
+ insertAfter: sectionGap.insertAfter,
19856
+ insertBefore: sectionGap.insertBefore
19857
+ },
19858
+ "*"
19859
+ );
19860
+ },
19861
+ children: "Add Section"
21168
19862
  }
21169
- )
21170
- }
21171
- ) : null
21172
- ] }),
21173
- bridgeRoot
21174
- ) : null
21175
- ] });
21176
- }
21177
-
21178
- // src/ui/EmptySection.tsx
21179
- var import_link = __toESM(require("next/link"), 1);
21180
- var import_jsx_runtime34 = require("react/jsx-runtime");
21181
- function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
21182
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
21183
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
21184
- "p",
21185
- {
21186
- style: {
21187
- fontFamily: "var(--brand-font-body)",
21188
- fontSize: "0.75rem",
21189
- fontWeight: 500,
21190
- letterSpacing: "0.15em",
21191
- textTransform: "uppercase",
21192
- color: "var(--brand-accent)",
21193
- marginBottom: "1.5rem"
21194
- },
21195
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_link.default, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
21196
- }
21197
- ),
21198
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
21199
- "h1",
21200
- {
21201
- style: {
21202
- fontFamily: "var(--brand-font-heading)",
21203
- fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
21204
- lineHeight: 1.1,
21205
- letterSpacing: "-0.025em",
21206
- color: "var(--brand-text)",
21207
- marginBottom: "1rem"
21208
- },
21209
- ...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
21210
- children: title
21211
- }
21212
- ),
21213
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
21214
- "p",
21215
- {
21216
- style: {
21217
- fontFamily: "var(--brand-font-body)",
21218
- fontSize: "1rem",
21219
- lineHeight: 1.7,
21220
- fontWeight: 300,
21221
- color: "var(--brand-text-muted)",
21222
- maxWidth: "340px"
19863
+ ),
19864
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
19865
+ ]
19866
+ }
19867
+ ),
19868
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19869
+ LinkPopover,
19870
+ {
19871
+ panelRef: linkPopoverPanelRef,
19872
+ portalContainer: dialogPortalContainer,
19873
+ open: true,
19874
+ mode: linkPopover.mode ?? "edit",
19875
+ pages: sitePages,
19876
+ sections: currentSections,
19877
+ sectionsByPath,
19878
+ initialTarget: linkPopover.target,
19879
+ existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
19880
+ onClose: closeLinkPopover,
19881
+ onSubmit: handleLinkPopoverSubmit
21223
19882
  },
21224
- ...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
21225
- children: "This page doesn't have any content yet."
21226
- }
21227
- )
21228
- ] });
19883
+ linkPopover.key
19884
+ ) : null,
19885
+ floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19886
+ FloatingPanel,
19887
+ {
19888
+ open: true,
19889
+ title: floatingPanel.title,
19890
+ context: floatingPanel.context,
19891
+ position: floatingPanelPos,
19892
+ onPositionChange: setFloatingPanelPos,
19893
+ parentScroll: parentScrollSnap ?? parentScrollRef.current,
19894
+ onClose: closeFloatingPanelOnly,
19895
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19896
+ SocialsDisplayPanel,
19897
+ {
19898
+ display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
19899
+ onChange: (next) => {
19900
+ changeSocialsDisplay(floatingPanel.row, next);
19901
+ setFloatingPanel({ ...floatingPanel });
19902
+ }
19903
+ }
19904
+ )
19905
+ }
19906
+ ) : null
19907
+ ] }),
19908
+ bridgeRoot
19909
+ ) : null;
21229
19910
  }
21230
19911
  // Annotate the CommonJS export names for ESM import in node:
21231
19912
  0 && (module.exports = {
@@ -21244,7 +19925,6 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
21244
19925
  DropdownMenuItem,
21245
19926
  DropdownMenuSeparator,
21246
19927
  DropdownMenuTrigger,
21247
- EmptySection,
21248
19928
  ItemActionToolbar,
21249
19929
  ItemInteractionLayer,
21250
19930
  LinkEditorPanel,