@ohhwells/bridge 0.1.66-next.192 → 0.1.66

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
  {
@@ -7755,9 +7327,6 @@ var import_lucide_react7 = require("lucide-react");
7755
7327
 
7756
7328
  // src/lib/sections.ts
7757
7329
  var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
7758
- function isChromeSection(el) {
7759
- return el.matches("header, nav, footer, aside");
7760
- }
7761
7330
  function titleCaseSectionId(id) {
7762
7331
  return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
7763
7332
  }
@@ -7768,8 +7337,6 @@ function parseSectionsFromRoot(root) {
7768
7337
  const id = el.getAttribute("data-ohw-section") ?? "";
7769
7338
  if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
7770
7339
  if (el.parentElement?.closest("[data-ohw-section]")) continue;
7771
- if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
7772
- continue;
7773
7340
  seen.add(id);
7774
7341
  const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
7775
7342
  sections.push({ id, label });
@@ -7787,12 +7354,8 @@ function parseSectionsFromHtml(html) {
7787
7354
 
7788
7355
  // src/ui/ai-section/AiSectionOverlay.tsx
7789
7356
  var import_jsx_runtime17 = require("react/jsx-runtime");
7790
- function findSectionElement(instanceId) {
7791
- const escaped = CSS.escape(instanceId);
7792
- return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
7793
- }
7794
- function readRect(instanceId) {
7795
- const el = findSectionElement(instanceId);
7357
+ function readRect(sectionId) {
7358
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7796
7359
  if (!el) return null;
7797
7360
  const r2 = el.getBoundingClientRect();
7798
7361
  if (r2.width <= 0 || r2.height <= 0) return null;
@@ -7815,7 +7378,7 @@ function useLiveSectionRect(sectionId) {
7815
7378
  const opts = { capture: true, passive: true };
7816
7379
  window.addEventListener("scroll", update, opts);
7817
7380
  window.addEventListener("resize", update);
7818
- const el = findSectionElement(sectionId);
7381
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7819
7382
  const ro = el ? new ResizeObserver(update) : null;
7820
7383
  if (el && ro) ro.observe(el);
7821
7384
  const interval = setInterval(update, 500);
@@ -7828,14 +7391,6 @@ function useLiveSectionRect(sectionId) {
7828
7391
  }, [sectionId]);
7829
7392
  return rect;
7830
7393
  }
7831
- function computeSectionBoundaryFlags(instanceId) {
7832
- const topLevel = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
7833
- (el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
7834
- );
7835
- const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
7836
- if (index === -1) return { isFirst: true, isLast: true };
7837
- return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
7838
- }
7839
7394
  var PRIMARY2 = "#0885FE";
7840
7395
  function edgeAwareRadius(rect) {
7841
7396
  const container = window.innerWidth <= 480 ? 16 : 24;
@@ -7909,7 +7464,6 @@ function AiSectionOverlay({
7909
7464
  }) {
7910
7465
  const [selectedId, setSelectedId] = (0, import_react8.useState)(null);
7911
7466
  const [reviewId, setReviewId] = (0, import_react8.useState)(null);
7912
- const [reviewButtonsHidden, setReviewButtonsHidden] = (0, import_react8.useState)(false);
7913
7467
  const reviewIdRef = (0, import_react8.useRef)(null);
7914
7468
  reviewIdRef.current = reviewId;
7915
7469
  const selectedIdRef = (0, import_react8.useRef)(null);
@@ -7918,7 +7472,7 @@ function AiSectionOverlay({
7918
7472
  (el) => {
7919
7473
  postToParent2({
7920
7474
  type: "ow:section-selected",
7921
- sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
7475
+ sectionId: el?.dataset.ohwSection ?? null,
7922
7476
  sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
7923
7477
  });
7924
7478
  },
@@ -7927,7 +7481,7 @@ function AiSectionOverlay({
7927
7481
  const selectFromElement = (0, import_react8.useCallback)(
7928
7482
  (el, options) => {
7929
7483
  const sectionEl = el?.closest("[data-ohw-section]") ?? null;
7930
- const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
7484
+ const id = sectionEl?.dataset.ohwSection ?? null;
7931
7485
  if (id === selectedIdRef.current) return;
7932
7486
  setSelectedId(id);
7933
7487
  if (options?.report !== false) report(sectionEl);
@@ -7968,10 +7522,9 @@ function AiSectionOverlay({
7968
7522
  }
7969
7523
  const found = readRect(sectionId) != null;
7970
7524
  setReviewId(found ? sectionId : null);
7971
- setReviewButtonsHidden(e.data.hideButtons === true);
7972
7525
  postToParent2({ type: "ow:ai-review-started", sectionId, found });
7973
7526
  if (found) {
7974
- document.querySelector(`[data-ohw-instance="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
7527
+ document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
7975
7528
  }
7976
7529
  }
7977
7530
  };
@@ -7990,7 +7543,7 @@ function AiSectionOverlay({
7990
7543
  return;
7991
7544
  }
7992
7545
  const sec = t.closest("[data-ohw-section]");
7993
- setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
7546
+ setHoveredId(sec?.dataset.ohwSection ?? null);
7994
7547
  };
7995
7548
  const onLeave = () => setHoveredId(null);
7996
7549
  document.addEventListener("mousemove", onMove, { passive: true });
@@ -8022,30 +7575,9 @@ function AiSectionOverlay({
8022
7575
  },
8023
7576
  [postToParent2]
8024
7577
  );
8025
- const activeSelectionId = reviewId ? null : selectedId;
8026
- const selectionRect = useLiveSectionRect(activeSelectionId);
7578
+ const selectionRect = useLiveSectionRect(reviewId ? null : selectedId);
8027
7579
  const reviewRect = useLiveSectionRect(reviewId);
8028
7580
  const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
8029
- (0, import_react8.useEffect)(() => {
8030
- const selectedEl = activeSelectionId ? findSectionElement(activeSelectionId) : null;
8031
- if (!activeSelectionId || !selectionRect || selectedEl && isChromeSection(selectedEl)) {
8032
- postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
8033
- return;
8034
- }
8035
- const { isFirst, isLast } = computeSectionBoundaryFlags(activeSelectionId);
8036
- postToParent2({
8037
- type: "ow:section-rect",
8038
- instanceId: activeSelectionId,
8039
- rect: {
8040
- top: selectionRect.top + window.scrollY,
8041
- left: selectionRect.left + window.scrollX,
8042
- width: selectionRect.width,
8043
- height: selectionRect.height
8044
- },
8045
- isFirst,
8046
- isLast
8047
- });
8048
- }, [activeSelectionId, selectionRect, postToParent2]);
8049
7581
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
8050
7582
  hoverRect && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
8051
7583
  "div",
@@ -8096,16 +7628,13 @@ function AiSectionOverlay({
8096
7628
  border: `2px solid ${PRIMARY2}`,
8097
7629
  borderRadius: edgeAwareRadius(reviewRect),
8098
7630
  zIndex: 2147483200,
8099
- // The veil itself: swallows clicks so the section stays locked until decided. This
8100
- // stopPropagation only guards the bubble phase; the bridge's capture-phase click
8101
- // handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
8102
- // Accept/Discard resolves to the media beneath and opens the file picker.
7631
+ // The veil itself: swallows clicks so the section stays locked until decided.
8103
7632
  background: "rgba(8, 133, 254, 0.04)",
8104
7633
  pointerEvents: "auto",
8105
7634
  cursor: "default"
8106
7635
  },
8107
7636
  onClick: (e) => e.stopPropagation(),
8108
- children: !reviewButtonsHidden && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
7637
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
8109
7638
  "div",
8110
7639
  {
8111
7640
  style: {
@@ -8130,58 +7659,6 @@ function AiSectionOverlay({
8130
7659
 
8131
7660
  // src/lib/section-instances.ts
8132
7661
  var SECTION_ORDER_KEY = "__ohw_section_order";
8133
- function topLevelSections() {
8134
- return Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
8135
- (el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
8136
- );
8137
- }
8138
- function instanceIdOf(el) {
8139
- return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
8140
- }
8141
- function planSectionMove(instanceId, targetIndex, currentPath) {
8142
- const sections = topLevelSections();
8143
- const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
8144
- if (index === -1) return null;
8145
- const dragged = sections[index];
8146
- const others = sections.filter((_, i) => i !== index);
8147
- const clamped = Math.max(0, Math.min(targetIndex, others.length));
8148
- const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
8149
- return reordered.map((el, order) => ({
8150
- instanceId: instanceIdOf(el),
8151
- type: el.getAttribute("data-ohw-section") ?? "",
8152
- order,
8153
- pagePath: currentPath
8154
- }));
8155
- }
8156
- function moveSectionInstance(instanceId, direction, currentPath) {
8157
- const sections = topLevelSections();
8158
- const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
8159
- if (index === -1) return null;
8160
- const siblingIndex = direction === "up" ? index - 1 : index + 1;
8161
- if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
8162
- const entries = planSectionMove(instanceId, siblingIndex, currentPath);
8163
- if (!entries) return null;
8164
- applyPersistedOrder(entries);
8165
- return entries;
8166
- }
8167
- function applyPersistedOrder(entries) {
8168
- if (entries.length === 0) return;
8169
- const sections = topLevelSections();
8170
- if (sections.length === 0) return;
8171
- const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
8172
- const ordered = [...sections].sort((a, b) => {
8173
- const aOrder = orderIndex.get(instanceIdOf(a));
8174
- const bOrder = orderIndex.get(instanceIdOf(b));
8175
- if (aOrder === void 0 && bOrder === void 0) return 0;
8176
- if (aOrder === void 0) return 1;
8177
- if (bOrder === void 0) return -1;
8178
- return aOrder - bOrder;
8179
- });
8180
- const parent = sections[0].parentElement;
8181
- if (!parent) return;
8182
- const anchor = sections[sections.length - 1].nextSibling;
8183
- ordered.forEach((el) => parent.insertBefore(el, anchor));
8184
- }
8185
7662
  function getPageSectionOrderEntries(raw, currentPath) {
8186
7663
  if (!raw) return [];
8187
7664
  try {
@@ -8219,7 +7696,6 @@ function initSectionInstancesFromContent(content, currentPath) {
8219
7696
  rekeySectionSubtree(clone, entry.instanceId);
8220
7697
  original.insertAdjacentElement("afterend", clone);
8221
7698
  }
8222
- applyPersistedOrder(entries);
8223
7699
  }
8224
7700
 
8225
7701
  // src/OhhwellsBridge.tsx
@@ -12352,7 +11828,6 @@ function readLogoSizeState(content, placement) {
12352
11828
  function getLogoElement(el) {
12353
11829
  const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
12354
11830
  if (marked) return marked;
12355
- if (el.closest('[data-ohw-editable="icon"]')) return null;
12356
11831
  const root = el.closest("nav, [data-ohw-nav-root], footer");
12357
11832
  if (!root) return null;
12358
11833
  const anchor = el.closest("a");
@@ -12601,127 +12076,16 @@ function FloatingPanel({
12601
12076
  );
12602
12077
  }
12603
12078
 
12604
- // src/ui/logo-size-panel.tsx
12605
- var import_lucide_react15 = require("lucide-react");
12606
- var import_jsx_runtime28 = require("react/jsx-runtime");
12607
- function SizeSlider({
12608
- value,
12609
- onChange
12610
- }) {
12611
- const pct = (value - LOGO_SIZE_MIN) / (LOGO_SIZE_MAX - LOGO_SIZE_MIN) * 100;
12612
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full flex-col gap-3", children: [
12613
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full items-center gap-2 text-sm font-medium leading-5", children: [
12614
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "min-w-0 flex-1 text-foreground", children: "Size" }),
12615
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "shrink-0 whitespace-nowrap text-muted-foreground", children: [
12616
- value,
12617
- " px"
12618
- ] })
12619
- ] }),
12620
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "relative h-2 w-full rounded-full bg-primary-50", children: [
12621
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12622
- "div",
12623
- {
12624
- className: "absolute inset-y-0 left-0 rounded-full bg-primary",
12625
- style: { width: `${pct}%` }
12626
- }
12627
- ),
12628
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12629
- "input",
12630
- {
12631
- type: "range",
12632
- min: LOGO_SIZE_MIN,
12633
- max: LOGO_SIZE_MAX,
12634
- step: 1,
12635
- value,
12636
- "aria-label": "Logo size",
12637
- className: cn(
12638
- "absolute inset-0 h-full w-full cursor-pointer appearance-none bg-transparent",
12639
- "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:size-5",
12640
- "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2",
12641
- "[&::-webkit-slider-thumb]:border-primary [&::-webkit-slider-thumb]:bg-background",
12642
- "[&::-moz-range-thumb]:size-5 [&::-moz-range-thumb]:rounded-full",
12643
- "[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary",
12644
- "[&::-moz-range-thumb]:bg-background"
12645
- ),
12646
- onChange: (e) => onChange(Number(e.target.value))
12647
- }
12648
- )
12649
- ] })
12650
- ] });
12651
- }
12652
- function LogoSizePanel({
12653
- viewport,
12654
- sizePx,
12655
- mobileFollowing = true,
12656
- onSizeChange,
12657
- onCustomizeMobile,
12658
- onResetMobile,
12659
- onUpdateEverywhere,
12660
- className
12661
- }) {
12662
- const showFollowing = viewport === "mobile" && mobileFollowing;
12663
- const showMobileSlider = viewport === "mobile" && !mobileFollowing;
12664
- const showDesktopSlider = viewport === "desktop";
12665
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: cn("flex w-full flex-col gap-4", className), children: [
12666
- showFollowing ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
12667
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-start gap-1", children: [
12668
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react15.Link, { size: 16, className: "mt-0.5 shrink-0 text-foreground", "aria-hidden": true }),
12669
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-sm font-semibold leading-5 text-foreground", children: "Following desktop size" })
12670
- ] }),
12671
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-sm leading-5 text-muted-foreground", children: "Mobile uses the desktop size until you customize it. Change the desktop size and it follows automatically." }),
12672
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12673
- Button,
12674
- {
12675
- type: "button",
12676
- variant: "outline",
12677
- size: "sm",
12678
- className: "h-9 w-full min-w-0 cursor-pointer",
12679
- onClick: onCustomizeMobile,
12680
- children: "Customize for mobile"
12681
- }
12682
- )
12683
- ] }) : null,
12684
- showDesktopSlider || showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(SizeSlider, { value: sizePx, onChange: onSizeChange }) : null,
12685
- showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12686
- Button,
12687
- {
12688
- type: "button",
12689
- variant: "outline",
12690
- size: "sm",
12691
- className: "h-9 w-full min-w-0 cursor-pointer",
12692
- onClick: onResetMobile,
12693
- children: "Reset to desktop size"
12694
- }
12695
- ) : null,
12696
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "h-px w-full bg-border", role: "separator" }),
12697
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
12698
- Button,
12699
- {
12700
- type: "button",
12701
- variant: "outline",
12702
- size: "sm",
12703
- className: "h-9 w-full min-w-0 cursor-pointer gap-1",
12704
- onClick: onUpdateEverywhere,
12705
- children: [
12706
- "Update logo everywhere",
12707
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react15.ArrowUpRight, { size: 16, "aria-hidden": true })
12708
- ]
12709
- }
12710
- ),
12711
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-sm leading-5 text-muted-foreground", children: "Matches the right version to your background." })
12712
- ] });
12713
- }
12714
-
12715
12079
  // src/ui/socials-display-panel.tsx
12716
- var import_jsx_runtime29 = require("react/jsx-runtime");
12080
+ var import_jsx_runtime28 = require("react/jsx-runtime");
12717
12081
  function DisplaySwitch({
12718
12082
  label,
12719
12083
  checked,
12720
12084
  disabled,
12721
12085
  onChange
12722
12086
  }) {
12723
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
12724
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12087
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
12088
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12725
12089
  "span",
12726
12090
  {
12727
12091
  className: cn(
@@ -12731,7 +12095,7 @@ function DisplaySwitch({
12731
12095
  children: label
12732
12096
  }
12733
12097
  ),
12734
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12098
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12735
12099
  "button",
12736
12100
  {
12737
12101
  type: "button",
@@ -12745,7 +12109,7 @@ function DisplaySwitch({
12745
12109
  checked ? "bg-primary" : "bg-primary-50",
12746
12110
  disabled ? "cursor-default opacity-50" : "cursor-pointer"
12747
12111
  ),
12748
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12112
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12749
12113
  "span",
12750
12114
  {
12751
12115
  className: cn(
@@ -12759,8 +12123,8 @@ function DisplaySwitch({
12759
12123
  ] });
12760
12124
  }
12761
12125
  function SocialsDisplayPanel({ display, onChange, className }) {
12762
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: cn("flex w-full flex-col gap-3", className), children: [
12763
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12126
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: cn("flex w-full flex-col gap-3", className), children: [
12127
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12764
12128
  DisplaySwitch,
12765
12129
  {
12766
12130
  label: "Text",
@@ -12769,7 +12133,7 @@ function SocialsDisplayPanel({ display, onChange, className }) {
12769
12133
  onChange: (text) => onChange({ ...display, text })
12770
12134
  }
12771
12135
  ),
12772
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12136
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12773
12137
  DisplaySwitch,
12774
12138
  {
12775
12139
  label: "Icon",
@@ -13328,414 +12692,87 @@ function useNavItemDrag({
13328
12692
  };
13329
12693
  }
13330
12694
 
13331
- // src/useSectionDrag.ts
13332
- var import_react15 = require("react");
12695
+ // src/ui/footer-container-chrome.tsx
12696
+ var import_lucide_react15 = require("lucide-react");
12697
+ var import_jsx_runtime29 = require("react/jsx-runtime");
12698
+ function FooterContainerChrome({
12699
+ rect,
12700
+ onAdd,
12701
+ addDisabled = false
12702
+ }) {
12703
+ const chromeGap = 6;
12704
+ const buttonMargin = 7;
12705
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12706
+ "div",
12707
+ {
12708
+ "data-ohw-footer-container-chrome": "",
12709
+ "data-ohw-bridge": "",
12710
+ className: "pointer-events-none fixed z-[2147483647]",
12711
+ style: {
12712
+ top: rect.top - chromeGap,
12713
+ left: rect.left - chromeGap,
12714
+ width: rect.width + chromeGap * 2,
12715
+ height: rect.height + chromeGap * 2
12716
+ },
12717
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(Tooltip, { children: [
12718
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
12719
+ "button",
12720
+ {
12721
+ type: "button",
12722
+ "data-ohw-footer-add-button": "",
12723
+ disabled: addDisabled,
12724
+ 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",
12725
+ style: { top: chromeGap - buttonMargin },
12726
+ "aria-label": "Add item",
12727
+ onMouseDown: (e) => {
12728
+ e.preventDefault();
12729
+ e.stopPropagation();
12730
+ },
12731
+ onClick: (e) => {
12732
+ e.preventDefault();
12733
+ e.stopPropagation();
12734
+ if (addDisabled) return;
12735
+ onAdd();
12736
+ },
12737
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12738
+ }
12739
+ ) }),
12740
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
12741
+ ] })
12742
+ }
12743
+ ) });
12744
+ }
13333
12745
 
13334
- // src/lib/section-dnd.ts
13335
- function isFooterSection(el) {
13336
- return el.dataset.ohwSection === "footer";
12746
+ // src/lib/carousel.ts
12747
+ var import_react15 = require("react");
12748
+ var CAROUSEL_ATTR = "data-ohw-carousel";
12749
+ var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
12750
+ var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
12751
+ var CAROUSEL_EVENT = "ohw:carousel-change";
12752
+ function listCarouselKeys() {
12753
+ const keys = /* @__PURE__ */ new Set();
12754
+ document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
12755
+ const key = el.getAttribute("data-ohw-key");
12756
+ if (key) keys.add(key);
12757
+ });
12758
+ return [...keys];
13337
12759
  }
13338
- function buildSectionDropSlots(draggedInstanceId) {
13339
- const sections = topLevelSections().filter(
13340
- (el) => instanceIdOf(el) !== draggedInstanceId && !isFooterSection(el)
12760
+ function containersForKey(key) {
12761
+ return Array.from(
12762
+ document.querySelectorAll(`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`)
13341
12763
  );
13342
- const slots = [];
13343
- if (sections.length === 0) return slots;
13344
- const left = 0;
13345
- const width = document.documentElement.clientWidth;
13346
- for (let i = 0; i <= sections.length; i++) {
13347
- let y;
13348
- if (i === 0) {
13349
- y = sections[0].getBoundingClientRect().top;
13350
- } else if (i === sections.length) {
13351
- y = sections[sections.length - 1].getBoundingClientRect().bottom;
13352
- } else {
13353
- const prev = sections[i - 1].getBoundingClientRect();
13354
- const next = sections[i].getBoundingClientRect();
13355
- y = (prev.bottom + next.top) / 2;
13356
- }
13357
- slots.push({ insertIndex: i, y, left, width });
13358
- }
13359
- return slots;
13360
12764
  }
13361
- function hitTestSectionDropSlot(y, slots) {
13362
- let best = null;
13363
- for (const slot of slots) {
13364
- const dist = Math.abs(y - slot.y);
13365
- if (!best || dist < best.dist) best = { slot, dist };
13366
- }
13367
- return best?.slot ?? null;
13368
- }
13369
-
13370
- // src/useSectionDrag.ts
13371
- var PRESS_THRESHOLD = 10;
13372
- var EDGE_ZONE = 60;
13373
- var MAX_AUTO_SCROLL_SPEED = 18;
13374
- var SECTION_DRAG_EXCLUDED_SELECTOR = [
13375
- "[data-ohw-toolbar]",
13376
- "[data-ohw-edit-chrome]",
13377
- "[data-ohw-item-interaction]",
13378
- "[data-ohw-drag-handle-container]",
13379
- '[data-slot="drag-handle"]',
13380
- "[data-ohw-item-toolbar-anchor]",
13381
- "[data-ohw-item-drag-surface]",
13382
- "[data-ohw-more-menu]",
13383
- '[data-slot="dropdown-menu-content"]',
13384
- '[data-slot="dropdown-menu-item"]',
13385
- "[data-ohw-state-toggle]",
13386
- "[data-ohw-max-badge]",
13387
- "[data-ohw-floating-panel]",
13388
- "[data-ohw-section-picker]",
13389
- "[data-ohw-link-popover-root]",
13390
- "[data-ohw-link-modal-root]",
13391
- "[data-ohw-link-page-dropdown]",
13392
- '[data-slot="popover-content"]',
13393
- '[data-slot="dialog-content"]',
13394
- '[data-slot="dialog-overlay"]',
13395
- "[data-ohw-ai-review]",
13396
- "[data-ohw-editable]",
13397
- "[data-ohw-editable-state]",
13398
- "[contenteditable]",
13399
- "[data-ohw-href-key]",
13400
- "[data-ohw-footer-col]",
13401
- "[data-ohw-social-label]",
13402
- "a",
13403
- "button",
13404
- '[role="button"]',
13405
- '[data-ohw-role="navbar-button"]',
13406
- '[data-ohw-role="button"]',
13407
- "[data-ohw-carousel]",
13408
- "[data-ohw-carousel-value]",
13409
- "[data-ohw-carousel-slide]",
13410
- "[data-ohw-carousel-overlay]",
13411
- "[data-ohw-media-chrome]",
13412
- "[data-ohw-media-overlay]",
13413
- "[data-ohw-media-skeleton]"
13414
- ].join(", ");
13415
- function visibleClip(ps) {
13416
- if (!ps) return null;
13417
- const top = Math.max(0, ps.headerH - ps.iframeOffsetTop);
13418
- const bottom = Math.min(window.innerHeight, ps.headerH + ps.canvasH - ps.iframeOffsetTop);
13419
- return { top, bottom: Math.max(top, bottom) };
13420
- }
13421
- function useSectionDrag({
13422
- isEditMode,
13423
- editContentRef,
13424
- postToParentRef,
13425
- parentScrollRef,
13426
- navDragRef,
13427
- footerDragRef,
13428
- suppressNextClickRef,
13429
- suppressClickUntilRef
13430
- }) {
13431
- const sectionDragRef = (0, import_react15.useRef)(null);
13432
- const [sectionDropSlots, setSectionDropSlots] = (0, import_react15.useState)([]);
13433
- const [activeSectionDropIndex, setActiveSectionDropIndex] = (0, import_react15.useState)(null);
13434
- const [isSectionDragging, setIsSectionDragging] = (0, import_react15.useState)(false);
13435
- const sectionPointerDragRef = (0, import_react15.useRef)(null);
13436
- const autoScrollRafRef = (0, import_react15.useRef)(null);
13437
- const autoScrollDeltaRef = (0, import_react15.useRef)(0);
13438
- const stopAutoScroll = (0, import_react15.useCallback)(() => {
13439
- if (autoScrollRafRef.current != null) {
13440
- cancelAnimationFrame(autoScrollRafRef.current);
13441
- autoScrollRafRef.current = null;
13442
- }
13443
- autoScrollDeltaRef.current = 0;
13444
- }, []);
13445
- const tickAutoScroll = (0, import_react15.useCallback)(() => {
13446
- if (!sectionDragRef.current) {
13447
- stopAutoScroll();
13448
- return;
13449
- }
13450
- if (autoScrollDeltaRef.current !== 0) {
13451
- postToParentRef.current({ type: "ow:request-scroll", deltaY: autoScrollDeltaRef.current });
13452
- }
13453
- autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
13454
- }, [postToParentRef, stopAutoScroll]);
13455
- const updateAutoScroll = (0, import_react15.useCallback)(
13456
- (clientY) => {
13457
- const clip = visibleClip(parentScrollRef.current);
13458
- let delta = 0;
13459
- if (clip) {
13460
- const distTop = clientY - clip.top;
13461
- const distBottom = clip.bottom - clientY;
13462
- if (distTop >= 0 && distTop < EDGE_ZONE) {
13463
- delta = -MAX_AUTO_SCROLL_SPEED * (1 - distTop / EDGE_ZONE);
13464
- } else if (distBottom >= 0 && distBottom < EDGE_ZONE) {
13465
- delta = MAX_AUTO_SCROLL_SPEED * (1 - distBottom / EDGE_ZONE);
13466
- }
13467
- }
13468
- autoScrollDeltaRef.current = delta;
13469
- if (delta !== 0 && autoScrollRafRef.current == null) {
13470
- autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
13471
- } else if (delta === 0) {
13472
- stopAutoScroll();
13473
- }
13474
- },
13475
- [parentScrollRef, stopAutoScroll, tickAutoScroll]
13476
- );
13477
- const clearSectionDragVisuals = (0, import_react15.useCallback)(() => {
13478
- sectionDragRef.current?.draggedEl.removeAttribute("data-ohw-section-dragging");
13479
- sectionDragRef.current = null;
13480
- setSectionDropSlots([]);
13481
- setActiveSectionDropIndex(null);
13482
- setIsSectionDragging(false);
13483
- stopAutoScroll();
13484
- document.documentElement.removeAttribute("data-ohw-section-dragging-root");
13485
- unlockItemDragInteraction();
13486
- }, [stopAutoScroll]);
13487
- const refreshSectionDragVisuals = (0, import_react15.useCallback)(
13488
- (session, clientX, clientY) => {
13489
- session.lastClientX = clientX;
13490
- session.lastClientY = clientY;
13491
- const slots = buildSectionDropSlots(session.instanceId);
13492
- const activeSlot = hitTestSectionDropSlot(clientY, slots);
13493
- session.activeSlot = activeSlot;
13494
- setSectionDropSlots(slots);
13495
- const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
13496
- setActiveSectionDropIndex(activeIdx >= 0 ? activeIdx : null);
13497
- updateAutoScroll(clientY);
13498
- },
13499
- [updateAutoScroll]
13500
- );
13501
- const beginSectionDrag = (0, import_react15.useCallback)(
13502
- (session) => {
13503
- sectionDragRef.current = session;
13504
- setIsSectionDragging(true);
13505
- lockItemDuringDrag();
13506
- document.documentElement.setAttribute("data-ohw-section-dragging-root", "");
13507
- session.draggedEl.setAttribute("data-ohw-section-dragging", "");
13508
- refreshSectionDragVisuals(session, session.lastClientX, session.lastClientY);
13509
- },
13510
- [refreshSectionDragVisuals]
13511
- );
13512
- const commitSectionDrag = (0, import_react15.useCallback)(() => {
13513
- const session = sectionDragRef.current;
13514
- if (!session) {
13515
- clearSectionDragVisuals();
13516
- return;
13517
- }
13518
- const slot = session.activeSlot ?? hitTestSectionDropSlot(session.lastClientY, buildSectionDropSlots(session.instanceId));
13519
- const entries = slot ? planSectionMove(session.instanceId, slot.insertIndex, window.location.pathname) : null;
13520
- if (!entries) {
13521
- clearSectionDragVisuals();
13522
- return;
13523
- }
13524
- const orderJson = JSON.stringify(entries);
13525
- editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
13526
- postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
13527
- applyPersistedOrder(entries);
13528
- clearSectionDragVisuals();
13529
- requestAnimationFrame(() => {
13530
- if (editContentRef.current[SECTION_ORDER_KEY] === orderJson) {
13531
- applyPersistedOrder(entries);
13532
- }
13533
- requestAnimationFrame(() => {
13534
- window.dispatchEvent(new Event("resize"));
13535
- });
13536
- });
13537
- }, [clearSectionDragVisuals, editContentRef, postToParentRef]);
13538
- const startSectionPressDrag = (0, import_react15.useCallback)(
13539
- (el, clientX, clientY, pointerId) => {
13540
- if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return false;
13541
- const instanceId = instanceIdOf(el);
13542
- if (!instanceId) return false;
13543
- sectionPointerDragRef.current = {
13544
- el,
13545
- instanceId,
13546
- startX: clientX,
13547
- startY: clientY,
13548
- pointerId,
13549
- started: false
13550
- };
13551
- return true;
13552
- },
13553
- [footerDragRef, navDragRef]
13554
- );
13555
- (0, import_react15.useEffect)(() => {
13556
- if (!isEditMode) return;
13557
- const onPointerDown = (e) => {
13558
- if (e.button !== 0) return;
13559
- if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return;
13560
- if (sectionPointerDragRef.current) return;
13561
- const target = e.target;
13562
- if (!(target instanceof HTMLElement)) return;
13563
- if (target.closest(SECTION_DRAG_EXCLUDED_SELECTOR)) return;
13564
- const sectionEl = target.closest("[data-ohw-section]");
13565
- if (!sectionEl || isChromeSection(sectionEl) || sectionEl.dataset.ohwSection === "footer") return;
13566
- if (!topLevelSections().includes(sectionEl)) return;
13567
- startSectionPressDrag(sectionEl, e.clientX, e.clientY, e.pointerId);
13568
- };
13569
- const onPointerMove = (e) => {
13570
- const pending = sectionPointerDragRef.current;
13571
- if (!pending) return;
13572
- if (pending.started) {
13573
- e.preventDefault();
13574
- clearTextSelection();
13575
- const session = sectionDragRef.current;
13576
- if (!session) return;
13577
- refreshSectionDragVisuals(session, e.clientX, e.clientY);
13578
- return;
13579
- }
13580
- const dx = e.clientX - pending.startX;
13581
- const dy = e.clientY - pending.startY;
13582
- if (dx * dx + dy * dy < PRESS_THRESHOLD * PRESS_THRESHOLD) return;
13583
- e.preventDefault();
13584
- pending.started = true;
13585
- armItemPressDrag();
13586
- clearTextSelection();
13587
- try {
13588
- document.body.setPointerCapture(pending.pointerId);
13589
- } catch {
13590
- }
13591
- beginSectionDrag({
13592
- instanceId: pending.instanceId,
13593
- draggedEl: pending.el,
13594
- lastClientX: e.clientX,
13595
- lastClientY: e.clientY,
13596
- activeSlot: null
13597
- });
13598
- };
13599
- const endPointerDrag = (e) => {
13600
- const pending = sectionPointerDragRef.current;
13601
- sectionPointerDragRef.current = null;
13602
- try {
13603
- if (document.body.hasPointerCapture(e.pointerId)) {
13604
- document.body.releasePointerCapture(e.pointerId);
13605
- }
13606
- } catch {
13607
- }
13608
- if (!pending) return;
13609
- if (!pending.started) {
13610
- unlockItemDragInteraction();
13611
- return;
13612
- }
13613
- suppressNextClickRef.current = true;
13614
- suppressClickUntilRef.current = Date.now() + 500;
13615
- commitSectionDrag();
13616
- };
13617
- const onKeyDown = (e) => {
13618
- if (e.key !== "Escape") return;
13619
- if (!sectionDragRef.current && !sectionPointerDragRef.current) return;
13620
- sectionPointerDragRef.current = null;
13621
- clearSectionDragVisuals();
13622
- };
13623
- document.addEventListener("pointerdown", onPointerDown, true);
13624
- document.addEventListener("pointermove", onPointerMove, true);
13625
- document.addEventListener("pointerup", endPointerDrag, true);
13626
- document.addEventListener("pointercancel", endPointerDrag, true);
13627
- document.addEventListener("keydown", onKeyDown, true);
13628
- return () => {
13629
- document.removeEventListener("pointerdown", onPointerDown, true);
13630
- document.removeEventListener("pointermove", onPointerMove, true);
13631
- document.removeEventListener("pointerup", endPointerDrag, true);
13632
- document.removeEventListener("pointercancel", endPointerDrag, true);
13633
- document.removeEventListener("keydown", onKeyDown, true);
13634
- unlockItemDragInteraction();
13635
- stopAutoScroll();
13636
- };
13637
- }, [
13638
- beginSectionDrag,
13639
- clearSectionDragVisuals,
13640
- commitSectionDrag,
13641
- footerDragRef,
13642
- isEditMode,
13643
- navDragRef,
13644
- refreshSectionDragVisuals,
13645
- startSectionPressDrag,
13646
- stopAutoScroll,
13647
- suppressClickUntilRef,
13648
- suppressNextClickRef
13649
- ]);
13650
- return {
13651
- sectionDragRef,
13652
- sectionDropSlots,
13653
- activeSectionDropIndex,
13654
- isSectionDragging
13655
- };
13656
- }
13657
-
13658
- // src/ui/footer-container-chrome.tsx
13659
- var import_lucide_react16 = require("lucide-react");
13660
- var import_jsx_runtime30 = require("react/jsx-runtime");
13661
- function FooterContainerChrome({
13662
- rect,
13663
- onAdd,
13664
- addDisabled = false
13665
- }) {
13666
- const chromeGap = 6;
13667
- const buttonMargin = 7;
13668
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13669
- "div",
13670
- {
13671
- "data-ohw-footer-container-chrome": "",
13672
- "data-ohw-bridge": "",
13673
- className: "pointer-events-none fixed z-[2147483647]",
13674
- style: {
13675
- top: rect.top - chromeGap,
13676
- left: rect.left - chromeGap,
13677
- width: rect.width + chromeGap * 2,
13678
- height: rect.height + chromeGap * 2
13679
- },
13680
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(Tooltip, { children: [
13681
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13682
- "button",
13683
- {
13684
- type: "button",
13685
- "data-ohw-footer-add-button": "",
13686
- disabled: addDisabled,
13687
- 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",
13688
- style: { top: chromeGap - buttonMargin },
13689
- "aria-label": "Add item",
13690
- onMouseDown: (e) => {
13691
- e.preventDefault();
13692
- e.stopPropagation();
13693
- },
13694
- onClick: (e) => {
13695
- e.preventDefault();
13696
- e.stopPropagation();
13697
- if (addDisabled) return;
13698
- onAdd();
13699
- },
13700
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react16.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
13701
- }
13702
- ) }),
13703
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
13704
- ] })
13705
- }
13706
- ) });
13707
- }
13708
-
13709
- // src/lib/carousel.ts
13710
- var import_react16 = require("react");
13711
- var CAROUSEL_ATTR = "data-ohw-carousel";
13712
- var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
13713
- var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
13714
- var CAROUSEL_EVENT = "ohw:carousel-change";
13715
- function listCarouselKeys() {
13716
- const keys = /* @__PURE__ */ new Set();
13717
- document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
13718
- const key = el.getAttribute("data-ohw-key");
13719
- if (key) keys.add(key);
13720
- });
13721
- return [...keys];
13722
- }
13723
- function containersForKey(key) {
13724
- return Array.from(
13725
- document.querySelectorAll(`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`)
13726
- );
13727
- }
13728
- function isCarouselKey(key) {
13729
- return containersForKey(key).length > 0;
13730
- }
13731
- function parseSlides(raw) {
13732
- if (!raw) return [];
13733
- try {
13734
- const parsed = JSON.parse(raw);
13735
- if (!Array.isArray(parsed)) return [];
13736
- return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
13737
- } catch {
13738
- return [];
12765
+ function isCarouselKey(key) {
12766
+ return containersForKey(key).length > 0;
12767
+ }
12768
+ function parseSlides(raw) {
12769
+ if (!raw) return [];
12770
+ try {
12771
+ const parsed = JSON.parse(raw);
12772
+ if (!Array.isArray(parsed)) return [];
12773
+ return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
12774
+ } catch {
12775
+ return [];
13739
12776
  }
13740
12777
  }
13741
12778
  function readCarouselValue(key) {
@@ -13769,8 +12806,8 @@ function applyCarouselNode(key, val) {
13769
12806
  return true;
13770
12807
  }
13771
12808
  function useOhwCarousel(key, initial) {
13772
- const [images, setImages] = (0, import_react16.useState)(initial);
13773
- (0, import_react16.useEffect)(() => {
12809
+ const [images, setImages] = (0, import_react15.useState)(initial);
12810
+ (0, import_react15.useEffect)(() => {
13774
12811
  const el = document.querySelector(
13775
12812
  `[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
13776
12813
  );
@@ -13848,7 +12885,7 @@ function collectEditableNodes(extraContent, root = document) {
13848
12885
  nodes.push({ key, type: "link", text: href });
13849
12886
  }
13850
12887
  if (extraContent) {
13851
- for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY, SECTION_ORDER_KEY]) {
12888
+ for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
13852
12889
  const text = extraContent[key];
13853
12890
  if (typeof text === "string" && text.length > 0) {
13854
12891
  nodes.push({ key, type: "meta", text });
@@ -13885,18 +12922,6 @@ function collectEditableNodes(extraContent, root = document) {
13885
12922
  }
13886
12923
  if (extraContent && !isScoped) {
13887
12924
  applyNavFooterDeleteOverrides(byKey, extraContent);
13888
- for (const key of LOGO_IMAGE_KEYS) {
13889
- if (!(key in extraContent)) continue;
13890
- byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
13891
- }
13892
- for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
13893
- if (!(key in extraContent)) continue;
13894
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
13895
- }
13896
- for (const key of LOGO_SIZE_KEYS) {
13897
- if (!(key in extraContent)) continue;
13898
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
13899
- }
13900
12925
  }
13901
12926
  return Array.from(byKey.values());
13902
12927
  }
@@ -14162,14 +13187,14 @@ function deleteSelectedNavFooterItem(deps) {
14162
13187
  }
14163
13188
 
14164
13189
  // src/ui/navbar-container-chrome.tsx
14165
- var import_lucide_react17 = require("lucide-react");
14166
- var import_jsx_runtime31 = require("react/jsx-runtime");
13190
+ var import_lucide_react16 = require("lucide-react");
13191
+ var import_jsx_runtime30 = require("react/jsx-runtime");
14167
13192
  function NavbarContainerChrome({
14168
13193
  rect,
14169
13194
  onAdd
14170
13195
  }) {
14171
13196
  const chromeGap = 6;
14172
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
13197
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
14173
13198
  "div",
14174
13199
  {
14175
13200
  "data-ohw-navbar-container-chrome": "",
@@ -14181,7 +13206,7 @@ function NavbarContainerChrome({
14181
13206
  width: rect.width + chromeGap * 2,
14182
13207
  height: rect.height + chromeGap * 2
14183
13208
  },
14184
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
13209
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
14185
13210
  "button",
14186
13211
  {
14187
13212
  type: "button",
@@ -14198,7 +13223,7 @@ function NavbarContainerChrome({
14198
13223
  e.stopPropagation();
14199
13224
  onAdd();
14200
13225
  },
14201
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react17.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
13226
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react16.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
14202
13227
  }
14203
13228
  )
14204
13229
  }
@@ -14207,7 +13232,7 @@ function NavbarContainerChrome({
14207
13232
 
14208
13233
  // src/ui/drop-indicator.tsx
14209
13234
  var React10 = __toESM(require("react"), 1);
14210
- var import_jsx_runtime32 = require("react/jsx-runtime");
13235
+ var import_jsx_runtime31 = require("react/jsx-runtime");
14211
13236
  var dropIndicatorVariants = cva(
14212
13237
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
14213
13238
  {
@@ -14231,7 +13256,7 @@ var dropIndicatorVariants = cva(
14231
13256
  );
14232
13257
  var DropIndicator = React10.forwardRef(
14233
13258
  ({ className, direction, state, ...props }, ref) => {
14234
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
13259
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
14235
13260
  "div",
14236
13261
  {
14237
13262
  ref,
@@ -14248,7 +13273,7 @@ var DropIndicator = React10.forwardRef(
14248
13273
  DropIndicator.displayName = "DropIndicator";
14249
13274
 
14250
13275
  // src/ui/badge.tsx
14251
- var import_jsx_runtime33 = require("react/jsx-runtime");
13276
+ var import_jsx_runtime32 = require("react/jsx-runtime");
14252
13277
  var badgeVariants = cva(
14253
13278
  "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
14254
13279
  {
@@ -14266,12 +13291,12 @@ var badgeVariants = cva(
14266
13291
  }
14267
13292
  );
14268
13293
  function Badge({ className, variant, ...props }) {
14269
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
13294
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
14270
13295
  }
14271
13296
 
14272
13297
  // src/OhhwellsBridge.tsx
14273
- var import_lucide_react18 = require("lucide-react");
14274
- var import_jsx_runtime34 = require("react/jsx-runtime");
13298
+ var import_lucide_react17 = require("lucide-react");
13299
+ var import_jsx_runtime33 = require("react/jsx-runtime");
14275
13300
  var PRIMARY3 = "#0885FE";
14276
13301
  var IMAGE_FADE_MS = 300;
14277
13302
  function runOpacityFade(el, onDone) {
@@ -14365,10 +13390,21 @@ function parseSchedulingInsertAfter(insertAfter) {
14365
13390
  insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
14366
13391
  };
14367
13392
  }
14368
- function resolveEntryAnchor(entry) {
14369
- if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
14370
- const parsed = parseSchedulingInsertAfter(entry.insertAfter);
14371
- return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
13393
+ function resolveSchedulingInsert(insertAfter, explicitInsertBefore) {
13394
+ const parsed = parseSchedulingInsertAfter(insertAfter);
13395
+ const insertBefore = explicitInsertBefore ?? parsed.insertBefore;
13396
+ const effectiveInsertAfter = insertBefore && parsed.insertBefore === null ? `${insertAfter}${INSERT_BEFORE_MARKER}${insertBefore}` : insertAfter;
13397
+ return { effectiveInsertAfter, insertBefore };
13398
+ }
13399
+ function getSchedulingMountPoint(insertAfter) {
13400
+ const { anchor } = parseSchedulingInsertAfter(insertAfter);
13401
+ let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
13402
+ if (!anchorEl && anchor === "scheduling") {
13403
+ const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
13404
+ anchorEl = widgets.at(-1) ?? null;
13405
+ }
13406
+ if (!anchorEl) return null;
13407
+ return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
14372
13408
  }
14373
13409
  function schedulingMountDepth(insertAfter) {
14374
13410
  if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
@@ -14385,7 +13421,8 @@ function getPageSchedulingEntries(raw) {
14385
13421
  }
14386
13422
  }
14387
13423
  function isSchedulingWidgetMissing(entry) {
14388
- return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
13424
+ const { effectiveInsertAfter } = resolveSchedulingInsert(entry.insertAfter);
13425
+ return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
14389
13426
  }
14390
13427
  function hasMissingSchedulingWidgets(entries) {
14391
13428
  return entries.some(isSchedulingWidgetMissing);
@@ -14415,17 +13452,16 @@ function initSectionsFromContent(content, removeExisting = false) {
14415
13452
  } catch {
14416
13453
  }
14417
13454
  }
14418
- function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
14419
- const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
14420
- const sectionId = schedulingSectionId(widgetId);
13455
+ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId, explicitInsertBefore) {
13456
+ const { effectiveInsertAfter, insertBefore } = resolveSchedulingInsert(insertAfter, explicitInsertBefore);
13457
+ const sectionId = schedulingSectionId(effectiveInsertAfter);
14421
13458
  if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
14422
- const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
14423
- if (!anchorEl) return false;
14424
- const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
13459
+ const mountPoint = getSchedulingMountPoint(effectiveInsertAfter);
13460
+ if (!mountPoint) return false;
14425
13461
  const container = document.createElement("div");
14426
13462
  container.dataset.ohwSectionContainer = "scheduling";
14427
- if (beforeId) {
14428
- const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
13463
+ if (insertBefore) {
13464
+ const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
14429
13465
  const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
14430
13466
  if (!beforePoint) return false;
14431
13467
  beforePoint.insertAdjacentElement("beforebegin", container);
@@ -14436,25 +13472,19 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
14436
13472
  }
14437
13473
  tail.insertAdjacentElement("afterend", container);
14438
13474
  }
14439
- try {
14440
- const root = (0, import_client2.createRoot)(container);
14441
- (0, import_react_dom3.flushSync)(() => {
14442
- root.render(
14443
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14444
- SchedulingWidget,
14445
- {
14446
- notifyOnConnect,
14447
- initialScheduleId: scheduleId,
14448
- insertAfter: widgetId
14449
- }
14450
- )
14451
- );
14452
- });
14453
- } catch (err) {
14454
- console.error("[ow:scheduling] render threw", err);
14455
- container.remove();
14456
- return false;
14457
- }
13475
+ const root = (0, import_client2.createRoot)(container);
13476
+ (0, import_react_dom3.flushSync)(() => {
13477
+ root.render(
13478
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13479
+ SchedulingWidget,
13480
+ {
13481
+ notifyOnConnect,
13482
+ initialScheduleId: scheduleId,
13483
+ insertAfter: effectiveInsertAfter
13484
+ }
13485
+ )
13486
+ );
13487
+ });
14458
13488
  const tracker = getSectionsTracker();
14459
13489
  let sections = [];
14460
13490
  try {
@@ -14462,12 +13492,10 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
14462
13492
  } catch {
14463
13493
  }
14464
13494
  const inEditor = typeof window !== "undefined" && window.self !== window.top;
14465
- if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
13495
+ if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === effectiveInsertAfter)) {
14466
13496
  sections.push({
14467
13497
  type: "scheduling",
14468
- insertAfter: widgetId,
14469
- anchorId,
14470
- beforeId: beforeId ?? null,
13498
+ insertAfter: effectiveInsertAfter,
14471
13499
  pagePath: window.location.pathname,
14472
13500
  ...scheduleId ? { scheduleId } : {}
14473
13501
  });
@@ -14481,8 +13509,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
14481
13509
  for (let i = pending.length - 1; i >= 0; i--) {
14482
13510
  const entry = pending[i];
14483
13511
  const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
14484
- const { anchorId, beforeId } = resolveEntryAnchor(entry);
14485
- if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
13512
+ if (mountSchedulingWidget(entry.insertAfter, shouldNotify, entry.scheduleId)) {
14486
13513
  pending.splice(i, 1);
14487
13514
  }
14488
13515
  }
@@ -14630,13 +13657,6 @@ function isInsideLinkEditor(target) {
14630
13657
  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"]')
14631
13658
  );
14632
13659
  }
14633
- function isInsideFloatingPanel(target) {
14634
- return Boolean(target.closest("[data-ohw-floating-panel]"));
14635
- }
14636
- function isPointOverFloatingPanel(clientX, clientY) {
14637
- const el = document.elementFromPoint(clientX, clientY);
14638
- return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
14639
- }
14640
13660
  function getHrefKeyFromElement(el) {
14641
13661
  if (!el) return null;
14642
13662
  const anchor = el.closest("[data-ohw-href-key]");
@@ -14787,6 +13807,13 @@ function resolveFooterColumnSelectionTarget(target, clientX, clientY) {
14787
13807
  if (isPointOverNavItem(column, clientX, clientY)) return null;
14788
13808
  return column;
14789
13809
  }
13810
+ function isPointOverLogo(x, y) {
13811
+ for (const root of document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]')) {
13812
+ const r2 = root.getBoundingClientRect();
13813
+ if (r2.width > 0 && r2.height > 0 && x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom) return true;
13814
+ }
13815
+ return false;
13816
+ }
14790
13817
  function isPointOverNavigation(x, y) {
14791
13818
  const roots = /* @__PURE__ */ new Set();
14792
13819
  const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
@@ -14875,7 +13902,7 @@ function getNavigationSelectionParent(el) {
14875
13902
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
14876
13903
  return getFooterLinksContainer();
14877
13904
  }
14878
- 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)) {
13905
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
14879
13906
  return getNavigationRoot(el);
14880
13907
  }
14881
13908
  return null;
@@ -15121,7 +14148,7 @@ function EditGlowChrome({
15121
14148
  hideHandle = false
15122
14149
  }) {
15123
14150
  const GAP = SELECTION_CHROME_GAP2;
15124
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
14151
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
15125
14152
  "div",
15126
14153
  {
15127
14154
  ref: elRef,
@@ -15136,7 +14163,7 @@ function EditGlowChrome({
15136
14163
  zIndex: 2147483646
15137
14164
  },
15138
14165
  children: [
15139
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14166
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15140
14167
  "div",
15141
14168
  {
15142
14169
  style: {
@@ -15149,7 +14176,7 @@ function EditGlowChrome({
15149
14176
  }
15150
14177
  }
15151
14178
  ),
15152
- reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14179
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15153
14180
  "div",
15154
14181
  {
15155
14182
  "data-ohw-drag-handle-container": "",
@@ -15161,7 +14188,7 @@ function EditGlowChrome({
15161
14188
  transform: "translate(calc(-100% - 7px), -50%)",
15162
14189
  pointerEvents: dragDisabled ? "none" : "auto"
15163
14190
  },
15164
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14191
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15165
14192
  DragHandle,
15166
14193
  {
15167
14194
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -15344,9 +14371,9 @@ function FloatingToolbar({
15344
14371
  showEditLink,
15345
14372
  onEditLink
15346
14373
  }) {
15347
- const localRef = import_react17.default.useRef(null);
15348
- const [measuredW, setMeasuredW] = import_react17.default.useState(330);
15349
- const setRefs = import_react17.default.useCallback(
14374
+ const localRef = import_react16.default.useRef(null);
14375
+ const [measuredW, setMeasuredW] = import_react16.default.useState(330);
14376
+ const setRefs = import_react16.default.useCallback(
15350
14377
  (node) => {
15351
14378
  localRef.current = node;
15352
14379
  if (typeof elRef === "function") elRef(node);
@@ -15358,7 +14385,7 @@ function FloatingToolbar({
15358
14385
  },
15359
14386
  [elRef]
15360
14387
  );
15361
- import_react17.default.useLayoutEffect(() => {
14388
+ import_react16.default.useLayoutEffect(() => {
15362
14389
  const node = localRef.current;
15363
14390
  if (!node) return;
15364
14391
  const update = () => {
@@ -15371,7 +14398,7 @@ function FloatingToolbar({
15371
14398
  return () => ro.disconnect();
15372
14399
  }, [showEditLink, activeCommands]);
15373
14400
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
15374
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14401
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15375
14402
  "div",
15376
14403
  {
15377
14404
  ref: setRefs,
@@ -15383,12 +14410,12 @@ function FloatingToolbar({
15383
14410
  zIndex: 2147483647,
15384
14411
  pointerEvents: "auto"
15385
14412
  },
15386
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(CustomToolbar, { children: [
15387
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react17.default.Fragment, { children: [
15388
- gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(CustomToolbarDivider, {}),
14413
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(CustomToolbar, { children: [
14414
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react16.default.Fragment, { children: [
14415
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CustomToolbarDivider, {}),
15389
14416
  btns.map((btn) => {
15390
14417
  const isActive = activeCommands.has(btn.cmd);
15391
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14418
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15392
14419
  CustomToolbarButton,
15393
14420
  {
15394
14421
  title: btn.title,
@@ -15397,7 +14424,7 @@ function FloatingToolbar({
15397
14424
  e.preventDefault();
15398
14425
  onCommand(btn.cmd);
15399
14426
  },
15400
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14427
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15401
14428
  "svg",
15402
14429
  {
15403
14430
  width: "16",
@@ -15418,7 +14445,7 @@ function FloatingToolbar({
15418
14445
  );
15419
14446
  })
15420
14447
  ] }, gi)),
15421
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14448
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15422
14449
  CustomToolbarButton,
15423
14450
  {
15424
14451
  type: "button",
@@ -15432,7 +14459,7 @@ function FloatingToolbar({
15432
14459
  e.preventDefault();
15433
14460
  e.stopPropagation();
15434
14461
  },
15435
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Link, { className: "size-4 shrink-0", "aria-hidden": true })
14462
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Link, { className: "size-4 shrink-0", "aria-hidden": true })
15436
14463
  }
15437
14464
  ) : null
15438
14465
  ] })
@@ -15449,7 +14476,7 @@ function StateToggle({
15449
14476
  states,
15450
14477
  onStateChange
15451
14478
  }) {
15452
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14479
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
15453
14480
  ToggleGroup,
15454
14481
  {
15455
14482
  "data-ohw-state-toggle": "",
@@ -15463,50 +14490,11 @@ function StateToggle({
15463
14490
  left: rect.right - 8,
15464
14491
  transform: "translateX(-100%)"
15465
14492
  },
15466
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
14493
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
15467
14494
  }
15468
14495
  );
15469
14496
  }
15470
14497
  var contentCache = /* @__PURE__ */ new Map();
15471
- var fetchedContentPaths = /* @__PURE__ */ new Set();
15472
- var OHW_LOADER_STYLE = {
15473
- position: "fixed",
15474
- inset: 0,
15475
- background: "#fff",
15476
- zIndex: 2147483646,
15477
- display: "flex",
15478
- alignItems: "center",
15479
- justifyContent: "center"
15480
- };
15481
- function OhwLoaderSpinner() {
15482
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", "aria-hidden": true, children: [
15483
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("circle", { cx: "14", cy: "14", r: "11", stroke: "#E7E5E4", strokeWidth: "3" }),
15484
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
15485
- "circle",
15486
- {
15487
- cx: "14",
15488
- cy: "14",
15489
- r: "11",
15490
- stroke: "#1C1917",
15491
- strokeWidth: "3",
15492
- strokeDasharray: "17 52",
15493
- strokeLinecap: "round",
15494
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
15495
- "animateTransform",
15496
- {
15497
- attributeName: "transform",
15498
- type: "rotate",
15499
- from: "0 14 14",
15500
- to: "360 14 14",
15501
- dur: "0.7s",
15502
- repeatCount: "indefinite"
15503
- }
15504
- )
15505
- }
15506
- )
15507
- ] });
15508
- }
15509
- 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){}})();`;
15510
14498
  function resolveSubdomain(subdomainFromQuery) {
15511
14499
  if (subdomainFromQuery) return subdomainFromQuery;
15512
14500
  if (typeof window !== "undefined") {
@@ -15529,8 +14517,8 @@ function OhhwellsBridge() {
15529
14517
  const router = (0, import_navigation3.useRouter)();
15530
14518
  const searchParams = (0, import_navigation3.useSearchParams)();
15531
14519
  const isEditMode = isEditSessionActive();
15532
- const [bridgeRoot, setBridgeRoot] = (0, import_react17.useState)(null);
15533
- (0, import_react17.useEffect)(() => {
14520
+ const [bridgeRoot, setBridgeRoot] = (0, import_react16.useState)(null);
14521
+ (0, import_react16.useEffect)(() => {
15534
14522
  const figtreeFontId = "ohw-figtree-font";
15535
14523
  if (!document.getElementById(figtreeFontId)) {
15536
14524
  const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
@@ -15559,82 +14547,82 @@ function OhhwellsBridge() {
15559
14547
  const subdomain = resolveSubdomain(subdomainFromQuery);
15560
14548
  useLinkHrefGuardian(pathname, subdomain, isEditMode);
15561
14549
  useSavedLinkNavigation(isEditMode);
15562
- const postToParent2 = (0, import_react17.useCallback)((data) => {
14550
+ const postToParent2 = (0, import_react16.useCallback)((data) => {
15563
14551
  if (typeof window !== "undefined" && window.parent !== window) {
15564
14552
  window.parent.postMessage(data, "*");
15565
14553
  }
15566
14554
  }, []);
15567
- const [fetchState, setFetchState] = (0, import_react17.useState)("idle");
15568
- const autoSaveTimers = (0, import_react17.useRef)(/* @__PURE__ */ new Map());
15569
- const activeElRef = (0, import_react17.useRef)(null);
15570
- const pointerHeldRef = (0, import_react17.useRef)(false);
15571
- const selectedElRef = (0, import_react17.useRef)(null);
15572
- const selectedHrefKeyRef = (0, import_react17.useRef)(null);
15573
- const selectedFooterColAttrRef = (0, import_react17.useRef)(null);
15574
- const originalContentRef = (0, import_react17.useRef)(null);
15575
- const activeStateElRef = (0, import_react17.useRef)(null);
15576
- const parentScrollRef = (0, import_react17.useRef)(null);
15577
- const visibleViewportRef = (0, import_react17.useRef)(null);
15578
- const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react17.useState)(null);
15579
- const attachVisibleViewport = (0, import_react17.useCallback)((node) => {
14555
+ const [fetchState, setFetchState] = (0, import_react16.useState)("idle");
14556
+ const autoSaveTimers = (0, import_react16.useRef)(/* @__PURE__ */ new Map());
14557
+ const activeElRef = (0, import_react16.useRef)(null);
14558
+ const pointerHeldRef = (0, import_react16.useRef)(false);
14559
+ const selectedElRef = (0, import_react16.useRef)(null);
14560
+ const selectedHrefKeyRef = (0, import_react16.useRef)(null);
14561
+ const selectedFooterColAttrRef = (0, import_react16.useRef)(null);
14562
+ const originalContentRef = (0, import_react16.useRef)(null);
14563
+ const activeStateElRef = (0, import_react16.useRef)(null);
14564
+ const parentScrollRef = (0, import_react16.useRef)(null);
14565
+ const visibleViewportRef = (0, import_react16.useRef)(null);
14566
+ const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react16.useState)(null);
14567
+ const attachVisibleViewport = (0, import_react16.useCallback)((node) => {
15580
14568
  visibleViewportRef.current = node;
15581
14569
  setDialogPortalContainer(node);
15582
14570
  if (node) applyVisibleViewport(node, parentScrollRef.current);
15583
14571
  }, []);
15584
- const toolbarElRef = (0, import_react17.useRef)(null);
15585
- const glowElRef = (0, import_react17.useRef)(null);
15586
- const hoveredImageRef = (0, import_react17.useRef)(null);
15587
- const hoveredImageHasTextOverlapRef = (0, import_react17.useRef)(false);
15588
- const dragOverElRef = (0, import_react17.useRef)(null);
15589
- const [mediaHover, setMediaHover] = (0, import_react17.useState)(null);
15590
- const [carouselHover, setCarouselHover] = (0, import_react17.useState)(null);
15591
- const [uploadingRects, setUploadingRects] = (0, import_react17.useState)({});
15592
- const hoveredGapRef = (0, import_react17.useRef)(null);
15593
- const imageUnhoverTimerRef = (0, import_react17.useRef)(null);
15594
- const imageShowTimerRef = (0, import_react17.useRef)(null);
15595
- const editStylesRef = (0, import_react17.useRef)(null);
15596
- const activateRef = (0, import_react17.useRef)(() => {
14572
+ const toolbarElRef = (0, import_react16.useRef)(null);
14573
+ const glowElRef = (0, import_react16.useRef)(null);
14574
+ const hoveredImageRef = (0, import_react16.useRef)(null);
14575
+ const hoveredImageHasTextOverlapRef = (0, import_react16.useRef)(false);
14576
+ const dragOverElRef = (0, import_react16.useRef)(null);
14577
+ const [mediaHover, setMediaHover] = (0, import_react16.useState)(null);
14578
+ const [carouselHover, setCarouselHover] = (0, import_react16.useState)(null);
14579
+ const [uploadingRects, setUploadingRects] = (0, import_react16.useState)({});
14580
+ const hoveredGapRef = (0, import_react16.useRef)(null);
14581
+ const imageUnhoverTimerRef = (0, import_react16.useRef)(null);
14582
+ const imageShowTimerRef = (0, import_react16.useRef)(null);
14583
+ const editStylesRef = (0, import_react16.useRef)(null);
14584
+ const activateRef = (0, import_react16.useRef)(() => {
15597
14585
  });
15598
- const deactivateRef = (0, import_react17.useRef)(() => {
14586
+ const deactivateRef = (0, import_react16.useRef)(() => {
15599
14587
  });
15600
- const selectRef = (0, import_react17.useRef)(() => {
14588
+ const selectRef = (0, import_react16.useRef)(() => {
15601
14589
  });
15602
- const selectFrameRef = (0, import_react17.useRef)(() => {
14590
+ const selectFrameRef = (0, import_react16.useRef)(() => {
15603
14591
  });
15604
- const selectLogoRef = (0, import_react17.useRef)(() => {
14592
+ const selectLogoRef = (0, import_react16.useRef)(() => {
15605
14593
  });
15606
- const openLogoSizePanelRef = (0, import_react17.useRef)(() => {
14594
+ const openLogoSizePanelRef = (0, import_react16.useRef)(() => {
15607
14595
  });
15608
- const deselectRef = (0, import_react17.useRef)(() => {
14596
+ const deselectRef = (0, import_react16.useRef)(() => {
15609
14597
  });
15610
- const closeFloatingPanelOnlyRef = (0, import_react17.useRef)(() => {
14598
+ const closeFloatingPanelOnlyRef = (0, import_react16.useRef)(() => {
15611
14599
  });
15612
- const reselectNavigationItemRef = (0, import_react17.useRef)(() => {
14600
+ const reselectNavigationItemRef = (0, import_react16.useRef)(() => {
15613
14601
  });
15614
- const commitNavigationTextEditRef = (0, import_react17.useRef)(() => {
14602
+ const commitNavigationTextEditRef = (0, import_react16.useRef)(() => {
15615
14603
  });
15616
- const handleDeleteSelectedRef = (0, import_react17.useRef)(() => false);
15617
- const runPendingDeleteUndoRef = (0, import_react17.useRef)(() => false);
15618
- const isFooterFrameSelectionRef = (0, import_react17.useRef)(false);
15619
- const refreshActiveCommandsRef = (0, import_react17.useRef)(() => {
14604
+ const handleDeleteSelectedRef = (0, import_react16.useRef)(() => false);
14605
+ const runPendingDeleteUndoRef = (0, import_react16.useRef)(() => false);
14606
+ const isFooterFrameSelectionRef = (0, import_react16.useRef)(false);
14607
+ const refreshActiveCommandsRef = (0, import_react16.useRef)(() => {
15620
14608
  });
15621
- const postToParentRef = (0, import_react17.useRef)(postToParent2);
14609
+ const postToParentRef = (0, import_react16.useRef)(postToParent2);
15622
14610
  postToParentRef.current = postToParent2;
15623
- const aiSectionApiRef = (0, import_react17.useRef)(null);
15624
- const sectionsLoadedRef = (0, import_react17.useRef)(false);
15625
- const pendingScheduleConfigRequests = (0, import_react17.useRef)([]);
15626
- const [toolbarRect, setToolbarRect] = (0, import_react17.useState)(null);
15627
- const [formPickRect, setFormPickRect] = (0, import_react17.useState)(null);
15628
- const formPickElRef = (0, import_react17.useRef)(null);
15629
- const [formViewState, setFormViewStateUi] = (0, import_react17.useState)("default");
15630
- const [formPickCount, setFormPickCount] = (0, import_react17.useState)(null);
15631
- const [formHoverRect, setFormHoverRect] = (0, import_react17.useState)(null);
15632
- const formHoverElRef = (0, import_react17.useRef)(null);
15633
- const [fieldPickRect, setFieldPickRect] = (0, import_react17.useState)(null);
15634
- const fieldPickElRef = (0, import_react17.useRef)(null);
15635
- const [fieldPickState, setFieldPickState] = (0, import_react17.useState)(null);
15636
- const [fieldTypePickerOpen, setFieldTypePickerOpen] = (0, import_react17.useState)(false);
15637
- const clearFormPick = (0, import_react17.useCallback)(() => {
14611
+ const aiSectionApiRef = (0, import_react16.useRef)(null);
14612
+ const sectionsLoadedRef = (0, import_react16.useRef)(false);
14613
+ const pendingScheduleConfigRequests = (0, import_react16.useRef)([]);
14614
+ const [toolbarRect, setToolbarRect] = (0, import_react16.useState)(null);
14615
+ const [formPickRect, setFormPickRect] = (0, import_react16.useState)(null);
14616
+ const formPickElRef = (0, import_react16.useRef)(null);
14617
+ const [formViewState, setFormViewStateUi] = (0, import_react16.useState)("default");
14618
+ const [formPickCount, setFormPickCount] = (0, import_react16.useState)(null);
14619
+ const [formHoverRect, setFormHoverRect] = (0, import_react16.useState)(null);
14620
+ const formHoverElRef = (0, import_react16.useRef)(null);
14621
+ const [fieldPickRect, setFieldPickRect] = (0, import_react16.useState)(null);
14622
+ const fieldPickElRef = (0, import_react16.useRef)(null);
14623
+ const [fieldPickState, setFieldPickState] = (0, import_react16.useState)(null);
14624
+ const [fieldTypePickerOpen, setFieldTypePickerOpen] = (0, import_react16.useState)(false);
14625
+ const clearFormPick = (0, import_react16.useCallback)(() => {
15638
14626
  const form = formPickElRef.current;
15639
14627
  const editing = fieldPickElRef.current;
15640
14628
  if (commitPlaceholderEdit(editing) && editing) {
@@ -15654,7 +14642,7 @@ function OhhwellsBridge() {
15654
14642
  formPickElRef.current = null;
15655
14643
  setFormPickRect(null);
15656
14644
  }, []);
15657
- const clearFieldPick = (0, import_react17.useCallback)(() => {
14645
+ const clearFieldPick = (0, import_react16.useCallback)(() => {
15658
14646
  const wrapper = fieldPickElRef.current;
15659
14647
  if (commitPlaceholderEdit(wrapper) && wrapper) {
15660
14648
  const form = wrapper.closest('[data-ohw-editable="form"]');
@@ -15664,9 +14652,9 @@ function OhhwellsBridge() {
15664
14652
  setFieldPickRect(null);
15665
14653
  setFieldPickState(null);
15666
14654
  }, []);
15667
- const persistFieldsRef = (0, import_react17.useRef)(() => {
14655
+ const persistFieldsRef = (0, import_react16.useRef)(() => {
15668
14656
  });
15669
- const persistFields = (0, import_react17.useCallback)(
14657
+ const persistFields = (0, import_react16.useCallback)(
15670
14658
  (form) => {
15671
14659
  const key = formKeyOf(form);
15672
14660
  if (!key) return;
@@ -15677,7 +14665,7 @@ function OhhwellsBridge() {
15677
14665
  []
15678
14666
  );
15679
14667
  persistFieldsRef.current = persistFields;
15680
- const selectField = (0, import_react17.useCallback)((wrapper) => {
14668
+ const selectField = (0, import_react16.useCallback)((wrapper) => {
15681
14669
  if (fieldPickElRef.current && fieldPickElRef.current !== wrapper) {
15682
14670
  commitPlaceholderEdit(fieldPickElRef.current);
15683
14671
  }
@@ -15690,7 +14678,7 @@ function OhhwellsBridge() {
15690
14678
  setFieldPickState({ type: fieldTypeOf(wrapper), required: isFieldRequired(wrapper) });
15691
14679
  setFieldTypePickerOpen(false);
15692
14680
  }, []);
15693
- const withSelectedField = (0, import_react17.useCallback)(
14681
+ const withSelectedField = (0, import_react16.useCallback)(
15694
14682
  (run) => {
15695
14683
  const wrapper = fieldPickElRef.current;
15696
14684
  const form = formPickElRef.current;
@@ -15703,28 +14691,28 @@ function OhhwellsBridge() {
15703
14691
  },
15704
14692
  [persistFields]
15705
14693
  );
15706
- const handleFieldTypeChange = (0, import_react17.useCallback)(
14694
+ const handleFieldTypeChange = (0, import_react16.useCallback)(
15707
14695
  (type) => withSelectedField((_form, wrapper) => {
15708
14696
  applyFieldType(wrapper, type);
15709
14697
  selectField(wrapper);
15710
14698
  }),
15711
14699
  [selectField, withSelectedField]
15712
14700
  );
15713
- const handleFieldRequiredToggle = (0, import_react17.useCallback)(
14701
+ const handleFieldRequiredToggle = (0, import_react16.useCallback)(
15714
14702
  () => withSelectedField((_form, wrapper) => {
15715
14703
  setFieldRequired(wrapper, !isFieldRequired(wrapper));
15716
14704
  selectField(wrapper);
15717
14705
  }),
15718
14706
  [selectField, withSelectedField]
15719
14707
  );
15720
- const handleFieldDuplicate = (0, import_react17.useCallback)(
14708
+ const handleFieldDuplicate = (0, import_react16.useCallback)(
15721
14709
  () => withSelectedField((form, wrapper) => {
15722
14710
  const copy = duplicateField(form, wrapper);
15723
14711
  selectField(copy);
15724
14712
  }),
15725
14713
  [selectField, withSelectedField]
15726
14714
  );
15727
- const handleFieldDelete = (0, import_react17.useCallback)(
14715
+ const handleFieldDelete = (0, import_react16.useCallback)(
15728
14716
  () => withSelectedField((_form, wrapper) => {
15729
14717
  removeField(wrapper);
15730
14718
  clearFieldPick();
@@ -15732,7 +14720,7 @@ function OhhwellsBridge() {
15732
14720
  }),
15733
14721
  [clearFieldPick, withSelectedField]
15734
14722
  );
15735
- const handleAddField = (0, import_react17.useCallback)(
14723
+ const handleAddField = (0, import_react16.useCallback)(
15736
14724
  (type) => {
15737
14725
  const form = formPickElRef.current;
15738
14726
  if (!form) return;
@@ -15748,8 +14736,8 @@ function OhhwellsBridge() {
15748
14736
  },
15749
14737
  [persistFields, selectField]
15750
14738
  );
15751
- const fieldDragRef = (0, import_react17.useRef)(null);
15752
- const buildFieldDropSlots = (0, import_react17.useCallback)((form, draggedKey) => {
14739
+ const fieldDragRef = (0, import_react16.useRef)(null);
14740
+ const buildFieldDropSlots = (0, import_react16.useCallback)((form, draggedKey) => {
15753
14741
  const others = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== draggedKey);
15754
14742
  const slots = others.map((el) => {
15755
14743
  const rect = el.getBoundingClientRect();
@@ -15762,7 +14750,7 @@ function OhhwellsBridge() {
15762
14750
  }
15763
14751
  return slots;
15764
14752
  }, []);
15765
- const handleFieldDragStart = (0, import_react17.useCallback)(() => {
14753
+ const handleFieldDragStart = (0, import_react16.useCallback)(() => {
15766
14754
  const wrapper = fieldPickElRef.current;
15767
14755
  const form = formPickElRef.current;
15768
14756
  if (!wrapper || !form) return;
@@ -15771,18 +14759,18 @@ function OhhwellsBridge() {
15771
14759
  setFieldDragging(true);
15772
14760
  setFieldDropSlots(buildFieldDropSlots(form, key));
15773
14761
  }, [buildFieldDropSlots]);
15774
- const handleFieldDragEnd = (0, import_react17.useCallback)(() => {
14762
+ const handleFieldDragEnd = (0, import_react16.useCallback)(() => {
15775
14763
  fieldDragRef.current = null;
15776
14764
  setFieldDropIndex(null);
15777
14765
  setFieldDropSlots([]);
15778
14766
  setFieldDragging(false);
15779
14767
  }, []);
15780
- const [fieldDropIndex, setFieldDropIndex] = (0, import_react17.useState)(null);
15781
- const [fieldDropSlots, setFieldDropSlots] = (0, import_react17.useState)([]);
15782
- const [fieldDragging, setFieldDragging] = (0, import_react17.useState)(false);
15783
- const clearFormPickRef = (0, import_react17.useRef)(clearFormPick);
14768
+ const [fieldDropIndex, setFieldDropIndex] = (0, import_react16.useState)(null);
14769
+ const [fieldDropSlots, setFieldDropSlots] = (0, import_react16.useState)([]);
14770
+ const [fieldDragging, setFieldDragging] = (0, import_react16.useState)(false);
14771
+ const clearFormPickRef = (0, import_react16.useRef)(clearFormPick);
15784
14772
  clearFormPickRef.current = clearFormPick;
15785
- (0, import_react17.useEffect)(() => {
14773
+ (0, import_react16.useEffect)(() => {
15786
14774
  const el = fieldPickElRef.current;
15787
14775
  if (!el || fieldPickRect === null) return;
15788
14776
  const observer = new ResizeObserver(() => {
@@ -15791,7 +14779,7 @@ function OhhwellsBridge() {
15791
14779
  observer.observe(el);
15792
14780
  return () => observer.disconnect();
15793
14781
  }, [fieldPickRect !== null, fieldPickState]);
15794
- (0, import_react17.useEffect)(() => {
14782
+ (0, import_react16.useEffect)(() => {
15795
14783
  const el = formPickElRef.current;
15796
14784
  if (!el || formPickRect === null) return;
15797
14785
  const observer = new ResizeObserver(() => {
@@ -15800,25 +14788,25 @@ function OhhwellsBridge() {
15800
14788
  observer.observe(el);
15801
14789
  return () => observer.disconnect();
15802
14790
  }, [formPickRect !== null, formViewState]);
15803
- const [toolbarVariant, setToolbarVariant] = (0, import_react17.useState)("none");
15804
- const toolbarVariantRef = (0, import_react17.useRef)("none");
14791
+ const [toolbarVariant, setToolbarVariant] = (0, import_react16.useState)("none");
14792
+ const toolbarVariantRef = (0, import_react16.useRef)("none");
15805
14793
  toolbarVariantRef.current = toolbarVariant;
15806
- const [selectedIsCta, setSelectedIsCta] = (0, import_react17.useState)(false);
15807
- const [selectedIsSocial, setSelectedIsSocial] = (0, import_react17.useState)(false);
15808
- const [selectedIsSocialsRow, setSelectedIsSocialsRow] = (0, import_react17.useState)(false);
15809
- const [reorderHrefKey, setReorderHrefKey] = (0, import_react17.useState)(null);
15810
- const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react17.useState)(false);
15811
- const [toggleState, setToggleState] = (0, import_react17.useState)(null);
15812
- const [maxBadge, setMaxBadge] = (0, import_react17.useState)(null);
15813
- const [activeCommands, setActiveCommands] = (0, import_react17.useState)(/* @__PURE__ */ new Set());
15814
- const [sectionGap, setSectionGap] = (0, import_react17.useState)(null);
15815
- const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react17.useState)(false);
15816
- const hoveredNavContainerRef = (0, import_react17.useRef)(null);
15817
- const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react17.useState)(null);
15818
- const hoveredItemElRef = (0, import_react17.useRef)(null);
15819
- const [hoveredItemRect, setHoveredItemRect] = (0, import_react17.useState)(null);
15820
- const [hoveredTextRect, setHoveredTextRect] = (0, import_react17.useState)(null);
15821
- (0, import_react17.useEffect)(() => {
14794
+ const [selectedIsCta, setSelectedIsCta] = (0, import_react16.useState)(false);
14795
+ const [selectedIsSocial, setSelectedIsSocial] = (0, import_react16.useState)(false);
14796
+ const [selectedIsSocialsRow, setSelectedIsSocialsRow] = (0, import_react16.useState)(false);
14797
+ const [reorderHrefKey, setReorderHrefKey] = (0, import_react16.useState)(null);
14798
+ const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react16.useState)(false);
14799
+ const [toggleState, setToggleState] = (0, import_react16.useState)(null);
14800
+ const [maxBadge, setMaxBadge] = (0, import_react16.useState)(null);
14801
+ const [activeCommands, setActiveCommands] = (0, import_react16.useState)(/* @__PURE__ */ new Set());
14802
+ const [sectionGap, setSectionGap] = (0, import_react16.useState)(null);
14803
+ const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react16.useState)(false);
14804
+ const hoveredNavContainerRef = (0, import_react16.useRef)(null);
14805
+ const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react16.useState)(null);
14806
+ const hoveredItemElRef = (0, import_react16.useRef)(null);
14807
+ const [hoveredItemRect, setHoveredItemRect] = (0, import_react16.useState)(null);
14808
+ const [hoveredTextRect, setHoveredTextRect] = (0, import_react16.useState)(null);
14809
+ (0, import_react16.useEffect)(() => {
15822
14810
  const sync = () => {
15823
14811
  const el = document.querySelector(
15824
14812
  '[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]):not([data-ohw-editable="form"] *)'
@@ -15839,56 +14827,43 @@ function OhhwellsBridge() {
15839
14827
  });
15840
14828
  return () => observer.disconnect();
15841
14829
  }, []);
15842
- const siblingHintElRef = (0, import_react17.useRef)(null);
15843
- const [siblingHintRect, setSiblingHintRect] = (0, import_react17.useState)(null);
15844
- const [siblingHintRects, setSiblingHintRects] = (0, import_react17.useState)([]);
15845
- const [isItemDragging, setIsItemDragging] = (0, import_react17.useState)(false);
15846
- const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react17.useState)(false);
14830
+ const siblingHintElRef = (0, import_react16.useRef)(null);
14831
+ const [siblingHintRect, setSiblingHintRect] = (0, import_react16.useState)(null);
14832
+ const [siblingHintRects, setSiblingHintRects] = (0, import_react16.useState)([]);
14833
+ const [isItemDragging, setIsItemDragging] = (0, import_react16.useState)(false);
14834
+ const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react16.useState)(false);
15847
14835
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
15848
- const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react17.useState)(null);
15849
- const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react17.useState)(null);
15850
- const footerDragRef = (0, import_react17.useRef)(null);
15851
- const [footerDropSlots, setFooterDropSlots] = (0, import_react17.useState)([]);
15852
- const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react17.useState)(null);
15853
- const [draggedItemRect, setDraggedItemRect] = (0, import_react17.useState)(null);
15854
- const footerPointerDragRef = (0, import_react17.useRef)(null);
15855
- const suppressNextClickRef = (0, import_react17.useRef)(false);
15856
- const suppressClickUntilRef = (0, import_react17.useRef)(0);
15857
- const [linkPopover, setLinkPopover] = (0, import_react17.useState)(null);
15858
- const linkPopoverSessionRef = (0, import_react17.useRef)(null);
15859
- const addNavAfterAnchorRef = (0, import_react17.useRef)(null);
15860
- const editContentRef = (0, import_react17.useRef)({});
15861
- const aiSectionsRef = (0, import_react17.useRef)("");
15862
- const brandKitRef = (0, import_react17.useRef)("");
15863
- const stylesRef = (0, import_react17.useRef)("");
15864
- const pendingDeleteUndoRef = (0, import_react17.useRef)(null);
15865
- const [floatingPanel, setFloatingPanel] = (0, import_react17.useState)(null);
15866
- const floatingPanelOpenRef = (0, import_react17.useRef)(false);
15867
- const setFloatingPanelRef = (0, import_react17.useRef)(setFloatingPanel);
15868
- const [floatingPanelPos, setFloatingPanelPos] = (0, import_react17.useState)(null);
15869
- const [logoSizeDraft, setLogoSizeDraft] = (0, import_react17.useState)(null);
15870
- const [editorViewport, setEditorViewport] = (0, import_react17.useState)("desktop");
15871
- const [parentScrollSnap, setParentScrollSnap] = (0, import_react17.useState)(null);
15872
- const [sitePages, setSitePages] = (0, import_react17.useState)([]);
15873
- const [sectionsByPath, setSectionsByPath] = (0, import_react17.useState)({});
15874
- const sectionsPrefetchGenRef = (0, import_react17.useRef)(0);
15875
- const setLinkPopoverRef = (0, import_react17.useRef)(setLinkPopover);
15876
- const linkPopoverPanelRef = (0, import_react17.useRef)(null);
15877
- const linkPopoverOpenRef = (0, import_react17.useRef)(false);
15878
- const linkPopoverGraceUntilRef = (0, import_react17.useRef)(0);
14836
+ const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
14837
+ const floatingPanelOpenRef = (0, import_react16.useRef)(false);
14838
+ floatingPanelOpenRef.current = floatingPanel !== null;
14839
+ const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
14840
+ const [logoSizeDraft, setLogoSizeDraft] = (0, import_react16.useState)(null);
14841
+ const [editorViewport, setEditorViewport] = (0, import_react16.useState)("desktop");
14842
+ const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
14843
+ const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react16.useState)(null);
14844
+ const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react16.useState)(null);
14845
+ const footerDragRef = (0, import_react16.useRef)(null);
14846
+ const [footerDropSlots, setFooterDropSlots] = (0, import_react16.useState)([]);
14847
+ const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react16.useState)(null);
14848
+ const [draggedItemRect, setDraggedItemRect] = (0, import_react16.useState)(null);
14849
+ const footerPointerDragRef = (0, import_react16.useRef)(null);
14850
+ const suppressNextClickRef = (0, import_react16.useRef)(false);
14851
+ const suppressClickUntilRef = (0, import_react16.useRef)(0);
14852
+ const [linkPopover, setLinkPopover] = (0, import_react16.useState)(null);
14853
+ const linkPopoverSessionRef = (0, import_react16.useRef)(null);
14854
+ const addNavAfterAnchorRef = (0, import_react16.useRef)(null);
14855
+ const editContentRef = (0, import_react16.useRef)({});
14856
+ const aiSectionsRef = (0, import_react16.useRef)("");
14857
+ const pendingDeleteUndoRef = (0, import_react16.useRef)(null);
14858
+ const [sitePages, setSitePages] = (0, import_react16.useState)([]);
14859
+ const [sectionsByPath, setSectionsByPath] = (0, import_react16.useState)({});
14860
+ const sectionsPrefetchGenRef = (0, import_react16.useRef)(0);
14861
+ const setLinkPopoverRef = (0, import_react16.useRef)(setLinkPopover);
14862
+ const linkPopoverPanelRef = (0, import_react16.useRef)(null);
14863
+ const linkPopoverOpenRef = (0, import_react16.useRef)(false);
14864
+ const linkPopoverGraceUntilRef = (0, import_react16.useRef)(0);
15879
14865
  setLinkPopoverRef.current = setLinkPopover;
15880
- setFloatingPanelRef.current = setFloatingPanel;
15881
14866
  linkPopoverSessionRef.current = linkPopover;
15882
- floatingPanelOpenRef.current = Boolean(floatingPanel);
15883
- (0, import_react17.useEffect)(() => {
15884
- const syncViewport = () => {
15885
- const next = window.innerWidth <= 480 ? "mobile" : "desktop";
15886
- setEditorViewport((prev) => prev === next ? prev : next);
15887
- };
15888
- syncViewport();
15889
- window.addEventListener("resize", syncViewport);
15890
- return () => window.removeEventListener("resize", syncViewport);
15891
- }, []);
15892
14867
  const {
15893
14868
  navDragRef,
15894
14869
  navDropSlots,
@@ -15921,20 +14896,10 @@ function OhhwellsBridge() {
15921
14896
  getNavigationItemAnchor,
15922
14897
  isDragHandleDisabled
15923
14898
  });
15924
- const { sectionDropSlots, activeSectionDropIndex, isSectionDragging } = useSectionDrag({
15925
- isEditMode,
15926
- editContentRef,
15927
- postToParentRef,
15928
- parentScrollRef,
15929
- navDragRef,
15930
- footerDragRef,
15931
- suppressNextClickRef,
15932
- suppressClickUntilRef
15933
- });
15934
14899
  const bumpLinkPopoverGrace = () => {
15935
14900
  linkPopoverGraceUntilRef.current = Date.now() + 350;
15936
14901
  };
15937
- const runSectionsPrefetch = (0, import_react17.useCallback)((pages) => {
14902
+ const runSectionsPrefetch = (0, import_react16.useCallback)((pages) => {
15938
14903
  if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
15939
14904
  const gen = ++sectionsPrefetchGenRef.current;
15940
14905
  const paths = pages.map((p) => p.path);
@@ -15953,9 +14918,9 @@ function OhhwellsBridge() {
15953
14918
  );
15954
14919
  });
15955
14920
  }, [isEditMode, pathname]);
15956
- const runSectionsPrefetchRef = (0, import_react17.useRef)(runSectionsPrefetch);
14921
+ const runSectionsPrefetchRef = (0, import_react16.useRef)(runSectionsPrefetch);
15957
14922
  runSectionsPrefetchRef.current = runSectionsPrefetch;
15958
- (0, import_react17.useEffect)(() => {
14923
+ (0, import_react16.useEffect)(() => {
15959
14924
  if (!linkPopover) {
15960
14925
  document.documentElement.removeAttribute("data-ohw-link-popover-open");
15961
14926
  return;
@@ -15983,7 +14948,7 @@ function OhhwellsBridge() {
15983
14948
  document.documentElement.removeAttribute("data-ohw-link-popover-open");
15984
14949
  };
15985
14950
  }, [linkPopover, postToParent2]);
15986
- (0, import_react17.useEffect)(() => {
14951
+ (0, import_react16.useEffect)(() => {
15987
14952
  if (!isEditMode) return;
15988
14953
  const useFixtures = shouldUseDevFixtures();
15989
14954
  if (useFixtures) {
@@ -16007,14 +14972,14 @@ function OhhwellsBridge() {
16007
14972
  if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
16008
14973
  return () => window.removeEventListener("message", onSitePages);
16009
14974
  }, [isEditMode, postToParent2]);
16010
- (0, import_react17.useEffect)(() => {
14975
+ (0, import_react16.useEffect)(() => {
16011
14976
  if (!isEditMode || shouldUseDevFixtures()) return;
16012
14977
  void loadAllSectionsManifest().then((manifest) => {
16013
14978
  if (Object.keys(manifest).length === 0) return;
16014
14979
  setSectionsByPath((prev) => ({ ...manifest, ...prev }));
16015
14980
  });
16016
14981
  }, [isEditMode]);
16017
- (0, import_react17.useEffect)(() => {
14982
+ (0, import_react16.useEffect)(() => {
16018
14983
  const update = () => {
16019
14984
  const el = activeElRef.current ?? selectedElRef.current;
16020
14985
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
@@ -16038,10 +15003,10 @@ function OhhwellsBridge() {
16038
15003
  vvp.removeEventListener("resize", update);
16039
15004
  };
16040
15005
  }, []);
16041
- const refreshStateRules = (0, import_react17.useCallback)(() => {
15006
+ const refreshStateRules = (0, import_react16.useCallback)(() => {
16042
15007
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
16043
15008
  }, []);
16044
- const processConfigRequest = (0, import_react17.useCallback)((insertAfterVal) => {
15009
+ const processConfigRequest = (0, import_react16.useCallback)((insertAfterVal) => {
16045
15010
  const tracker = getSectionsTracker();
16046
15011
  let entries = [];
16047
15012
  try {
@@ -16064,7 +15029,7 @@ function OhhwellsBridge() {
16064
15029
  }
16065
15030
  window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
16066
15031
  }, [isEditMode]);
16067
- const deactivate = (0, import_react17.useCallback)(() => {
15032
+ const deactivate = (0, import_react16.useCallback)(() => {
16068
15033
  const el = activeElRef.current;
16069
15034
  if (!el) return;
16070
15035
  const isFormBlock = el.dataset.ohwEditable === "form";
@@ -16105,12 +15070,12 @@ function OhhwellsBridge() {
16105
15070
  setToolbarShowEditLink(false);
16106
15071
  postToParent2({ type: "ow:exit-edit" });
16107
15072
  }, [postToParent2]);
16108
- const clearSelectedAttr = (0, import_react17.useCallback)(() => {
15073
+ const clearSelectedAttr = (0, import_react16.useCallback)(() => {
16109
15074
  document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
16110
15075
  el.removeAttribute("data-ohw-selected");
16111
15076
  });
16112
15077
  }, []);
16113
- const deselect = (0, import_react17.useCallback)(() => {
15078
+ const deselect = (0, import_react16.useCallback)(() => {
16114
15079
  clearSelectedAttr();
16115
15080
  selectedElRef.current = null;
16116
15081
  selectedHrefKeyRef.current = null;
@@ -16139,11 +15104,11 @@ function OhhwellsBridge() {
16139
15104
  setToolbarVariant("none");
16140
15105
  }
16141
15106
  }, [clearSelectedAttr]);
16142
- const markSelected = (0, import_react17.useCallback)((el) => {
15107
+ const markSelected = (0, import_react16.useCallback)((el) => {
16143
15108
  clearSelectedAttr();
16144
15109
  el.setAttribute("data-ohw-selected", "");
16145
15110
  }, [clearSelectedAttr]);
16146
- const resolveHrefKeyElement = (0, import_react17.useCallback)((hrefKey) => {
15111
+ const resolveHrefKeyElement = (0, import_react16.useCallback)((hrefKey) => {
16147
15112
  if (isFooterHrefKey(hrefKey)) {
16148
15113
  return document.querySelector(
16149
15114
  `footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
@@ -16158,7 +15123,7 @@ function OhhwellsBridge() {
16158
15123
  `[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
16159
15124
  );
16160
15125
  }, []);
16161
- const resyncSelectedNavigationItem = (0, import_react17.useCallback)(() => {
15126
+ const resyncSelectedNavigationItem = (0, import_react16.useCallback)(() => {
16162
15127
  const hrefKey = selectedHrefKeyRef.current;
16163
15128
  if (hrefKey) {
16164
15129
  const link = resolveHrefKeyElement(hrefKey);
@@ -16196,7 +15161,7 @@ function OhhwellsBridge() {
16196
15161
  );
16197
15162
  }
16198
15163
  }, [resolveHrefKeyElement]);
16199
- const reselectNavigationItem = (0, import_react17.useCallback)((navAnchor) => {
15164
+ const reselectNavigationItem = (0, import_react16.useCallback)((navAnchor) => {
16200
15165
  selectedElRef.current = navAnchor;
16201
15166
  selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
16202
15167
  selectedFooterColAttrRef.current = null;
@@ -16227,7 +15192,7 @@ function OhhwellsBridge() {
16227
15192
  setToolbarShowEditLink(false);
16228
15193
  setActiveCommands(/* @__PURE__ */ new Set());
16229
15194
  }, [markSelected]);
16230
- const commitNavigationTextEdit = (0, import_react17.useCallback)((navAnchor) => {
15195
+ const commitNavigationTextEdit = (0, import_react16.useCallback)((navAnchor) => {
16231
15196
  const el = activeElRef.current;
16232
15197
  if (!el) return;
16233
15198
  const key = el.dataset.ohwKey;
@@ -16260,7 +15225,7 @@ function OhhwellsBridge() {
16260
15225
  postToParent2({ type: "ow:exit-edit" });
16261
15226
  reselectNavigationItem(navAnchor);
16262
15227
  }, [postToParent2, reselectNavigationItem]);
16263
- const handleAddTopLevelNavItem = (0, import_react17.useCallback)(() => {
15228
+ const handleAddTopLevelNavItem = (0, import_react16.useCallback)(() => {
16264
15229
  const items = listNavbarRootItems();
16265
15230
  addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
16266
15231
  deselectRef.current();
@@ -16272,7 +15237,7 @@ function OhhwellsBridge() {
16272
15237
  intent: "add-nav"
16273
15238
  });
16274
15239
  }, []);
16275
- const maybeWarnNavLinkDropdownConflict = (0, import_react17.useCallback)(
15240
+ const maybeWarnNavLinkDropdownConflict = (0, import_react16.useCallback)(
16276
15241
  (anchor) => {
16277
15242
  if (!isNavbarHrefKey(anchor.getAttribute("data-ohw-href-key"))) return;
16278
15243
  if (!navDropdownsOpenOnClick()) return;
@@ -16285,7 +15250,7 @@ function OhhwellsBridge() {
16285
15250
  },
16286
15251
  [postToParent2]
16287
15252
  );
16288
- const handleNavDropdownOpenChange = (0, import_react17.useCallback)((open) => {
15253
+ const handleNavDropdownOpenChange = (0, import_react16.useCallback)((open) => {
16289
15254
  const selected = selectedElRef.current;
16290
15255
  if (!selected || !isNavigationItem2(selected)) return;
16291
15256
  setNavGroupForceOpen(selected, open);
@@ -16297,7 +15262,7 @@ function OhhwellsBridge() {
16297
15262
  }
16298
15263
  });
16299
15264
  }, []);
16300
- const handleFooterHeadingVisibleChange = (0, import_react17.useCallback)(
15265
+ const handleFooterHeadingVisibleChange = (0, import_react16.useCallback)(
16301
15266
  (visible) => {
16302
15267
  const selected = selectedElRef.current;
16303
15268
  if (!selected || !isFooterFrameSelectionRef.current) return;
@@ -16321,7 +15286,7 @@ function OhhwellsBridge() {
16321
15286
  },
16322
15287
  [postToParent2]
16323
15288
  );
16324
- const enterEditOnNewItem = (0, import_react17.useCallback)((anchor) => {
15289
+ const enterEditOnNewItem = (0, import_react16.useCallback)((anchor) => {
16325
15290
  const label = anchor.querySelector('[data-ohw-editable="text"]');
16326
15291
  if (!label) {
16327
15292
  selectRef.current(anchor);
@@ -16330,7 +15295,7 @@ function OhhwellsBridge() {
16330
15295
  setNavGroupForceOpen(anchor, true);
16331
15296
  activateRef.current(label);
16332
15297
  }, []);
16333
- const handleAddChildItem = (0, import_react17.useCallback)(() => {
15298
+ const handleAddChildItem = (0, import_react16.useCallback)(() => {
16334
15299
  const selected = selectedElRef.current;
16335
15300
  if (!selected) return;
16336
15301
  const socialsRow = isSocialsRow(selected) ? selected : findSocialsRow(selected);
@@ -16442,7 +15407,7 @@ function OhhwellsBridge() {
16442
15407
  enterEditOnNewItem(result.anchor);
16443
15408
  });
16444
15409
  }, [enterEditOnNewItem, isFooterFrameSelection, maybeWarnNavLinkDropdownConflict, postToParent2]);
16445
- const handleAddFooterColumn = (0, import_react17.useCallback)(() => {
15410
+ const handleAddFooterColumn = (0, import_react16.useCallback)(() => {
16446
15411
  if (!canAddFooterColumn()) {
16447
15412
  postToParent2({
16448
15413
  type: "ow:toast",
@@ -16463,7 +15428,7 @@ function OhhwellsBridge() {
16463
15428
  selectRef.current(result.firstLink);
16464
15429
  });
16465
15430
  }, [postToParent2]);
16466
- const clearFooterDragVisuals = (0, import_react17.useCallback)(() => {
15431
+ const clearFooterDragVisuals = (0, import_react16.useCallback)(() => {
16467
15432
  footerDragRef.current = null;
16468
15433
  setSiblingHintRects([]);
16469
15434
  setFooterDropSlots([]);
@@ -16472,7 +15437,7 @@ function OhhwellsBridge() {
16472
15437
  setIsItemDragging(false);
16473
15438
  unlockFooterDragInteraction();
16474
15439
  }, []);
16475
- const refreshFooterDragVisuals = (0, import_react17.useCallback)((session, activeSlot, clientX, clientY) => {
15440
+ const refreshFooterDragVisuals = (0, import_react16.useCallback)((session, activeSlot, clientX, clientY) => {
16476
15441
  const dragged = session.draggedEl;
16477
15442
  setDraggedItemRect(dragged.getBoundingClientRect());
16478
15443
  if (typeof clientX === "number" && typeof clientY === "number") {
@@ -16504,13 +15469,13 @@ function OhhwellsBridge() {
16504
15469
  const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
16505
15470
  setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
16506
15471
  }, []);
16507
- const refreshFooterDragVisualsRef = (0, import_react17.useRef)(refreshFooterDragVisuals);
15472
+ const refreshFooterDragVisualsRef = (0, import_react16.useRef)(refreshFooterDragVisuals);
16508
15473
  refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
16509
- const commitFooterDragRef = (0, import_react17.useRef)(() => {
15474
+ const commitFooterDragRef = (0, import_react16.useRef)(() => {
16510
15475
  });
16511
- const beginFooterDragRef = (0, import_react17.useRef)(() => {
15476
+ const beginFooterDragRef = (0, import_react16.useRef)(() => {
16512
15477
  });
16513
- const beginFooterDrag = (0, import_react17.useCallback)(
15478
+ const beginFooterDrag = (0, import_react16.useCallback)(
16514
15479
  (session) => {
16515
15480
  const rect = session.draggedEl.getBoundingClientRect();
16516
15481
  session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
@@ -16530,7 +15495,7 @@ function OhhwellsBridge() {
16530
15495
  [refreshFooterDragVisuals]
16531
15496
  );
16532
15497
  beginFooterDragRef.current = beginFooterDrag;
16533
- const commitFooterDrag = (0, import_react17.useCallback)(
15498
+ const commitFooterDrag = (0, import_react16.useCallback)(
16534
15499
  (clientX, clientY) => {
16535
15500
  const session = footerDragRef.current;
16536
15501
  if (!session) {
@@ -16658,7 +15623,7 @@ function OhhwellsBridge() {
16658
15623
  [clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
16659
15624
  );
16660
15625
  commitFooterDragRef.current = commitFooterDrag;
16661
- const startFooterLinkDrag = (0, import_react17.useCallback)(
15626
+ const startFooterLinkDrag = (0, import_react16.useCallback)(
16662
15627
  (anchor, clientX, clientY, wasSelected) => {
16663
15628
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
16664
15629
  if (!hrefKey) return false;
@@ -16694,7 +15659,7 @@ function OhhwellsBridge() {
16694
15659
  },
16695
15660
  [beginFooterDrag]
16696
15661
  );
16697
- const startFooterColumnDrag = (0, import_react17.useCallback)(
15662
+ const startFooterColumnDrag = (0, import_react16.useCallback)(
16698
15663
  (columnEl, clientX, clientY, wasSelected) => {
16699
15664
  const columns = listFooterColumns();
16700
15665
  const idx = columns.indexOf(columnEl);
@@ -16714,7 +15679,7 @@ function OhhwellsBridge() {
16714
15679
  },
16715
15680
  [beginFooterDrag]
16716
15681
  );
16717
- const handleItemDragStart = (0, import_react17.useCallback)(
15682
+ const handleItemDragStart = (0, import_react16.useCallback)(
16718
15683
  (e) => {
16719
15684
  const selected = selectedElRef.current;
16720
15685
  if (!selected) {
@@ -16734,7 +15699,7 @@ function OhhwellsBridge() {
16734
15699
  },
16735
15700
  [startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
16736
15701
  );
16737
- const handleItemDragEnd = (0, import_react17.useCallback)(
15702
+ const handleItemDragEnd = (0, import_react16.useCallback)(
16738
15703
  (e) => {
16739
15704
  if (footerDragRef.current) {
16740
15705
  const x = e?.clientX;
@@ -16760,7 +15725,7 @@ function OhhwellsBridge() {
16760
15725
  },
16761
15726
  [commitFooterDrag, commitNavDrag, navDragRef]
16762
15727
  );
16763
- const handleItemChromePointerDown = (0, import_react17.useCallback)((e) => {
15728
+ const handleItemChromePointerDown = (0, import_react16.useCallback)((e) => {
16764
15729
  if (e.button !== 0) return;
16765
15730
  const selected = selectedElRef.current;
16766
15731
  if (!selected) return;
@@ -16791,7 +15756,7 @@ function OhhwellsBridge() {
16791
15756
  }
16792
15757
  if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
16793
15758
  }, [armNavPressFromChrome]);
16794
- const handleItemChromeClick = (0, import_react17.useCallback)((clientX, clientY) => {
15759
+ const handleItemChromeClick = (0, import_react16.useCallback)((clientX, clientY) => {
16795
15760
  if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
16796
15761
  suppressNextClickRef.current = false;
16797
15762
  return;
@@ -16804,7 +15769,7 @@ function OhhwellsBridge() {
16804
15769
  }, []);
16805
15770
  reselectNavigationItemRef.current = reselectNavigationItem;
16806
15771
  commitNavigationTextEditRef.current = commitNavigationTextEdit;
16807
- const select = (0, import_react17.useCallback)((anchor) => {
15772
+ const select = (0, import_react16.useCallback)((anchor) => {
16808
15773
  if (!isNavigationItem2(anchor)) return;
16809
15774
  if (activeElRef.current) deactivate();
16810
15775
  aiSectionApiRef.current?.selectFromElement(anchor);
@@ -16847,7 +15812,7 @@ function OhhwellsBridge() {
16847
15812
  setFloatingPanel(null);
16848
15813
  setLogoSizeDraft(null);
16849
15814
  }, [deactivate, markSelected]);
16850
- const selectFrame = (0, import_react17.useCallback)((el) => {
15815
+ const selectFrame = (0, import_react16.useCallback)((el) => {
16851
15816
  if (!isNavigationContainer(el)) return;
16852
15817
  if (activeElRef.current) deactivate();
16853
15818
  aiSectionApiRef.current?.selectFromElement(el);
@@ -16898,7 +15863,7 @@ function OhhwellsBridge() {
16898
15863
  setFloatingPanel(null);
16899
15864
  setLogoSizeDraft(null);
16900
15865
  }, [deactivate, markSelected, postToParent2]);
16901
- const selectLogo = (0, import_react17.useCallback)(
15866
+ const selectLogo = (0, import_react16.useCallback)(
16902
15867
  (logoEl) => {
16903
15868
  if (activeElRef.current) deactivate();
16904
15869
  selectedElRef.current = logoEl;
@@ -16927,7 +15892,7 @@ function OhhwellsBridge() {
16927
15892
  },
16928
15893
  [deactivate, markSelected]
16929
15894
  );
16930
- const openLogoSizePanel = (0, import_react17.useCallback)((logoEl) => {
15895
+ const openLogoSizePanel = (0, import_react16.useCallback)((logoEl) => {
16931
15896
  const placement = getLogoPlacement(logoEl);
16932
15897
  const draft = readLogoSizeState(editContentRef.current, placement);
16933
15898
  setLogoSizeDraft(draft);
@@ -16940,7 +15905,7 @@ function OhhwellsBridge() {
16940
15905
  placement
16941
15906
  });
16942
15907
  }, []);
16943
- const openSocialsDisplayPanel = (0, import_react17.useCallback)((row) => {
15908
+ const openSocialsDisplayPanel = (0, import_react16.useCallback)((row) => {
16944
15909
  setParentScrollSnap(parentScrollRef.current);
16945
15910
  setFloatingPanel({
16946
15911
  key: "socials-display",
@@ -16950,7 +15915,7 @@ function OhhwellsBridge() {
16950
15915
  row
16951
15916
  });
16952
15917
  }, []);
16953
- const changeSocialsDisplay = (0, import_react17.useCallback)(
15918
+ const changeSocialsDisplay = (0, import_react16.useCallback)(
16954
15919
  (row, next) => {
16955
15920
  if (next.icon) {
16956
15921
  const missing = socialsMissingIcons(row);
@@ -16973,17 +15938,36 @@ function OhhwellsBridge() {
16973
15938
  },
16974
15939
  []
16975
15940
  );
16976
- const closeFloatingPanelOnly = (0, import_react17.useCallback)(() => {
15941
+ const closeFloatingPanelOnly = (0, import_react16.useCallback)(() => {
16977
15942
  setFloatingPanel(null);
16978
15943
  setLogoSizeDraft(null);
16979
15944
  }, []);
16980
15945
  closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
16981
- const closeFloatingPanelAndDeselect = (0, import_react17.useCallback)(() => {
15946
+ const closeFloatingPanelAndDeselect = (0, import_react16.useCallback)(() => {
16982
15947
  setFloatingPanel(null);
16983
15948
  setLogoSizeDraft(null);
16984
15949
  deselectRef.current();
16985
15950
  }, []);
16986
- const persistLogoSizeDraft = (0, import_react17.useCallback)(
15951
+ (0, import_react16.useEffect)(() => {
15952
+ const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
15953
+ if (!session || !logoSizeDraft) {
15954
+ postToParentRef.current({ type: "ow:logo-size-panel", open: false });
15955
+ return;
15956
+ }
15957
+ postToParentRef.current({
15958
+ type: "ow:logo-size-panel",
15959
+ open: true,
15960
+ title: session.title,
15961
+ context: session.context ?? "",
15962
+ placement: session.placement,
15963
+ viewport: editorViewport,
15964
+ mobileFollowing: logoSizeDraft.mobileFollowing,
15965
+ sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
15966
+ min: LOGO_SIZE_MIN,
15967
+ max: LOGO_SIZE_MAX
15968
+ });
15969
+ }, [floatingPanel, logoSizeDraft, editorViewport]);
15970
+ const persistLogoSizeDraft = (0, import_react16.useCallback)(
16987
15971
  (placement, draft) => {
16988
15972
  const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
16989
15973
  const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
@@ -17023,7 +16007,7 @@ function OhhwellsBridge() {
17023
16007
  },
17024
16008
  [postToParent2]
17025
16009
  );
17026
- const activate = (0, import_react17.useCallback)((el, options) => {
16010
+ const activate = (0, import_react16.useCallback)((el, options) => {
17027
16011
  if (activeElRef.current === el) return;
17028
16012
  if (isIconEditable(el)) return;
17029
16013
  if (el.hasAttribute("data-ohw-social-label")) return;
@@ -17107,8 +16091,8 @@ function OhhwellsBridge() {
17107
16091
  openLogoSizePanelRef.current = openLogoSizePanel;
17108
16092
  deselectRef.current = deselect;
17109
16093
  closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
17110
- const lastSiteWideScopeRef = (0, import_react17.useRef)(null);
17111
- (0, import_react17.useEffect)(() => {
16094
+ const lastSiteWideScopeRef = (0, import_react16.useRef)(null);
16095
+ (0, import_react16.useEffect)(() => {
17112
16096
  if (!isEditMode) {
17113
16097
  if (lastSiteWideScopeRef.current !== false) {
17114
16098
  lastSiteWideScopeRef.current = false;
@@ -17134,34 +16118,22 @@ function OhhwellsBridge() {
17134
16118
  isFooterFrameSelection,
17135
16119
  postToParent2
17136
16120
  ]);
17137
- (0, import_react17.useLayoutEffect)(() => {
16121
+ (0, import_react16.useLayoutEffect)(() => {
17138
16122
  if (!subdomain || isEditMode) {
17139
16123
  setFetchState("done");
17140
16124
  return;
17141
16125
  }
17142
16126
  const applyContent = (content) => {
17143
16127
  const imageLoads = [];
17144
- if (typeof content[BRAND_KIT_KEY] === "string") {
17145
- brandKitRef.current = content[BRAND_KIT_KEY];
17146
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
17147
- }
17148
16128
  if (typeof content[AI_SECTIONS_KEY] === "string") {
17149
16129
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
17150
16130
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
17151
16131
  }
17152
- if (typeof content[STYLE_STORE_KEY] === "string") {
17153
- stylesRef.current = content[STYLE_STORE_KEY];
17154
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
17155
- }
17156
- applyBrandChrome(content);
17157
16132
  for (const [key, val] of Object.entries(content)) {
17158
16133
  if (key === "__ohw_sections") continue;
17159
16134
  if (key === AI_SECTIONS_KEY) continue;
17160
16135
  if (key === LOGO_PLACEHOLDER_KEY) continue;
17161
16136
  if (LOGO_IMAGE_KEYS.includes(key)) continue;
17162
- if (key === BRAND_KIT_KEY) continue;
17163
- if (key === STYLE_STORE_KEY) continue;
17164
- if (BRAND_CHROME_KEYS.has(key)) continue;
17165
16137
  if (applyVideoSettingNode(key, val)) continue;
17166
16138
  if (applyCarouselNode(key, val)) continue;
17167
16139
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -17219,9 +16191,7 @@ function OhhwellsBridge() {
17219
16191
  let cancelled = false;
17220
16192
  setFetchState("loading");
17221
16193
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
17222
- const initialPath = pathname;
17223
- fetchedContentPaths.add(`${subdomain}::${initialPath}`);
17224
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
16194
+ fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
17225
16195
  if (cancelled) return;
17226
16196
  const content = data?.content ?? {};
17227
16197
  contentCache.set(subdomain, content);
@@ -17234,7 +16204,7 @@ function OhhwellsBridge() {
17234
16204
  cancelled = true;
17235
16205
  };
17236
16206
  }, [subdomain, isEditMode]);
17237
- (0, import_react17.useEffect)(() => {
16207
+ (0, import_react16.useEffect)(() => {
17238
16208
  if (!isEditMode) return;
17239
16209
  const resolveIndex = (form, clientY) => {
17240
16210
  const wrappers = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== fieldDragRef.current?.key);
@@ -17275,7 +16245,7 @@ function OhhwellsBridge() {
17275
16245
  window.removeEventListener("drop", onDrop, true);
17276
16246
  };
17277
16247
  }, [buildFieldDropSlots, isEditMode, persistFields, selectField]);
17278
- (0, import_react17.useEffect)(() => {
16248
+ (0, import_react16.useEffect)(() => {
17279
16249
  if (!isEditMode) return;
17280
16250
  const mark = () => document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
17281
16251
  markFormFields(form);
@@ -17287,7 +16257,7 @@ function OhhwellsBridge() {
17287
16257
  });
17288
16258
  return () => observer.disconnect();
17289
16259
  }, [isEditMode, fetchState, pathname]);
17290
- (0, import_react17.useEffect)(() => {
16260
+ (0, import_react16.useEffect)(() => {
17291
16261
  if (!isEditMode) return;
17292
16262
  let saveTimer = null;
17293
16263
  const onInput = (e) => {
@@ -17309,14 +16279,14 @@ function OhhwellsBridge() {
17309
16279
  document.addEventListener("input", onInput, true);
17310
16280
  return () => document.removeEventListener("input", onInput, true);
17311
16281
  }, [isEditMode, persistFields]);
17312
- (0, import_react17.useEffect)(() => {
16282
+ (0, import_react16.useEffect)(() => {
17313
16283
  if (isEditMode || fetchState !== "done") return;
17314
16284
  const content = contentCache.get(subdomain) ?? {};
17315
16285
  document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
17316
16286
  reconcileFieldsFromContent(form, content);
17317
16287
  });
17318
16288
  }, [isEditMode, fetchState, subdomain]);
17319
- (0, import_react17.useEffect)(() => {
16289
+ (0, import_react16.useEffect)(() => {
17320
16290
  if (!isEditMode) return;
17321
16291
  const swallow = (e) => {
17322
16292
  const target = e.target;
@@ -17325,12 +16295,12 @@ function OhhwellsBridge() {
17325
16295
  document.addEventListener("submit", swallow, true);
17326
16296
  return () => document.removeEventListener("submit", swallow, true);
17327
16297
  }, [isEditMode]);
17328
- (0, import_react17.useEffect)(() => {
16298
+ (0, import_react16.useEffect)(() => {
17329
16299
  if (isEditMode || fetchState !== "done") return;
17330
16300
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
17331
16301
  bindPublishedForms(apiUrl, subdomain, contentCache.get(subdomain) ?? {});
17332
16302
  }, [isEditMode, fetchState, subdomain]);
17333
- (0, import_react17.useEffect)(() => {
16303
+ (0, import_react16.useEffect)(() => {
17334
16304
  if (!subdomain || isEditMode) return;
17335
16305
  let debounceTimer = null;
17336
16306
  let observer = null;
@@ -17341,21 +16311,10 @@ function OhhwellsBridge() {
17341
16311
  initSectionInstancesFromContent(content, window.location.pathname);
17342
16312
  observer?.disconnect();
17343
16313
  try {
17344
- applyBrandChrome(content);
17345
- if (typeof content[BRAND_KIT_KEY] === "string") {
17346
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
17347
- }
17348
- if (typeof content[STYLE_STORE_KEY] === "string") {
17349
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
17350
- }
17351
16314
  for (const [key, val] of Object.entries(content)) {
17352
16315
  if (key === "__ohw_sections") continue;
17353
16316
  if (key === LOGO_PLACEHOLDER_KEY) continue;
17354
16317
  if (LOGO_IMAGE_KEYS.includes(key)) continue;
17355
- if (key === BRAND_KIT_KEY) continue;
17356
- if (key === STYLE_STORE_KEY) continue;
17357
- if (key === STYLE_STORE_KEY) continue;
17358
- if (BRAND_CHROME_KEYS.has(key)) continue;
17359
16318
  if (applyVideoSettingNode(key, val)) continue;
17360
16319
  if (applyCarouselNode(key, val)) continue;
17361
16320
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -17398,17 +16357,6 @@ function OhhwellsBridge() {
17398
16357
  debounceTimer = setTimeout(applyFromCache, 150);
17399
16358
  };
17400
16359
  applyFromCache();
17401
- const pathCacheKey = `${subdomain}::${pathname}`;
17402
- if (!fetchedContentPaths.has(pathCacheKey)) {
17403
- fetchedContentPaths.add(pathCacheKey);
17404
- const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
17405
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
17406
- if (!data?.content) return;
17407
- contentCache.set(subdomain, data.content);
17408
- applyFromCache();
17409
- }).catch(() => {
17410
- });
17411
- }
17412
16360
  observer = new MutationObserver(scheduleApply);
17413
16361
  observer.observe(document.body, { childList: true, subtree: true });
17414
16362
  return () => {
@@ -17416,16 +16364,16 @@ function OhhwellsBridge() {
17416
16364
  if (debounceTimer) clearTimeout(debounceTimer);
17417
16365
  };
17418
16366
  }, [subdomain, isEditMode, pathname]);
17419
- (0, import_react17.useLayoutEffect)(() => {
16367
+ (0, import_react16.useLayoutEffect)(() => {
17420
16368
  const el = document.getElementById("ohw-loader");
17421
16369
  if (!el) return;
17422
16370
  const visible = Boolean(subdomain) && fetchState !== "done";
17423
16371
  el.style.display = visible ? "flex" : "none";
17424
16372
  }, [subdomain, fetchState]);
17425
- (0, import_react17.useEffect)(() => {
16373
+ (0, import_react16.useEffect)(() => {
17426
16374
  postToParent2({ type: "ow:navigation", path: pathname });
17427
16375
  }, [pathname, postToParent2]);
17428
- (0, import_react17.useEffect)(() => {
16376
+ (0, import_react16.useEffect)(() => {
17429
16377
  if (!isEditMode) return;
17430
16378
  if (linkPopoverSessionRef.current?.intent === "add-nav") return;
17431
16379
  if (document.querySelector("[data-ohw-section-picker]")) return;
@@ -17433,7 +16381,7 @@ function OhhwellsBridge() {
17433
16381
  deselectRef.current();
17434
16382
  deactivateRef.current();
17435
16383
  }, [pathname, isEditMode]);
17436
- (0, import_react17.useEffect)(() => {
16384
+ (0, import_react16.useEffect)(() => {
17437
16385
  const contentForNav = () => {
17438
16386
  if (isEditMode) return editContentRef.current;
17439
16387
  if (!subdomain) return {};
@@ -17500,36 +16448,31 @@ function OhhwellsBridge() {
17500
16448
  observer?.disconnect();
17501
16449
  };
17502
16450
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
17503
- (0, import_react17.useEffect)(() => {
16451
+ (0, import_react16.useEffect)(() => {
17504
16452
  if (!isEditMode) return;
17505
- let lastPosted = 0;
17506
16453
  const measure = () => {
17507
16454
  const h = document.body.scrollHeight;
17508
- if (h > 50 && Math.abs(h - lastPosted) > 1) {
17509
- lastPosted = h;
17510
- postToParent2({ type: "ow:height", height: h });
17511
- }
17512
- };
17513
- let raf = null;
17514
- const schedule = () => {
17515
- if (raf != null) return;
17516
- raf = requestAnimationFrame(() => {
17517
- raf = null;
17518
- measure();
17519
- });
16455
+ if (h > 50) postToParent2({ type: "ow:height", height: h });
17520
16456
  };
17521
16457
  const t1 = setTimeout(measure, 50);
17522
16458
  const t2 = setTimeout(measure, 500);
17523
- const ro = new ResizeObserver(schedule);
17524
- ro.observe(document.body);
16459
+ let lastWidth = window.innerWidth;
16460
+ let resizeTimer = null;
16461
+ const handleResize = () => {
16462
+ if (window.innerWidth === lastWidth) return;
16463
+ lastWidth = window.innerWidth;
16464
+ if (resizeTimer) clearTimeout(resizeTimer);
16465
+ resizeTimer = setTimeout(measure, 150);
16466
+ };
16467
+ window.addEventListener("resize", handleResize);
17525
16468
  return () => {
17526
16469
  clearTimeout(t1);
17527
16470
  clearTimeout(t2);
17528
- if (raf != null) cancelAnimationFrame(raf);
17529
- ro.disconnect();
16471
+ if (resizeTimer) clearTimeout(resizeTimer);
16472
+ window.removeEventListener("resize", handleResize);
17530
16473
  };
17531
16474
  }, [pathname, isEditMode, postToParent2]);
17532
- (0, import_react17.useEffect)(() => {
16475
+ (0, import_react16.useEffect)(() => {
17533
16476
  if (!subdomainFromQuery || isEditMode) return;
17534
16477
  const handleClick = (e) => {
17535
16478
  const anchor = e.target.closest("a");
@@ -17545,7 +16488,7 @@ function OhhwellsBridge() {
17545
16488
  document.addEventListener("click", handleClick, true);
17546
16489
  return () => document.removeEventListener("click", handleClick, true);
17547
16490
  }, [subdomainFromQuery, isEditMode, router]);
17548
- (0, import_react17.useEffect)(() => {
16491
+ (0, import_react16.useEffect)(() => {
17549
16492
  if (!isEditMode) {
17550
16493
  editStylesRef.current?.base.remove();
17551
16494
  editStylesRef.current?.forceHover.remove();
@@ -17707,12 +16650,10 @@ function OhhwellsBridge() {
17707
16650
  return;
17708
16651
  }
17709
16652
  const target = e.target;
17710
- if (target.closest("[data-ohw-ai-review]")) return;
17711
16653
  if (target.closest("[data-ohw-toolbar]")) return;
17712
16654
  if (target.closest("[data-ohw-state-toggle]")) return;
17713
16655
  if (target.closest("[data-ohw-max-badge]")) return;
17714
16656
  if (isInsideLinkEditor(target)) return;
17715
- if (isInsideFloatingPanel(target)) return;
17716
16657
  if (target.closest("[data-ohw-form-toolbar]")) return;
17717
16658
  if (target.closest(
17718
16659
  '[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
@@ -17986,12 +16927,10 @@ function OhhwellsBridge() {
17986
16927
  };
17987
16928
  const handleDblClick = (e) => {
17988
16929
  const target = e.target;
17989
- if (target.closest("[data-ohw-ai-review]")) return;
17990
16930
  if (target.closest("[data-ohw-toolbar]")) return;
17991
16931
  if (target.closest("[data-ohw-state-toggle]")) return;
17992
16932
  if (target.closest("[data-ohw-max-badge]")) return;
17993
16933
  if (isInsideLinkEditor(target)) return;
17994
- if (isInsideFloatingPanel(target)) return;
17995
16934
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
17996
16935
  return;
17997
16936
  }
@@ -18032,14 +16971,11 @@ function OhhwellsBridge() {
18032
16971
  setSiblingHintRects([]);
18033
16972
  return;
18034
16973
  }
18035
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
16974
+ if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || target.closest("[data-ohw-floating-panel]")) {
18036
16975
  hoveredItemElRef.current = null;
18037
16976
  setHoveredItemRect(null);
18038
16977
  hoveredNavContainerRef.current = null;
18039
16978
  setHoveredNavContainerRect(null);
18040
- siblingHintElRef.current = null;
18041
- setSiblingHintRect(null);
18042
- setSiblingHintRects([]);
18043
16979
  return;
18044
16980
  }
18045
16981
  {
@@ -18148,6 +17084,7 @@ function OhhwellsBridge() {
18148
17084
  hoveredNavContainerRef.current = null;
18149
17085
  setHoveredNavContainerRect(null);
18150
17086
  hoveredItemElRef.current = editable;
17087
+ setHoveredItemRect(editable.getBoundingClientRect());
18151
17088
  }
18152
17089
  }
18153
17090
  }
@@ -18444,7 +17381,7 @@ function OhhwellsBridge() {
18444
17381
  }
18445
17382
  };
18446
17383
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
18447
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
17384
+ if (linkPopoverOpenRef.current) {
18448
17385
  if (hoveredImageRef.current) {
18449
17386
  hoveredImageRef.current = null;
18450
17387
  hoveredImageHasTextOverlapRef.current = false;
@@ -18460,6 +17397,11 @@ function OhhwellsBridge() {
18460
17397
  probeNavigationHoverAt(x, y);
18461
17398
  return;
18462
17399
  }
17400
+ if (isPointOverLogo(x, y)) {
17401
+ dismissImageHover();
17402
+ probeNavigationHoverAt(x, y);
17403
+ return;
17404
+ }
18463
17405
  const overMoreMenu = document.elementFromPoint(x, y)?.closest?.(
18464
17406
  '[data-ohw-more-menu], [data-slot="dropdown-menu-content"], [data-slot="dropdown-menu-item"]'
18465
17407
  );
@@ -18698,7 +17640,7 @@ function OhhwellsBridge() {
18698
17640
  }
18699
17641
  };
18700
17642
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
18701
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
17643
+ if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
18702
17644
  if (activeStateElRef.current) {
18703
17645
  activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
18704
17646
  activeStateElRef.current = null;
@@ -18773,7 +17715,8 @@ function OhhwellsBridge() {
18773
17715
  };
18774
17716
  const handleMouseMove = (e) => {
18775
17717
  const { clientX, clientY } = e;
18776
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
17718
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
17719
+ if (isOverEditorChrome(clientX, clientY)) {
18777
17720
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
18778
17721
  formHoverElRef.current = null;
18779
17722
  setFormHoverRect(null);
@@ -18781,12 +17724,6 @@ function OhhwellsBridge() {
18781
17724
  setHoveredItemRect(null);
18782
17725
  hoveredNavContainerRef.current = null;
18783
17726
  setHoveredNavContainerRect(null);
18784
- siblingHintElRef.current = null;
18785
- setSiblingHintRect(null);
18786
- setSiblingHintRects([]);
18787
- dismissImageHover();
18788
- clearImageHover();
18789
- setSectionGap(null);
18790
17727
  return;
18791
17728
  }
18792
17729
  probeSectionGapAt(clientX, clientY);
@@ -18797,11 +17734,7 @@ function OhhwellsBridge() {
18797
17734
  if (e.data?.type !== "ow:pointer-sync") return;
18798
17735
  const { clientX, clientY } = e.data;
18799
17736
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
18800
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
18801
- dismissImageHover();
18802
- clearImageHover();
18803
- return;
18804
- }
17737
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
18805
17738
  probeSectionGapAt(clientX, clientY);
18806
17739
  probeImageAt(clientX, clientY);
18807
17740
  probeHoverCardsAt(clientX, clientY);
@@ -19047,19 +17980,10 @@ function OhhwellsBridge() {
19047
17980
  if (e.data?.type !== "ow:hydrate") return;
19048
17981
  const content = e.data.content;
19049
17982
  if (!content) return;
19050
- if (typeof content[BRAND_KIT_KEY] === "string") {
19051
- brandKitRef.current = content[BRAND_KIT_KEY];
19052
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
19053
- }
19054
17983
  if (typeof content[AI_SECTIONS_KEY] === "string") {
19055
17984
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
19056
17985
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
19057
17986
  }
19058
- if (typeof content[STYLE_STORE_KEY] === "string") {
19059
- stylesRef.current = content[STYLE_STORE_KEY];
19060
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
19061
- }
19062
- applyBrandChrome(content);
19063
17987
  let sectionsJson = null;
19064
17988
  for (const [key, val] of Object.entries(content)) {
19065
17989
  if (key === "__ohw_sections") {
@@ -19069,9 +17993,6 @@ function OhhwellsBridge() {
19069
17993
  if (key === AI_SECTIONS_KEY) continue;
19070
17994
  if (key === LOGO_PLACEHOLDER_KEY) continue;
19071
17995
  if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
19072
- if (key === BRAND_KIT_KEY) continue;
19073
- if (key === STYLE_STORE_KEY) continue;
19074
- if (BRAND_CHROME_KEYS.has(key)) continue;
19075
17996
  if (applyVideoSettingNode(key, val)) continue;
19076
17997
  if (applyCarouselNode(key, val)) continue;
19077
17998
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -19173,10 +18094,7 @@ function OhhwellsBridge() {
19173
18094
  const payload = e.data.payload;
19174
18095
  if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
19175
18096
  const previous = aiSectionsRef.current;
19176
- const nextState = applyTreeToState(parseAiSectionsState(previous), {
19177
- ...payload,
19178
- path: payload.path ?? window.location.pathname
19179
- });
18097
+ const nextState = applyTreeToState(parseAiSectionsState(previous), payload);
19180
18098
  const nextValue = serializeAiSectionsState(nextState);
19181
18099
  aiSectionsRef.current = nextValue;
19182
18100
  applyAiSectionsToDom(nextState);
@@ -19213,55 +18131,12 @@ function OhhwellsBridge() {
19213
18131
  const value = typeof e.data.value === "string" ? e.data.value : "";
19214
18132
  aiSectionsRef.current = value;
19215
18133
  applyAiSectionsToDom(parseAiSectionsState(value));
19216
- applyStylesToDom(parseStyleStore(stylesRef.current));
19217
18134
  const restoredHeight = document.documentElement.scrollHeight;
19218
18135
  if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
19219
18136
  postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
19220
18137
  postAiSectionsChanged();
19221
18138
  };
19222
18139
  window.addEventListener("message", handleAiSetSections);
19223
- const handleMoveSection = (e) => {
19224
- if (e.data?.type !== "ow:move-section") return;
19225
- const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
19226
- const direction = e.data.direction === "up" || e.data.direction === "down" ? e.data.direction : null;
19227
- if (!instanceId || !direction) return;
19228
- const entries = moveSectionInstance(instanceId, direction, window.location.pathname);
19229
- if (!entries) return;
19230
- const orderJson = JSON.stringify(entries);
19231
- editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
19232
- postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
19233
- window.dispatchEvent(new Event("resize"));
19234
- };
19235
- window.addEventListener("message", handleMoveSection);
19236
- const handleAiSetBrand = (e) => {
19237
- if (e.data?.type !== "ow:ai-set-brand") return;
19238
- const value = typeof e.data.value === "string" ? e.data.value : "";
19239
- const previous = brandKitRef.current;
19240
- brandKitRef.current = value;
19241
- applyBrandToDom(parseBrandKit(value));
19242
- if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
19243
- applyStylesToDom(parseStyleStore(stylesRef.current));
19244
- postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
19245
- postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
19246
- };
19247
- window.addEventListener("message", handleAiSetBrand);
19248
- const handleAiSetStyles = (e) => {
19249
- if (e.data?.type !== "ow:ai-set-styles") return;
19250
- const value = typeof e.data.value === "string" ? e.data.value : "";
19251
- const previous = stylesRef.current;
19252
- stylesRef.current = value;
19253
- applyStylesToDom(parseStyleStore(value));
19254
- postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
19255
- postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
19256
- };
19257
- window.addEventListener("message", handleAiSetStyles);
19258
- const handleGetBrand = (e) => {
19259
- if (e.data?.type !== "ow:get-brand") return;
19260
- const template = deriveTemplateBrand();
19261
- const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
19262
- postToParentRef.current({ type: "ow:brand-value", value });
19263
- };
19264
- window.addEventListener("message", handleGetBrand);
19265
18140
  const handleDeactivate = (e) => {
19266
18141
  if (e.data?.type !== "ow:deactivate") return;
19267
18142
  if (Date.now() < linkPopoverGraceUntilRef.current) return;
@@ -19270,12 +18145,6 @@ function OhhwellsBridge() {
19270
18145
  closeLinkPopoverRef.current();
19271
18146
  return;
19272
18147
  }
19273
- if (floatingPanelOpenRef.current) {
19274
- setFloatingPanelRef.current(null);
19275
- deselectRef.current();
19276
- deactivateRef.current();
19277
- return;
19278
- }
19279
18148
  deselectRef.current();
19280
18149
  deactivateRef.current();
19281
18150
  };
@@ -19522,12 +18391,6 @@ function OhhwellsBridge() {
19522
18391
  if (aiSectionsRef.current) {
19523
18392
  nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
19524
18393
  }
19525
- if (stylesRef.current) {
19526
- nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
19527
- }
19528
- if (brandKitRef.current) {
19529
- nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
19530
- }
19531
18394
  document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
19532
18395
  const formKey = formKeyOf(form);
19533
18396
  if (!formKey) return;
@@ -19545,12 +18408,8 @@ function OhhwellsBridge() {
19545
18408
  if (inserted) {
19546
18409
  const tracker = getSectionsTracker();
19547
18410
  postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
19548
- const reportHeight = () => {
19549
- const h = document.body.scrollHeight;
19550
- if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
19551
- };
19552
- reportHeight();
19553
- setTimeout(reportHeight, 500);
18411
+ const h = document.documentElement.scrollHeight;
18412
+ if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
19554
18413
  }
19555
18414
  };
19556
18415
  const handleSwitchSchedule = (e) => {
@@ -19937,10 +18796,6 @@ function OhhwellsBridge() {
19937
18796
  window.removeEventListener("message", handleAiApplyTree);
19938
18797
  window.removeEventListener("message", handleAiDeleteSection);
19939
18798
  window.removeEventListener("message", handleAiSetSections);
19940
- window.removeEventListener("message", handleMoveSection);
19941
- window.removeEventListener("message", handleAiSetBrand);
19942
- window.removeEventListener("message", handleAiSetStyles);
19943
- window.removeEventListener("message", handleGetBrand);
19944
18799
  window.removeEventListener("message", handleDeactivate);
19945
18800
  window.removeEventListener("message", handleToastAction);
19946
18801
  window.removeEventListener("message", handleFormCount);
@@ -19951,7 +18806,7 @@ function OhhwellsBridge() {
19951
18806
  if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
19952
18807
  };
19953
18808
  }, [isEditMode, refreshStateRules]);
19954
- (0, import_react17.useEffect)(() => {
18809
+ (0, import_react16.useEffect)(() => {
19955
18810
  if (!isEditMode) return;
19956
18811
  const THRESHOLD = 10;
19957
18812
  const resolveWasSelected = (el) => {
@@ -20107,7 +18962,7 @@ function OhhwellsBridge() {
20107
18962
  unlockFooterDragInteraction();
20108
18963
  };
20109
18964
  }, [isEditMode]);
20110
- (0, import_react17.useEffect)(() => {
18965
+ (0, import_react16.useEffect)(() => {
20111
18966
  const handler = (e) => {
20112
18967
  if (e.data?.type !== "ow:request-schedule-config") return;
20113
18968
  const insertAfterVal = e.data.insertAfter;
@@ -20123,7 +18978,7 @@ function OhhwellsBridge() {
20123
18978
  window.addEventListener("message", handler);
20124
18979
  return () => window.removeEventListener("message", handler);
20125
18980
  }, [processConfigRequest]);
20126
- (0, import_react17.useEffect)(() => {
18981
+ (0, import_react16.useEffect)(() => {
20127
18982
  if (!isEditMode) return;
20128
18983
  document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
20129
18984
  el.removeAttribute("data-ohw-active-state");
@@ -20147,7 +19002,7 @@ function OhhwellsBridge() {
20147
19002
  postToParent2({
20148
19003
  type: "ow:ready",
20149
19004
  version: "1",
20150
- bridgeVersion: "0.1.66",
19005
+ bridgeVersion: "0.1.65",
20151
19006
  path: pathname,
20152
19007
  nodes: collectEditableNodes(editContentRef.current),
20153
19008
  sections
@@ -20159,13 +19014,13 @@ function OhhwellsBridge() {
20159
19014
  clearTimeout(timer);
20160
19015
  };
20161
19016
  }, [pathname, isEditMode, refreshStateRules, postToParent2]);
20162
- (0, import_react17.useEffect)(() => {
19017
+ (0, import_react16.useEffect)(() => {
20163
19018
  scrollToHashSectionWhenReady();
20164
19019
  const onHashChange = () => scrollToHashSectionWhenReady();
20165
19020
  window.addEventListener("hashchange", onHashChange);
20166
19021
  return () => window.removeEventListener("hashchange", onHashChange);
20167
19022
  }, [pathname]);
20168
- const handleCommand = (0, import_react17.useCallback)((cmd) => {
19023
+ const handleCommand = (0, import_react16.useCallback)((cmd) => {
20169
19024
  const el = activeElRef.current;
20170
19025
  const selBefore = window.getSelection();
20171
19026
  let savedOffsets = null;
@@ -20201,7 +19056,45 @@ function OhhwellsBridge() {
20201
19056
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
20202
19057
  refreshActiveCommandsRef.current();
20203
19058
  }, []);
20204
- const handleStateChange = (0, import_react17.useCallback)((state) => {
19059
+ (0, import_react16.useEffect)(() => {
19060
+ const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
19061
+ if (!session || !logoSizeDraft) return;
19062
+ const onPanelAction = (e) => {
19063
+ const type = e.data?.type;
19064
+ if (type === "ow:logo-size-close") {
19065
+ closeFloatingPanelAndDeselect();
19066
+ return;
19067
+ }
19068
+ if (type === "ow:logo-size-update-everywhere") {
19069
+ postToParentRef.current({ type: "ow:open-logo-settings", ...readLogoIdentityFromDom() });
19070
+ return;
19071
+ }
19072
+ if (type === "ow:logo-size-customize-mobile" || type === "ow:logo-size-reset-mobile") {
19073
+ const following = type === "ow:logo-size-reset-mobile";
19074
+ const next2 = {
19075
+ ...logoSizeDraft,
19076
+ mobileFollowing: following,
19077
+ mobilePx: logoSizeDraft.desktopPx
19078
+ };
19079
+ setLogoSizeDraft(next2);
19080
+ persistLogoSizeDraft(session.placement, next2);
19081
+ return;
19082
+ }
19083
+ if (type !== "ow:logo-size-set") return;
19084
+ const px = Number(e.data.px);
19085
+ if (!Number.isFinite(px)) return;
19086
+ const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
19087
+ ...logoSizeDraft,
19088
+ desktopPx: px,
19089
+ mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
19090
+ };
19091
+ setLogoSizeDraft(next);
19092
+ persistLogoSizeDraft(session.placement, next);
19093
+ };
19094
+ window.addEventListener("message", onPanelAction);
19095
+ return () => window.removeEventListener("message", onPanelAction);
19096
+ }, [floatingPanel, logoSizeDraft, editorViewport, persistLogoSizeDraft, closeFloatingPanelAndDeselect]);
19097
+ const handleStateChange = (0, import_react16.useCallback)((state) => {
20205
19098
  if (!activeStateElRef.current) return;
20206
19099
  const el = activeStateElRef.current;
20207
19100
  if (state === "Default") {
@@ -20214,7 +19107,7 @@ function OhhwellsBridge() {
20214
19107
  }
20215
19108
  setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
20216
19109
  }, [deactivate]);
20217
- const reselectAfterLinkPopover = (0, import_react17.useCallback)(
19110
+ const reselectAfterLinkPopover = (0, import_react16.useCallback)(
20218
19111
  (hrefKey) => {
20219
19112
  requestAnimationFrame(() => {
20220
19113
  const el = resolveHrefKeyElement(hrefKey);
@@ -20223,7 +19116,7 @@ function OhhwellsBridge() {
20223
19116
  },
20224
19117
  [resolveHrefKeyElement]
20225
19118
  );
20226
- const closeLinkPopover = (0, import_react17.useCallback)(() => {
19119
+ const closeLinkPopover = (0, import_react16.useCallback)(() => {
20227
19120
  const session = linkPopoverSessionRef.current;
20228
19121
  addNavAfterAnchorRef.current = null;
20229
19122
  setLinkPopover(null);
@@ -20231,9 +19124,9 @@ function OhhwellsBridge() {
20231
19124
  reselectAfterLinkPopover(session.key);
20232
19125
  }
20233
19126
  }, [reselectAfterLinkPopover]);
20234
- const closeLinkPopoverRef = (0, import_react17.useRef)(closeLinkPopover);
19127
+ const closeLinkPopoverRef = (0, import_react16.useRef)(closeLinkPopover);
20235
19128
  closeLinkPopoverRef.current = closeLinkPopover;
20236
- const openLinkPopoverForActive = (0, import_react17.useCallback)(() => {
19129
+ const openLinkPopoverForActive = (0, import_react16.useCallback)(() => {
20237
19130
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
20238
19131
  if (!hrefCtx) return;
20239
19132
  bumpLinkPopoverGrace();
@@ -20244,7 +19137,7 @@ function OhhwellsBridge() {
20244
19137
  });
20245
19138
  deactivate();
20246
19139
  }, [deactivate]);
20247
- const openLinkPopoverForSelected = (0, import_react17.useCallback)(() => {
19140
+ const openLinkPopoverForSelected = (0, import_react16.useCallback)(() => {
20248
19141
  const anchor = selectedElRef.current;
20249
19142
  if (!anchor) return;
20250
19143
  const key = anchor.getAttribute("data-ohw-href-key");
@@ -20261,7 +19154,7 @@ function OhhwellsBridge() {
20261
19154
  });
20262
19155
  deselect();
20263
19156
  }, [deselect]);
20264
- const handleSelectParent = (0, import_react17.useCallback)(() => {
19157
+ const handleSelectParent = (0, import_react16.useCallback)(() => {
20265
19158
  const selected = selectedElRef.current;
20266
19159
  if (!selected) return;
20267
19160
  if (toolbarVariantRef.current === "select-frame") {
@@ -20288,7 +19181,7 @@ function OhhwellsBridge() {
20288
19181
  }
20289
19182
  deselectRef.current();
20290
19183
  }, []);
20291
- const handleDuplicateSelected = (0, import_react17.useCallback)(() => {
19184
+ const handleDuplicateSelected = (0, import_react16.useCallback)(() => {
20292
19185
  const selected = selectedElRef.current;
20293
19186
  if (!selected || !isNavigationItem2(selected)) return;
20294
19187
  const hrefKey = selected.getAttribute("data-ohw-href-key");
@@ -20404,7 +19297,7 @@ function OhhwellsBridge() {
20404
19297
  });
20405
19298
  }
20406
19299
  }, [postToParent2]);
20407
- const runPendingDeleteUndo = (0, import_react17.useCallback)(() => {
19300
+ const runPendingDeleteUndo = (0, import_react16.useCallback)(() => {
20408
19301
  const pending = pendingDeleteUndoRef.current;
20409
19302
  if (!pending) return false;
20410
19303
  pendingDeleteUndoRef.current = null;
@@ -20412,7 +19305,7 @@ function OhhwellsBridge() {
20412
19305
  enforceLinkHrefs();
20413
19306
  return true;
20414
19307
  }, []);
20415
- const handleDeleteSelected = (0, import_react17.useCallback)(() => {
19308
+ const handleDeleteSelected = (0, import_react16.useCallback)(() => {
20416
19309
  const selected = selectedElRef.current;
20417
19310
  if (!selected) return false;
20418
19311
  return deleteSelectedNavFooterItem({
@@ -20433,7 +19326,7 @@ function OhhwellsBridge() {
20433
19326
  }, [postToParent2]);
20434
19327
  handleDeleteSelectedRef.current = handleDeleteSelected;
20435
19328
  runPendingDeleteUndoRef.current = runPendingDeleteUndo;
20436
- const handleLinkPopoverSubmit = (0, import_react17.useCallback)(
19329
+ const handleLinkPopoverSubmit = (0, import_react16.useCallback)(
20437
19330
  (target) => {
20438
19331
  const session = linkPopoverSessionRef.current;
20439
19332
  if (!session) return;
@@ -20499,19 +19392,19 @@ function OhhwellsBridge() {
20499
19392
  const showEditLink = toolbarShowEditLink;
20500
19393
  const currentSections = sectionsByPath[pathname] ?? [];
20501
19394
  linkPopoverOpenRef.current = linkPopover !== null;
20502
- const handleMediaReplace = (0, import_react17.useCallback)(
19395
+ const handleMediaReplace = (0, import_react16.useCallback)(
20503
19396
  (key) => {
20504
19397
  postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
20505
19398
  },
20506
19399
  [postToParent2, mediaHover?.elementType]
20507
19400
  );
20508
- const handleEditCarousel = (0, import_react17.useCallback)(
19401
+ const handleEditCarousel = (0, import_react16.useCallback)(
20509
19402
  (key) => {
20510
19403
  postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
20511
19404
  },
20512
19405
  [postToParent2]
20513
19406
  );
20514
- const handleMediaFadeOutComplete = (0, import_react17.useCallback)((key) => {
19407
+ const handleMediaFadeOutComplete = (0, import_react16.useCallback)((key) => {
20515
19408
  setUploadingRects((prev) => {
20516
19409
  if (!(key in prev)) return prev;
20517
19410
  const next = { ...prev };
@@ -20519,7 +19412,7 @@ function OhhwellsBridge() {
20519
19412
  return next;
20520
19413
  });
20521
19414
  }, []);
20522
- const handleVideoSettingsChange = (0, import_react17.useCallback)(
19415
+ const handleVideoSettingsChange = (0, import_react16.useCallback)(
20523
19416
  (key, settings) => {
20524
19417
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
20525
19418
  const video = getVideoEl2(el);
@@ -20541,538 +19434,414 @@ function OhhwellsBridge() {
20541
19434
  },
20542
19435
  [postToParent2]
20543
19436
  );
20544
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
20545
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { id: "ohw-loader", suppressHydrationWarning: true, style: { ...OHW_LOADER_STYLE, display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(OhwLoaderSpinner, {}) }),
20546
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: OHW_LOADER_PREHYDRATE_SCRIPT } }),
20547
- bridgeRoot ? (0, import_react_dom4.createPortal)(
20548
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
20549
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
20550
- isEditMode && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
20551
- isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20552
- "div",
20553
- {
20554
- className: "pointer-events-none fixed z-2147483646",
20555
- style: { left: slot.left, top: slot.y, width: slot.width, height: 3, transform: "translateY(-50%)" },
20556
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20557
- DropIndicator,
20558
- {
20559
- direction: "horizontal",
20560
- state: activeSectionDropIndex === i ? "dragActive" : "dragIdle",
20561
- className: "!h-full !w-full"
20562
- }
20563
- )
20564
- },
20565
- `section-drop-${slot.insertIndex}-${i}`
20566
- )),
20567
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20568
- MediaOverlay,
20569
- {
20570
- hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
20571
- isUploading: true,
20572
- fadingOut,
20573
- onFadeOutComplete: handleMediaFadeOutComplete,
20574
- onReplace: handleMediaReplace
20575
- },
20576
- `uploading-${key}`
20577
- )),
20578
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20579
- MediaOverlay,
20580
- {
20581
- hover: mediaHover,
20582
- isUploading: false,
20583
- onReplace: handleMediaReplace,
20584
- onVideoSettingsChange: handleVideoSettingsChange
20585
- }
20586
- ),
20587
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
20588
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
20589
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
20590
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
20591
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20592
- "div",
20593
- {
20594
- className: "pointer-events-none fixed z-2147483646",
20595
- style: {
20596
- left: slot.left,
20597
- top: slot.top,
20598
- width: slot.width,
20599
- height: slot.height
20600
- },
20601
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20602
- DropIndicator,
20603
- {
20604
- direction: slot.direction,
20605
- state: activeFooterDropIndex === i ? "dragActive" : "dragIdle",
20606
- className: "!h-full !w-full"
20607
- }
20608
- )
19437
+ return bridgeRoot ? (0, import_react_dom4.createPortal)(
19438
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
19439
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
19440
+ isEditMode && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
19441
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19442
+ MediaOverlay,
19443
+ {
19444
+ hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
19445
+ isUploading: true,
19446
+ fadingOut,
19447
+ onFadeOutComplete: handleMediaFadeOutComplete,
19448
+ onReplace: handleMediaReplace
19449
+ },
19450
+ `uploading-${key}`
19451
+ )),
19452
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19453
+ MediaOverlay,
19454
+ {
19455
+ hover: mediaHover,
19456
+ isUploading: false,
19457
+ onReplace: handleMediaReplace,
19458
+ onVideoSettingsChange: handleVideoSettingsChange
19459
+ }
19460
+ ),
19461
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
19462
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
19463
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
19464
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
19465
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19466
+ "div",
19467
+ {
19468
+ className: "pointer-events-none fixed z-2147483646",
19469
+ style: {
19470
+ left: slot.left,
19471
+ top: slot.top,
19472
+ width: slot.width,
19473
+ height: slot.height
20609
19474
  },
20610
- `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
20611
- )),
20612
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20613
- "div",
20614
- {
20615
- className: "pointer-events-none fixed z-2147483646",
20616
- style: {
20617
- left: slot.left,
20618
- top: slot.top,
20619
- width: slot.width,
20620
- height: slot.height
20621
- },
20622
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20623
- DropIndicator,
20624
- {
20625
- direction: slot.direction,
20626
- state: activeNavDropIndex === i ? "dragActive" : "dragIdle",
20627
- className: "!h-full !w-full"
20628
- }
20629
- )
19475
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19476
+ DropIndicator,
19477
+ {
19478
+ direction: slot.direction,
19479
+ state: activeFooterDropIndex === i ? "dragActive" : "dragIdle",
19480
+ className: "!h-full !w-full"
19481
+ }
19482
+ )
19483
+ },
19484
+ `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
19485
+ )),
19486
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19487
+ "div",
19488
+ {
19489
+ className: "pointer-events-none fixed z-2147483646",
19490
+ style: {
19491
+ left: slot.left,
19492
+ top: slot.top,
19493
+ width: slot.width,
19494
+ height: slot.height
20630
19495
  },
20631
- `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
20632
- )),
20633
- hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
20634
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
20635
- hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
20636
- formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20637
- ItemInteractionLayer,
20638
- {
20639
- rect: formPickRect,
20640
- state: "active-top",
20641
- itemDragSurface: false,
20642
- toolbarAlign: "left",
20643
- chromeGap: 24,
20644
- toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
20645
- "div",
20646
- {
20647
- "data-ohw-form-toolbar": "",
20648
- className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
20649
- children: [
20650
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20651
- "button",
20652
- {
20653
- type: "button",
20654
- "aria-label": "Add field",
20655
- className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
20656
- onClick: () => setFieldTypePickerOpen((open) => !open),
20657
- "data-ohw-add-field": "",
20658
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Plus, { size: 15, "aria-hidden": true })
20659
- }
20660
- ),
20661
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20662
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
20663
- "button",
20664
- {
20665
- type: "button",
20666
- 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",
20667
- onClick: () => {
20668
- const form = formPickElRef.current;
20669
- if (!form) return;
20670
- postToParent2({
20671
- type: "ow:form-pick",
20672
- formKey: formKeyOf(form),
20673
- hasLongText: formHasLongText(form)
20674
- });
20675
- },
20676
- children: [
20677
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Settings, { size: 14, "aria-hidden": true }),
20678
- "Form settings",
20679
- formPickCount ? (
20680
- // Counter pill, per the design — not a text suffix.
20681
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20682
- "span",
20683
- {
20684
- "data-ohw-form-count": "",
20685
- 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",
20686
- children: formPickCount
20687
- }
20688
- )
20689
- ) : null
20690
- ]
20691
- }
20692
- ),
20693
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20694
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20695
- "button",
20696
- {
20697
- type: "button",
20698
- "aria-pressed": formViewState === state,
20699
- 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"),
20700
- onClick: () => {
20701
- const form = formPickElRef.current;
20702
- const key = form ? formKeyOf(form) : null;
20703
- if (!form || !key) return;
20704
- const initial = successInitialFor(form, key, editContentRef.current);
20705
- setFormViewState(form, key, state, initial);
20706
- setFormViewStateUi(state);
20707
- setFormPickRect(form.getBoundingClientRect());
20708
- if (state === "success") {
20709
- const successEl = form.querySelector(`[${SUCCESS_TEXT_ATTR}]`);
20710
- if (successEl) requestAnimationFrame(() => activateRef.current(successEl));
20711
- } else {
20712
- deactivateRef.current();
20713
- }
20714
- },
20715
- children: state
19496
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19497
+ DropIndicator,
19498
+ {
19499
+ direction: slot.direction,
19500
+ state: activeNavDropIndex === i ? "dragActive" : "dragIdle",
19501
+ className: "!h-full !w-full"
19502
+ }
19503
+ )
19504
+ },
19505
+ `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
19506
+ )),
19507
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
19508
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
19509
+ hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
19510
+ formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19511
+ ItemInteractionLayer,
19512
+ {
19513
+ rect: formPickRect,
19514
+ state: "active-top",
19515
+ itemDragSurface: false,
19516
+ toolbarAlign: "left",
19517
+ chromeGap: 24,
19518
+ toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
19519
+ "div",
19520
+ {
19521
+ "data-ohw-form-toolbar": "",
19522
+ className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
19523
+ children: [
19524
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19525
+ "button",
19526
+ {
19527
+ type: "button",
19528
+ "aria-label": "Add field",
19529
+ className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
19530
+ onClick: () => setFieldTypePickerOpen((open) => !open),
19531
+ "data-ohw-add-field": "",
19532
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Plus, { size: 15, "aria-hidden": true })
19533
+ }
19534
+ ),
19535
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
19536
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
19537
+ "button",
19538
+ {
19539
+ type: "button",
19540
+ 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",
19541
+ onClick: () => {
19542
+ const form = formPickElRef.current;
19543
+ if (!form) return;
19544
+ postToParent2({
19545
+ type: "ow:form-pick",
19546
+ formKey: formKeyOf(form),
19547
+ hasLongText: formHasLongText(form)
19548
+ });
20716
19549
  },
20717
- state
20718
- )) })
20719
- ]
20720
- }
20721
- )
20722
- }
20723
- ),
20724
- formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20725
- ItemInteractionLayer,
20726
- {
20727
- rect: formHoverRect,
20728
- state: "hover",
20729
- chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
20730
- }
20731
- ),
20732
- fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20733
- ItemInteractionLayer,
20734
- {
20735
- rect: fieldPickRect,
20736
- state: fieldDragging ? "dragging" : "active-top",
20737
- itemDragSurface: false,
20738
- toolbarAlign: "left",
20739
- chromeGap: 10,
20740
- showHandle: true,
20741
- dragHandleLabel: "Reorder field",
20742
- onDragHandleDragStart: handleFieldDragStart,
20743
- onDragHandleDragEnd: handleFieldDragEnd,
20744
- toolbar: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20745
- FormFieldToolbar,
20746
- {
20747
- type: fieldPickState.type,
20748
- required: fieldPickState.required,
20749
- onTypeChange: handleFieldTypeChange,
20750
- onRequiredToggle: handleFieldRequiredToggle,
20751
- onDuplicate: handleFieldDuplicate,
20752
- onDelete: handleFieldDelete
20753
- }
20754
- )
20755
- }
20756
- ),
20757
- fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20758
- "div",
20759
- {
20760
- className: "pointer-events-none fixed z-[2147483644]",
20761
- style: { top: slot.top, left: slot.left, width: slot.width },
20762
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20763
- DropIndicator,
20764
- {
20765
- direction: "horizontal",
20766
- state: fieldDropIndex === i ? "dragActive" : "dragIdle",
20767
- className: "!w-full"
20768
- }
20769
- )
20770
- },
20771
- `field-drop-${i}`
20772
- )) : null,
20773
- fieldTypePickerOpen && formPickRect && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20774
- "div",
20775
- {
20776
- className: "pointer-events-none fixed z-[2147483645]",
20777
- style: { top: formPickRect.top + 16, left: formPickRect.left + 24 },
20778
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(FieldTypePicker, { onPick: handleAddField })
20779
- }
20780
- ),
20781
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
20782
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20783
- FooterContainerChrome,
20784
- {
20785
- rect: toolbarRect,
20786
- onAdd: handleAddFooterColumn,
20787
- addDisabled: !canAddFooterColumn()
20788
- }
20789
- ),
20790
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20791
- ItemInteractionLayer,
20792
- {
20793
- rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
20794
- toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
20795
- elRef: glowElRef,
20796
- state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanelRect(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
20797
- showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
20798
- dragDisabled: reorderDragDisabled,
20799
- dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
20800
- onDragHandleDragStart: handleItemDragStart,
20801
- onDragHandleDragEnd: handleItemDragEnd,
20802
- onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
20803
- onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
20804
- itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
20805
- toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20806
- ItemActionToolbar,
20807
- {
20808
- onEditLink: openLinkPopoverForSelected,
20809
- onStyle: () => {
20810
- const row = selectedElRef.current;
20811
- if (!row) return;
20812
- if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
20813
- else openSocialsDisplayPanel(row);
20814
- },
20815
- showStyle: selectedIsSocialsRow,
20816
- styleActive: floatingPanel?.kind === "socials-display",
20817
- onAddItem: handleAddChildItem,
20818
- onSelectParent: handleSelectParent,
20819
- onDuplicate: handleDuplicateSelected,
20820
- onDelete: handleDeleteSelected,
20821
- addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
20822
- const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
20823
- return row ? !canAddSocialItem(row) : false;
20824
- })(),
20825
- editLinkDisabled: false,
20826
- moreDisabled: false,
20827
- duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
20828
- showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
20829
- showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
20830
- selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
19550
+ children: [
19551
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Settings, { size: 14, "aria-hidden": true }),
19552
+ "Form settings",
19553
+ formPickCount ? (
19554
+ // Counter pill, per the design — not a text suffix.
19555
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19556
+ "span",
19557
+ {
19558
+ "data-ohw-form-count": "",
19559
+ 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",
19560
+ children: formPickCount
19561
+ }
19562
+ )
19563
+ ) : null
19564
+ ]
19565
+ }
20831
19566
  ),
20832
- showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
20833
- dropdownOpen: navDropdownPreviewOpen,
20834
- onDropdownOpenChange: handleNavDropdownOpenChange,
20835
- headingVisible: footerHeadingVisible,
20836
- onHeadingVisibleChange: handleFooterHeadingVisibleChange
20837
- }
20838
- ) : void 0
20839
- }
20840
- ),
20841
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
20842
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20843
- EditGlowChrome,
19567
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
19568
+ /* @__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)(
19569
+ "button",
19570
+ {
19571
+ type: "button",
19572
+ "aria-pressed": formViewState === state,
19573
+ 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"),
19574
+ onClick: () => {
19575
+ const form = formPickElRef.current;
19576
+ const key = form ? formKeyOf(form) : null;
19577
+ if (!form || !key) return;
19578
+ const initial = successInitialFor(form, key, editContentRef.current);
19579
+ setFormViewState(form, key, state, initial);
19580
+ setFormViewStateUi(state);
19581
+ setFormPickRect(form.getBoundingClientRect());
19582
+ if (state === "success") {
19583
+ const successEl = form.querySelector(`[${SUCCESS_TEXT_ATTR}]`);
19584
+ if (successEl) requestAnimationFrame(() => activateRef.current(successEl));
19585
+ } else {
19586
+ deactivateRef.current();
19587
+ }
19588
+ },
19589
+ children: state
19590
+ },
19591
+ state
19592
+ )) })
19593
+ ]
19594
+ }
19595
+ )
19596
+ }
19597
+ ),
19598
+ formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19599
+ ItemInteractionLayer,
19600
+ {
19601
+ rect: formHoverRect,
19602
+ state: "hover",
19603
+ chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
19604
+ }
19605
+ ),
19606
+ fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19607
+ ItemInteractionLayer,
19608
+ {
19609
+ rect: fieldPickRect,
19610
+ state: fieldDragging ? "dragging" : "active-top",
19611
+ itemDragSurface: false,
19612
+ toolbarAlign: "left",
19613
+ chromeGap: 10,
19614
+ showHandle: true,
19615
+ dragHandleLabel: "Reorder field",
19616
+ onDragHandleDragStart: handleFieldDragStart,
19617
+ onDragHandleDragEnd: handleFieldDragEnd,
19618
+ toolbar: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19619
+ FormFieldToolbar,
20844
19620
  {
20845
- rect: toolbarRect,
20846
- elRef: glowElRef,
20847
- reorderHrefKey,
20848
- dragDisabled: reorderDragDisabled,
20849
- hideHandle: isItemDragging
19621
+ type: fieldPickState.type,
19622
+ required: fieldPickState.required,
19623
+ onTypeChange: handleFieldTypeChange,
19624
+ onRequiredToggle: handleFieldRequiredToggle,
19625
+ onDuplicate: handleFieldDuplicate,
19626
+ onDelete: handleFieldDelete
20850
19627
  }
20851
- ),
20852
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20853
- FloatingToolbar,
19628
+ )
19629
+ }
19630
+ ),
19631
+ fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19632
+ "div",
19633
+ {
19634
+ className: "pointer-events-none fixed z-[2147483644]",
19635
+ style: { top: slot.top, left: slot.left, width: slot.width },
19636
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19637
+ DropIndicator,
20854
19638
  {
20855
- rect: toolbarRect,
20856
- parentScroll: parentScrollRef.current,
20857
- elRef: toolbarElRef,
20858
- onCommand: handleCommand,
20859
- activeCommands,
20860
- showEditLink,
20861
- onEditLink: openLinkPopoverForActive
19639
+ direction: "horizontal",
19640
+ state: fieldDropIndex === i ? "dragActive" : "dragIdle",
19641
+ className: "!w-full"
20862
19642
  }
20863
19643
  )
20864
- ] }),
20865
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
20866
- "div",
20867
- {
20868
- "data-ohw-max-badge": "",
20869
- style: {
20870
- position: "fixed",
20871
- top: maxBadge.rect.bottom + 4,
20872
- left: maxBadge.rect.right,
20873
- transform: "translateX(-100%)",
20874
- zIndex: 2147483647,
20875
- background: maxBadge.current > maxBadge.max ? "#FEF2F2" : "#F5F5F4",
20876
- color: maxBadge.current > maxBadge.max ? "#DC2626" : "#78716C",
20877
- border: `1px solid ${maxBadge.current > maxBadge.max ? "#FECACA" : "#E7E5E4"}`,
20878
- borderRadius: 4,
20879
- padding: "2px 6px",
20880
- fontSize: 11,
20881
- fontWeight: 500,
20882
- pointerEvents: "none"
20883
- },
20884
- children: [
20885
- maxBadge.current,
20886
- "/",
20887
- maxBadge.max
20888
- ]
20889
- }
20890
- ),
20891
- toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20892
- StateToggle,
19644
+ },
19645
+ `field-drop-${i}`
19646
+ )) : null,
19647
+ fieldTypePickerOpen && formPickRect && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19648
+ "div",
19649
+ {
19650
+ className: "pointer-events-none fixed z-[2147483645]",
19651
+ style: { top: formPickRect.top + 16, left: formPickRect.left + 24 },
19652
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FieldTypePicker, { onPick: handleAddField })
19653
+ }
19654
+ ),
19655
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
19656
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19657
+ FooterContainerChrome,
19658
+ {
19659
+ rect: toolbarRect,
19660
+ onAdd: handleAddFooterColumn,
19661
+ addDisabled: !canAddFooterColumn()
19662
+ }
19663
+ ),
19664
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19665
+ ItemInteractionLayer,
19666
+ {
19667
+ rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
19668
+ toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
19669
+ elRef: glowElRef,
19670
+ state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanelRect(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
19671
+ showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
19672
+ dragDisabled: reorderDragDisabled,
19673
+ dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
19674
+ onDragHandleDragStart: handleItemDragStart,
19675
+ onDragHandleDragEnd: handleItemDragEnd,
19676
+ onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
19677
+ onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
19678
+ itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
19679
+ toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19680
+ ItemActionToolbar,
19681
+ {
19682
+ onEditLink: openLinkPopoverForSelected,
19683
+ onStyle: () => {
19684
+ const row = selectedElRef.current;
19685
+ if (!row) return;
19686
+ if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
19687
+ else openSocialsDisplayPanel(row);
19688
+ },
19689
+ showStyle: selectedIsSocialsRow,
19690
+ styleActive: floatingPanel?.kind === "socials-display",
19691
+ onAddItem: handleAddChildItem,
19692
+ onSelectParent: handleSelectParent,
19693
+ onDuplicate: handleDuplicateSelected,
19694
+ onDelete: handleDeleteSelected,
19695
+ addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
19696
+ const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
19697
+ return row ? !canAddSocialItem(row) : false;
19698
+ })(),
19699
+ editLinkDisabled: false,
19700
+ moreDisabled: false,
19701
+ duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
19702
+ showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
19703
+ showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
19704
+ selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
19705
+ ),
19706
+ showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
19707
+ dropdownOpen: navDropdownPreviewOpen,
19708
+ onDropdownOpenChange: handleNavDropdownOpenChange,
19709
+ headingVisible: footerHeadingVisible,
19710
+ onHeadingVisibleChange: handleFooterHeadingVisibleChange
19711
+ }
19712
+ ) : void 0
19713
+ }
19714
+ ),
19715
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
19716
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19717
+ EditGlowChrome,
20893
19718
  {
20894
- rect: toggleState.rect,
20895
- activeState: toggleState.activeState,
20896
- states: toggleState.states,
20897
- onStateChange: handleStateChange
19719
+ rect: toolbarRect,
19720
+ elRef: glowElRef,
19721
+ reorderHrefKey,
19722
+ dragDisabled: reorderDragDisabled,
19723
+ hideHandle: isItemDragging
20898
19724
  }
20899
19725
  ),
20900
- sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
20901
- "div",
19726
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19727
+ FloatingToolbar,
20902
19728
  {
20903
- "data-ohw-section-insert-line": "",
20904
- className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
20905
- style: { top: sectionGap.y, transform: "translateY(-50%)" },
20906
- children: [
20907
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
20908
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20909
- Badge,
20910
- {
20911
- 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",
20912
- onClick: () => {
20913
- window.parent.postMessage(
20914
- {
20915
- type: "ow:add-section",
20916
- insertAfter: sectionGap.insertAfter,
20917
- insertBefore: sectionGap.insertBefore
20918
- },
20919
- "*"
20920
- );
20921
- },
20922
- children: "Add Section"
20923
- }
20924
- ),
20925
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
20926
- ]
19729
+ rect: toolbarRect,
19730
+ parentScroll: parentScrollRef.current,
19731
+ elRef: toolbarElRef,
19732
+ onCommand: handleCommand,
19733
+ activeCommands,
19734
+ showEditLink,
19735
+ onEditLink: openLinkPopoverForActive
20927
19736
  }
20928
- ),
20929
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20930
- LinkPopover,
20931
- {
20932
- panelRef: linkPopoverPanelRef,
20933
- portalContainer: dialogPortalContainer,
20934
- open: true,
20935
- mode: linkPopover.mode ?? "edit",
20936
- pages: sitePages,
20937
- sections: currentSections,
20938
- sectionsByPath,
20939
- initialTarget: linkPopover.target,
20940
- existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
20941
- onClose: closeLinkPopover,
20942
- onSubmit: handleLinkPopoverSubmit
19737
+ )
19738
+ ] }),
19739
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
19740
+ "div",
19741
+ {
19742
+ "data-ohw-max-badge": "",
19743
+ style: {
19744
+ position: "fixed",
19745
+ top: maxBadge.rect.bottom + 4,
19746
+ left: maxBadge.rect.right,
19747
+ transform: "translateX(-100%)",
19748
+ zIndex: 2147483647,
19749
+ background: maxBadge.current > maxBadge.max ? "#FEF2F2" : "#F5F5F4",
19750
+ color: maxBadge.current > maxBadge.max ? "#DC2626" : "#78716C",
19751
+ border: `1px solid ${maxBadge.current > maxBadge.max ? "#FECACA" : "#E7E5E4"}`,
19752
+ borderRadius: 4,
19753
+ padding: "2px 6px",
19754
+ fontSize: 11,
19755
+ fontWeight: 500,
19756
+ pointerEvents: "none"
20943
19757
  },
20944
- linkPopover.key
20945
- ) : null,
20946
- floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20947
- FloatingPanel,
20948
- {
20949
- open: true,
20950
- title: floatingPanel.title,
20951
- context: floatingPanel.context,
20952
- position: floatingPanelPos,
20953
- onPositionChange: setFloatingPanelPos,
20954
- parentScroll: parentScrollSnap ?? parentScrollRef.current,
20955
- onClose: closeFloatingPanelOnly,
20956
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20957
- SocialsDisplayPanel,
20958
- {
20959
- display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
20960
- onChange: (next) => {
20961
- changeSocialsDisplay(floatingPanel.row, next);
20962
- setFloatingPanel({ ...floatingPanel });
20963
- }
20964
- }
20965
- )
20966
- }
20967
- ) : null,
20968
- floatingPanel && floatingPanel.kind === "logo-size" && logoSizeDraft ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20969
- FloatingPanel,
20970
- {
20971
- open: true,
20972
- title: floatingPanel.title,
20973
- context: floatingPanel.context,
20974
- position: floatingPanelPos,
20975
- onPositionChange: setFloatingPanelPos,
20976
- parentScroll: parentScrollSnap ?? parentScrollRef.current,
20977
- onClose: closeFloatingPanelAndDeselect,
20978
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20979
- LogoSizePanel,
19758
+ children: [
19759
+ maxBadge.current,
19760
+ "/",
19761
+ maxBadge.max
19762
+ ]
19763
+ }
19764
+ ),
19765
+ toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19766
+ StateToggle,
19767
+ {
19768
+ rect: toggleState.rect,
19769
+ activeState: toggleState.activeState,
19770
+ states: toggleState.states,
19771
+ onStateChange: handleStateChange
19772
+ }
19773
+ ),
19774
+ sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
19775
+ "div",
19776
+ {
19777
+ "data-ohw-section-insert-line": "",
19778
+ className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
19779
+ style: { top: sectionGap.y, transform: "translateY(-50%)" },
19780
+ children: [
19781
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
19782
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19783
+ Badge,
20980
19784
  {
20981
- viewport: editorViewport,
20982
- sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
20983
- mobileFollowing: logoSizeDraft.mobileFollowing,
20984
- onSizeChange: (px) => {
20985
- const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
20986
- ...logoSizeDraft,
20987
- desktopPx: px,
20988
- mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
20989
- };
20990
- setLogoSizeDraft(next);
20991
- persistLogoSizeDraft(floatingPanel.placement, next);
20992
- },
20993
- onCustomizeMobile: () => {
20994
- const next = {
20995
- ...logoSizeDraft,
20996
- mobileFollowing: false,
20997
- mobilePx: logoSizeDraft.desktopPx
20998
- };
20999
- setLogoSizeDraft(next);
21000
- persistLogoSizeDraft(floatingPanel.placement, next);
21001
- },
21002
- onResetMobile: () => {
21003
- const next = {
21004
- ...logoSizeDraft,
21005
- mobileFollowing: true,
21006
- mobilePx: logoSizeDraft.desktopPx
21007
- };
21008
- setLogoSizeDraft(next);
21009
- persistLogoSizeDraft(floatingPanel.placement, next);
19785
+ 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",
19786
+ onClick: () => {
19787
+ window.parent.postMessage(
19788
+ {
19789
+ type: "ow:add-section",
19790
+ insertAfter: sectionGap.insertAfter,
19791
+ insertBefore: sectionGap.insertBefore
19792
+ },
19793
+ "*"
19794
+ );
21010
19795
  },
21011
- onUpdateEverywhere: () => {
21012
- const identity = readLogoIdentityFromDom();
21013
- postToParent2({ type: "ow:open-logo-settings", ...identity });
21014
- }
19796
+ children: "Add Section"
21015
19797
  }
21016
- )
21017
- }
21018
- ) : null
21019
- ] }),
21020
- bridgeRoot
21021
- ) : null
21022
- ] });
21023
- }
21024
-
21025
- // src/ui/EmptySection.tsx
21026
- var import_link = __toESM(require("next/link"), 1);
21027
- var import_jsx_runtime35 = require("react/jsx-runtime");
21028
- function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
21029
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
21030
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
21031
- "p",
21032
- {
21033
- style: {
21034
- fontFamily: "var(--brand-font-body)",
21035
- fontSize: "0.75rem",
21036
- fontWeight: 500,
21037
- letterSpacing: "0.15em",
21038
- textTransform: "uppercase",
21039
- color: "var(--brand-accent)",
21040
- marginBottom: "1.5rem"
21041
- },
21042
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_link.default, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
21043
- }
21044
- ),
21045
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
21046
- "h1",
21047
- {
21048
- style: {
21049
- fontFamily: "var(--brand-font-heading)",
21050
- fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
21051
- lineHeight: 1.1,
21052
- letterSpacing: "-0.025em",
21053
- color: "var(--brand-text)",
21054
- marginBottom: "1rem"
21055
- },
21056
- ...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
21057
- children: title
21058
- }
21059
- ),
21060
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
21061
- "p",
21062
- {
21063
- style: {
21064
- fontFamily: "var(--brand-font-body)",
21065
- fontSize: "1rem",
21066
- lineHeight: 1.7,
21067
- fontWeight: 300,
21068
- color: "var(--brand-text-muted)",
21069
- maxWidth: "340px"
19798
+ ),
19799
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
19800
+ ]
19801
+ }
19802
+ ),
19803
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19804
+ LinkPopover,
19805
+ {
19806
+ panelRef: linkPopoverPanelRef,
19807
+ portalContainer: dialogPortalContainer,
19808
+ open: true,
19809
+ mode: linkPopover.mode ?? "edit",
19810
+ pages: sitePages,
19811
+ sections: currentSections,
19812
+ sectionsByPath,
19813
+ initialTarget: linkPopover.target,
19814
+ existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
19815
+ onClose: closeLinkPopover,
19816
+ onSubmit: handleLinkPopoverSubmit
21070
19817
  },
21071
- ...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
21072
- children: "This page doesn't have any content yet."
21073
- }
21074
- )
21075
- ] });
19818
+ linkPopover.key
19819
+ ) : null,
19820
+ floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19821
+ FloatingPanel,
19822
+ {
19823
+ open: true,
19824
+ title: floatingPanel.title,
19825
+ context: floatingPanel.context,
19826
+ position: floatingPanelPos,
19827
+ onPositionChange: setFloatingPanelPos,
19828
+ parentScroll: parentScrollSnap ?? parentScrollRef.current,
19829
+ onClose: closeFloatingPanelOnly,
19830
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19831
+ SocialsDisplayPanel,
19832
+ {
19833
+ display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
19834
+ onChange: (next) => {
19835
+ changeSocialsDisplay(floatingPanel.row, next);
19836
+ setFloatingPanel({ ...floatingPanel });
19837
+ }
19838
+ }
19839
+ )
19840
+ }
19841
+ ) : null
19842
+ ] }),
19843
+ bridgeRoot
19844
+ ) : null;
21076
19845
  }
21077
19846
  // Annotate the CommonJS export names for ESM import in node:
21078
19847
  0 && (module.exports = {
@@ -21091,7 +19860,6 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
21091
19860
  DropdownMenuItem,
21092
19861
  DropdownMenuSeparator,
21093
19862
  DropdownMenuTrigger,
21094
- EmptySection,
21095
19863
  ItemActionToolbar,
21096
19864
  ItemInteractionLayer,
21097
19865
  LinkEditorPanel,