@ohhwells/bridge 0.1.64-next.177 → 0.1.64

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,
@@ -170,7 +169,6 @@ function applyTreeToState(state, payload) {
170
169
  const entry = {
171
170
  id: payload.id,
172
171
  label: payload.label ?? "Generated section",
173
- ...typeof payload.path === "string" && payload.path ? { path: payload.path } : {},
174
172
  afterSection: payload.mode === "insert" && !insertBefore ? payload.targetSectionId ?? null : null,
175
173
  ...insertBefore && payload.targetSectionId ? { beforeSection: payload.targetSectionId } : {},
176
174
  ...payload.mode === "replace" && payload.targetSectionId ? { replaces: payload.targetSectionId } : {},
@@ -193,317 +191,6 @@ function deleteSectionFromState(state, sectionId) {
193
191
  return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
194
192
  }
195
193
 
196
- // src/lib/brand-chrome.ts
197
- var BRAND_NAME_KEY = "__ohw_brand_name";
198
- var BRAND_TITLE_KEY = "__ohw_site_title";
199
- var BRAND_FAVICON_LETTER_KEY = "__ohw_favicon_letter";
200
- var BRAND_CHROME_KEYS = /* @__PURE__ */ new Set([
201
- BRAND_NAME_KEY,
202
- BRAND_TITLE_KEY,
203
- BRAND_FAVICON_LETTER_KEY
204
- ]);
205
- function upsertMeta(selector, attr, token, value) {
206
- let el = document.head.querySelector(selector);
207
- if (!el) {
208
- el = document.createElement("meta");
209
- el.setAttribute(attr, token);
210
- document.head.appendChild(el);
211
- }
212
- if (el.getAttribute("content") !== value) el.setAttribute("content", value);
213
- }
214
- function escapeXml(value) {
215
- return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
216
- }
217
- function applyLetterFavicon(letter) {
218
- 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>`;
219
- const href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
220
- let link = document.head.querySelector('link[rel="icon"]');
221
- if (!link) {
222
- link = document.createElement("link");
223
- link.rel = "icon";
224
- document.head.appendChild(link);
225
- }
226
- link.type = "image/svg+xml";
227
- if (link.href !== href) link.href = href;
228
- }
229
- function applyBrandChrome(content) {
230
- const name = content[BRAND_NAME_KEY];
231
- if (typeof name === "string" && name.length > 0) {
232
- document.querySelectorAll("[data-ohw-wordmark]").forEach((el) => {
233
- if (el.textContent !== name) el.textContent = name;
234
- if (el.getAttribute("title") !== name) el.setAttribute("title", name);
235
- });
236
- }
237
- const title = content[BRAND_TITLE_KEY];
238
- if (typeof title === "string" && title.length > 0) {
239
- if (document.title !== title) document.title = title;
240
- upsertMeta('meta[property="og:title"]', "property", "og:title", title);
241
- upsertMeta('meta[name="twitter:title"]', "name", "twitter:title", title);
242
- }
243
- const letter = content[BRAND_FAVICON_LETTER_KEY];
244
- if (typeof letter === "string" && letter.length > 0) {
245
- applyLetterFavicon(letter);
246
- }
247
- }
248
-
249
- // src/lib/brand-kit.ts
250
- var BRAND_KIT_KEY = "__ohw_brand";
251
- var BRAND_VAR_PREFIX = "--ohw-brand-";
252
- var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
253
- (role) => `${BRAND_VAR_PREFIX}${role}`
254
- );
255
- var FONT_VARS = {
256
- heading: ["--font-heading", "--font-display", "--brand-font-heading"],
257
- body: ["--font-body", "--brand-font-body"]
258
- };
259
- var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
260
- function brandColorVars(kit) {
261
- const { dark, primary, accent, light } = kit.palette;
262
- const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
263
- return {
264
- [`${BRAND_VAR_PREFIX}primary`]: primary,
265
- [`${BRAND_VAR_PREFIX}accent`]: accent,
266
- [`${BRAND_VAR_PREFIX}light`]: light,
267
- [`${BRAND_VAR_PREFIX}dark`]: dark,
268
- [`${BRAND_VAR_PREFIX}surface`]: mix(light, 95, dark),
269
- [`${BRAND_VAR_PREFIX}border`]: mix(light, 85, dark),
270
- [`${BRAND_VAR_PREFIX}muted`]: mix(dark, 62, light)
271
- };
272
- }
273
- function parseBrandKit(raw) {
274
- if (!raw) return null;
275
- try {
276
- const parsed = JSON.parse(raw);
277
- const p = parsed?.palette;
278
- const f = parsed?.fonts;
279
- 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") {
280
- return null;
281
- }
282
- return {
283
- palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
284
- fonts: { heading: f.heading, body: f.body }
285
- };
286
- } catch {
287
- return null;
288
- }
289
- }
290
- function familyOf(stack) {
291
- const first = stack.split(",")[0]?.trim() ?? "";
292
- return first.replace(/^['"]|['"]$/g, "");
293
- }
294
- function loadBrandFonts(families) {
295
- const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
296
- if (unique.length === 0) return;
297
- const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
298
- const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
299
- let link = document.getElementById(BRAND_FONT_LINK_ID);
300
- if (!link) {
301
- link = document.createElement("link");
302
- link.id = BRAND_FONT_LINK_ID;
303
- link.rel = "stylesheet";
304
- document.head.appendChild(link);
305
- }
306
- if (link.href !== href) link.href = href;
307
- }
308
- function applyBrandToDom(kit) {
309
- const root = document.documentElement;
310
- if (!kit) {
311
- for (const name of BRAND_VAR_NAMES) root.style.removeProperty(name);
312
- for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
313
- document.getElementById(BRAND_FONT_LINK_ID)?.remove();
314
- return;
315
- }
316
- for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
317
- for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
318
- for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
319
- loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
320
- }
321
-
322
- // src/lib/section-styles.ts
323
- var STYLE_STORE_KEY = "__ohw_styles";
324
- var STYLE_SHEET_ID = "ohw-section-styles";
325
- function parseStyleStore(raw) {
326
- if (!raw) return null;
327
- try {
328
- const parsed = JSON.parse(raw);
329
- if (parsed?.v !== 1) return null;
330
- return {
331
- v: 1,
332
- sections: typeof parsed.sections === "object" && parsed.sections ? parsed.sections : {},
333
- nodes: typeof parsed.nodes === "object" && parsed.nodes ? parsed.nodes : {}
334
- };
335
- } catch {
336
- return null;
337
- }
338
- }
339
- var BG_VALUES = {
340
- surface: "color-mix(in srgb, var(--ohw-brand-light, var(--color-light, #ECECEB)) 94%, var(--ohw-brand-dark, var(--color-dark, #0C0A09)))",
341
- accent: "var(--ohw-brand-primary, var(--color-primary, #0078E5))",
342
- "accent-soft": "color-mix(in srgb, var(--ohw-brand-primary, var(--color-primary, #0078E5)) 12%, var(--ohw-brand-light, var(--color-light, #FFFFFF)))"
343
- };
344
- var HEADLINE_SIZES = { md: 24, lg: 32, xl: 40, display: 56 };
345
- function styleSheetCss() {
346
- const rules = [];
347
- for (const [tone, value] of Object.entries(BG_VALUES)) {
348
- rules.push(`[data-ohw-style-bg="${tone}"] { background: ${value} !important; }`);
349
- }
350
- rules.push(
351
- `[data-ohw-style-bg="accent"] { color: var(--ohw-brand-light, var(--color-light, #FFFFFF)) !important; }`
352
- );
353
- rules.push(
354
- `[data-ohw-style-distribution="space-between"] { display: flex !important; flex-direction: column; justify-content: space-between; }`,
355
- `[data-ohw-style-distribution="center"] { display: flex !important; flex-direction: column; justify-content: center; }`
356
- );
357
- for (const [scale, size] of Object.entries(HEADLINE_SIZES)) {
358
- rules.push(
359
- `[data-ohw-style-headline="${scale}"] :is(h1, h2, h3) { font-size: ${size}px !important; line-height: 1.15 !important; }`
360
- );
361
- }
362
- rules.push(
363
- `[data-ohw-style-aspect="fill-height"] img { height: 100% !important; aspect-ratio: auto !important; object-fit: cover; }`
364
- );
365
- for (const aspect of ["1:1", "4:5", "3:4", "3:2", "16:9", "2:1", "3:1"]) {
366
- rules.push(
367
- `[data-ohw-style-aspect="${aspect.replace(":", "-")}"] img { aspect-ratio: ${aspect.replace(":", " / ")} !important; height: auto !important; object-fit: cover; }`
368
- );
369
- }
370
- const pad = { tight: 40, balanced: 64, airy: 96 };
371
- for (const [spacing, px] of Object.entries(pad)) {
372
- rules.push(
373
- `[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
374
- );
375
- }
376
- return rules.join("\n");
377
- }
378
- var STYLE_FONT_LINK_ID = "ohw-style-fonts";
379
- function loadStyleFonts(families) {
380
- const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
381
- const existing = document.getElementById(STYLE_FONT_LINK_ID);
382
- if (unique.length === 0) {
383
- existing?.remove();
384
- return;
385
- }
386
- const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
387
- const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
388
- let link = existing;
389
- if (!link) {
390
- link = document.createElement("link");
391
- link.id = STYLE_FONT_LINK_ID;
392
- link.rel = "stylesheet";
393
- document.head.appendChild(link);
394
- }
395
- if (link.href !== href) link.href = href;
396
- }
397
- var SECTION_ATTRS = {
398
- sectionBackground: "data-ohw-style-bg",
399
- textDistribution: "data-ohw-style-distribution",
400
- headlineScale: "data-ohw-style-headline",
401
- imageAspect: "data-ohw-style-aspect",
402
- spacing: "data-ohw-style-spacing"
403
- };
404
- var NODE_WROTE_ATTR = "data-ohw-style-node";
405
- var NODE_PROPS = ["color", "font-family", "font-size", "background"];
406
- function saveInline(el, prop) {
407
- const attr = `data-ohw-style-prev-${prop}`;
408
- if (!el.hasAttribute(attr)) el.setAttribute(attr, el.style.getPropertyValue(prop));
409
- }
410
- function restoreInline(el, prop) {
411
- const attr = `data-ohw-style-prev-${prop}`;
412
- if (!el.hasAttribute(attr)) return;
413
- const prev = el.getAttribute(attr) ?? "";
414
- if (prev) el.style.setProperty(prop, prev);
415
- else el.style.removeProperty(prop);
416
- el.removeAttribute(attr);
417
- }
418
- function ensureStyleSheet() {
419
- let el = document.getElementById(STYLE_SHEET_ID);
420
- if (!el) {
421
- el = document.createElement("style");
422
- el.id = STYLE_SHEET_ID;
423
- document.head.appendChild(el);
424
- }
425
- const css = styleSheetCss();
426
- if (el.textContent !== css) el.textContent = css;
427
- }
428
- function clearSectionAttrs(root) {
429
- for (const attr of Object.values(SECTION_ATTRS)) {
430
- for (const el of Array.from(root.querySelectorAll(`[${attr}]`))) el.removeAttribute(attr);
431
- }
432
- for (const el of Array.from(root.querySelectorAll("[data-ohw-style-bgcolor]"))) {
433
- restoreInline(el, "background");
434
- el.removeAttribute("data-ohw-style-bgcolor");
435
- }
436
- }
437
- function clearNodeProps(root) {
438
- for (const el of Array.from(root.querySelectorAll(`[${NODE_WROTE_ATTR}]`))) {
439
- const h = el;
440
- for (const prop of NODE_PROPS) restoreInline(h, prop);
441
- h.removeAttribute(NODE_WROTE_ATTR);
442
- }
443
- }
444
- function buttonSurfaceOf(el) {
445
- return el.closest("a, button") ?? el;
446
- }
447
- function applyStylesToDom(store) {
448
- ensureStyleSheet();
449
- clearSectionAttrs(document);
450
- clearNodeProps(document);
451
- loadStyleFonts(
452
- store ? Object.values(store.nodes).flatMap((n) => n.fontFamily ? [n.fontFamily] : []) : []
453
- );
454
- if (!store) return;
455
- for (const [sectionId, override] of Object.entries(store.sections)) {
456
- const sections = document.querySelectorAll(
457
- `[data-ohw-section="${CSS.escape(sectionId)}"]`
458
- );
459
- for (const section of Array.from(sections)) {
460
- for (const [prop, attr] of Object.entries(SECTION_ATTRS)) {
461
- const value = override[prop];
462
- if (value === void 0) continue;
463
- if (prop === "sectionBackground" && override.sectionBackgroundColor !== void 0) continue;
464
- section.setAttribute(attr, String(value).replace(":", "-"));
465
- }
466
- if (override.sectionBackgroundColor !== void 0) {
467
- saveInline(section, "background");
468
- section.style.setProperty("background", override.sectionBackgroundColor, "important");
469
- section.setAttribute("data-ohw-style-bgcolor", "");
470
- }
471
- }
472
- }
473
- for (const [key, override] of Object.entries(store.nodes)) {
474
- const nodes = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
475
- for (const el of Array.from(nodes)) {
476
- if (override.color !== void 0) {
477
- saveInline(el, "color");
478
- el.style.setProperty("color", override.color, "important");
479
- el.setAttribute(NODE_WROTE_ATTR, "");
480
- }
481
- if (override.fontFamily !== void 0) {
482
- saveInline(el, "font-family");
483
- el.style.setProperty("font-family", `'${override.fontFamily}'`, "important");
484
- el.setAttribute(NODE_WROTE_ATTR, "");
485
- }
486
- if (override.fontSize !== void 0) {
487
- saveInline(el, "font-size");
488
- el.style.setProperty("font-size", `${override.fontSize}px`, "important");
489
- el.setAttribute(NODE_WROTE_ATTR, "");
490
- }
491
- if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
492
- const surface = buttonSurfaceOf(el);
493
- if (override.buttonBackground !== void 0) {
494
- saveInline(surface, "background");
495
- surface.style.setProperty("background", override.buttonBackground, "important");
496
- }
497
- if (override.buttonText !== void 0) {
498
- saveInline(surface, "color");
499
- surface.style.setProperty("color", override.buttonText, "important");
500
- }
501
- surface.setAttribute(NODE_WROTE_ATTR, "");
502
- }
503
- }
504
- }
505
- }
506
-
507
194
  // src/ui/ai-tree/aiSectionsManager.tsx
508
195
  var import_react_dom = require("react-dom");
509
196
  var import_client = require("react-dom/client");
@@ -518,8 +205,7 @@ function lucideByName(name) {
518
205
  }
519
206
  var typeStyle = (spec, font) => ({
520
207
  fontFamily: font,
521
- // Headings shrink with the viewport (reaching full size around ~900px wide); body copy stays put.
522
- 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,
523
209
  lineHeight: spec.line,
524
210
  fontWeight: spec.weight
525
211
  });
@@ -546,8 +232,6 @@ var AI_RESPONSIVE_CSS = [
546
232
  " [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
547
233
  " [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
548
234
  " [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
549
- " [data-ai-responsive] { overflow-x: hidden; }",
550
- " [data-ai-responsive] img { max-width: 100%; }",
551
235
  "}"
552
236
  ].join("\n");
553
237
  var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
@@ -1555,20 +1239,6 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1555
1239
  const overlayAlpha = { low: 0.25, medium: 0.45, high: 0.65 }[settings.overlayIntensity ?? "medium"];
1556
1240
  const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
1557
1241
  const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
1558
- const toneBackground = (() => {
1559
- const { dark, primary, light } = resolvedBrand.palette;
1560
- switch (settings.sectionBackground) {
1561
- case "surface":
1562
- return `color-mix(in srgb, ${light} 94%, ${dark})`;
1563
- case "accent":
1564
- return primary;
1565
- case "accent-soft":
1566
- return `color-mix(in srgb, ${primary} 12%, ${light})`;
1567
- default:
1568
- return void 0;
1569
- }
1570
- })();
1571
- const distributed = !isOverlay && settings.textDistribution;
1572
1242
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1573
1243
  "section",
1574
1244
  {
@@ -1578,11 +1248,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1578
1248
  style: {
1579
1249
  position: "relative",
1580
1250
  padding: `${pad}px 0`,
1581
- background: toneBackground ?? (isOverlay && !backgroundUrl ? "#DBEAFE" : void 0),
1251
+ background: isOverlay && !backgroundUrl ? "#DBEAFE" : void 0,
1582
1252
  backgroundImage: backgroundUrl ? `url(${backgroundUrl})` : void 0,
1583
1253
  backgroundSize: "cover",
1584
- backgroundPosition: "center",
1585
- color: settings.sectionBackground === "accent" ? resolvedBrand.palette.light : void 0
1254
+ backgroundPosition: "center"
1586
1255
  },
1587
1256
  children: [
1588
1257
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
@@ -1606,24 +1275,10 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
1606
1275
  display: "grid",
1607
1276
  gridTemplateColumns: "repeat(12, 1fr)",
1608
1277
  gap: AI_TREE_TOKENS.spacing6,
1609
- alignItems: distributed === "space-between" ? "stretch" : (distributed ?? settings.verticalPosition) === "top" ? "start" : "center",
1278
+ alignItems: settings.verticalPosition === "top" ? "start" : "center",
1610
1279
  marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
1611
1280
  },
1612
- children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1613
- "div",
1614
- {
1615
- "data-ai-cell": "",
1616
- style: {
1617
- gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
1618
- minWidth: 0,
1619
- // space-between: each column becomes a flex column whose content spreads over
1620
- // the full row height instead of clumping at the top.
1621
- ...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
1622
- },
1623
- children: renderNode(block, ctx, `r${r2}.b${b}`)
1624
- },
1625
- b
1626
- ))
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))
1627
1282
  },
1628
1283
  r2
1629
1284
  ))
@@ -1639,34 +1294,17 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
1639
1294
  var CONTAINER_ATTR = "data-ohw-ai-generated";
1640
1295
  var REPLACED_ATTR = "data-ohw-ai-replaced-by";
1641
1296
  var REMOVED_ATTR = "data-ohw-ai-removed";
1642
- function readRootVar(name) {
1643
- if (typeof document === "undefined") return "";
1644
- return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
1645
- }
1646
- function deriveBrandOverride() {
1647
- const dark = readRootVar("--ohw-brand-dark");
1648
- const primary = readRootVar("--ohw-brand-primary");
1649
- const light = readRootVar("--ohw-brand-light");
1650
- if (!dark || !primary || !light) return null;
1651
- const accent = readRootVar("--ohw-brand-accent");
1652
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1653
- const body = readRootVar("--font-body");
1654
- return {
1655
- palette: { dark, primary, accent: accent || dark, light },
1656
- fonts: {
1657
- heading: heading || AI_DEFAULT_BRAND.fonts.heading,
1658
- body: body || AI_DEFAULT_BRAND.fonts.body
1659
- }
1660
- };
1661
- }
1662
1297
  function deriveTemplateBrand() {
1663
- const dark = readRootVar("--color-dark");
1664
- const primary = readRootVar("--color-primary");
1665
- 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");
1666
1304
  if (!dark || !primary || !light) return null;
1667
- const accent = readRootVar("--color-accent");
1668
- const heading = readRootVar("--font-heading") || readRootVar("--font-display");
1669
- 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");
1670
1308
  return {
1671
1309
  palette: { dark, primary, accent: accent || dark, light },
1672
1310
  fonts: {
@@ -1758,12 +1396,8 @@ function syncReplacedOriginals(state) {
1758
1396
  }
1759
1397
  function applyAiSectionsToDom(state, options) {
1760
1398
  if (typeof document === "undefined") return;
1761
- const brandOverride = deriveBrandOverride();
1762
1399
  const templateBrand = deriveTemplateBrand();
1763
- const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
1764
- const pagePath = window.location.pathname;
1765
- const pageSections = state.sections.filter((entry) => !entry.path || entry.path === pagePath);
1766
- const activeIds = new Set(pageSections.map((entry) => entry.id));
1400
+ const activeIds = new Set(state.sections.map((entry) => entry.id));
1767
1401
  for (const [id, section] of mounted) {
1768
1402
  if (!activeIds.has(id)) {
1769
1403
  section.root.unmount();
@@ -1771,8 +1405,8 @@ function applyAiSectionsToDom(state, options) {
1771
1405
  mounted.delete(id);
1772
1406
  }
1773
1407
  }
1774
- for (const entry of pageSections) {
1775
- const serialized = JSON.stringify(entry) + brandKey;
1408
+ for (const entry of state.sections) {
1409
+ const serialized = JSON.stringify(entry);
1776
1410
  const existing = mounted.get(entry.id);
1777
1411
  if (existing && existing.serialized === serialized && existing.container.isConnected) {
1778
1412
  continue;
@@ -1786,7 +1420,6 @@ function applyAiSectionsToDom(state, options) {
1786
1420
  mounted.delete(entry.id);
1787
1421
  }
1788
1422
  container.setAttribute("data-ohw-section", entry.id);
1789
- container.setAttribute("data-ohw-instance", entry.id);
1790
1423
  container.setAttribute("data-ohw-section-label", entry.label);
1791
1424
  placeContainer(container, entry);
1792
1425
  const root = mounted.get(entry.id)?.root ?? (0, import_client.createRoot)(container);
@@ -1797,7 +1430,7 @@ function applyAiSectionsToDom(state, options) {
1797
1430
  AiTreeRenderer,
1798
1431
  {
1799
1432
  tree: entry.tree,
1800
- brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1433
+ brand: entry.brand ?? options?.brand ?? templateBrand ?? void 0,
1801
1434
  resolveMedia,
1802
1435
  editKeyPrefix: `ai.${entry.id}`
1803
1436
  }
@@ -2414,7 +2047,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2414
2047
  const autoId = (0, import_react5.useId)();
2415
2048
  const insertAfter = insertAfterProp ?? autoId;
2416
2049
  const [schedule, setSchedule] = (0, import_react5.useState)(null);
2417
- const [loading, setLoading] = (0, import_react5.useState)(initialScheduleId !== null);
2050
+ const [loading, setLoading] = (0, import_react5.useState)(true);
2418
2051
  const [inEditor, setInEditor] = (0, import_react5.useState)(false);
2419
2052
  const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
2420
2053
  const [modalState, setModalState] = (0, import_react5.useState)(null);
@@ -2588,10 +2221,8 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2588
2221
  "*"
2589
2222
  );
2590
2223
  };
2224
+ if (!inEditor && !loading && !schedule) return null;
2591
2225
  const sectionId = `scheduling-${insertAfter}`;
2592
- if (!inEditor && !loading && !schedule) {
2593
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
2594
- }
2595
2226
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2596
2227
  "section",
2597
2228
  {
@@ -6848,14 +6479,14 @@ function showSuccess(form, message) {
6848
6479
  });
6849
6480
  return;
6850
6481
  }
6851
- const text = message ?? form.getAttribute("data-ohw-success-text") ?? DEFAULT_SUCCESS_TEXT;
6482
+ const text = message || form.getAttribute("data-ohw-success-text") || DEFAULT_SUCCESS_TEXT;
6852
6483
  const note = document.createElement("p");
6853
6484
  note.setAttribute("data-ohw-form-success", "");
6854
6485
  note.setAttribute("role", "status");
6855
6486
  note.innerHTML = text;
6856
6487
  form.replaceChildren(note);
6857
6488
  }
6858
- function showSubmitError(form) {
6489
+ function showSubmitError(form, message = "Something went wrong. Please try again.") {
6859
6490
  let note = form.querySelector("[data-ohw-form-error]");
6860
6491
  if (!note) {
6861
6492
  note = document.createElement("p");
@@ -6864,7 +6495,7 @@ function showSubmitError(form) {
6864
6495
  note.style.marginTop = "8px";
6865
6496
  form.appendChild(note);
6866
6497
  }
6867
- note.textContent = "Something went wrong. Please try again.";
6498
+ note.textContent = message;
6868
6499
  note.style.display = "";
6869
6500
  }
6870
6501
  function clearSubmitError(form) {
@@ -6890,6 +6521,9 @@ function ensureSuccessTextEl(form, formKey, initialText) {
6890
6521
  form.appendChild(el);
6891
6522
  return el;
6892
6523
  }
6524
+ function successInitialFor(form, formKey, content) {
6525
+ return content[formSuccessKey(formKey)] || form.getAttribute("data-ohw-success-text") || DEFAULT_SUCCESS_TEXT;
6526
+ }
6893
6527
  function setFormViewState(form, formKey, state, initialText) {
6894
6528
  const success = ensureSuccessTextEl(form, formKey, initialText);
6895
6529
  Array.from(form.children).forEach((child) => {
@@ -6907,38 +6541,54 @@ function setFormViewState(form, formKey, state, initialText) {
6907
6541
  success.style.display = state === "success" ? "" : "none";
6908
6542
  }
6909
6543
  var BOUND_ATTR = "data-ohw-form-bound";
6544
+ var publishedFormContext = {
6545
+ apiUrl: "",
6546
+ subdomain: "",
6547
+ content: {}
6548
+ };
6910
6549
  function bindPublishedForms(apiUrl, subdomain, content = {}) {
6911
- document.querySelectorAll(FORM_SELECTOR).forEach((form) => {
6912
- if (form.hasAttribute(BOUND_ATTR)) return;
6913
- if (!(form instanceof HTMLFormElement)) return;
6914
- const formKey = formKeyOf(form);
6915
- if (!formKey) return;
6916
- form.setAttribute(BOUND_ATTR, "");
6917
- form.addEventListener("submit", async (e) => {
6550
+ publishedFormContext = { apiUrl, subdomain, content };
6551
+ if (document.documentElement.hasAttribute(BOUND_ATTR)) return;
6552
+ document.documentElement.setAttribute(BOUND_ATTR, "");
6553
+ document.addEventListener(
6554
+ "submit",
6555
+ async (e) => {
6556
+ const target = e.target;
6557
+ const form = target?.closest(FORM_SELECTOR);
6558
+ if (!form || !(form instanceof HTMLFormElement)) return;
6559
+ const formKey = formKeyOf(form);
6560
+ if (!formKey) return;
6918
6561
  e.preventDefault();
6919
6562
  clearSubmitError(form);
6563
+ const filled = collectFormFields(form);
6564
+ if (!Object.values(filled).some((value) => value.trim() !== "")) {
6565
+ showSubmitError(form, "Please fill in at least one field.");
6566
+ return;
6567
+ }
6920
6568
  const submitButton = form.querySelector(
6921
6569
  'button[type="submit"], input[type="submit"], button:not([type])'
6922
6570
  );
6923
6571
  if (submitButton) submitButton.disabled = true;
6924
6572
  try {
6925
- const response = await fetch(`${apiUrl}/api/public/sites/${subdomain}/forms/submissions`, {
6573
+ const { apiUrl: api, subdomain: site, content: latest } = publishedFormContext;
6574
+ const response = await fetch(`${api}/api/public/sites/${site}/forms/submissions`, {
6926
6575
  method: "POST",
6927
6576
  headers: { "Content-Type": "application/json" },
6928
6577
  body: JSON.stringify({
6929
6578
  formKey,
6930
- fields: collectFormFields(form),
6579
+ fields: filled,
6931
6580
  hasLongText: formHasLongText(form)
6932
6581
  })
6933
6582
  });
6934
6583
  if (!response.ok) throw new Error(`submit failed: ${response.status}`);
6935
- showSuccess(form, content[formSuccessKey(formKey)]);
6584
+ showSuccess(form, latest[formSuccessKey(formKey)]);
6936
6585
  } catch {
6937
6586
  showSubmitError(form);
6938
6587
  if (submitButton) submitButton.disabled = false;
6939
6588
  }
6940
- });
6941
- });
6589
+ },
6590
+ true
6591
+ );
6942
6592
  }
6943
6593
 
6944
6594
  // src/lib/form-fields.ts
@@ -6956,6 +6606,7 @@ var FIELD_TYPES = [
6956
6606
  ];
6957
6607
  var FIELD_ATTR = "data-ohw-form-field";
6958
6608
  var FIELD_TYPE_ATTR = "data-ohw-field-type";
6609
+ var PLACEHOLDER_EDIT_ATTR = "data-ohw-placeholder-edit";
6959
6610
  function fieldsKey(formKey) {
6960
6611
  return `${formKey}-fields`;
6961
6612
  }
@@ -6993,7 +6644,7 @@ function ensureFieldLabel(wrapper, key) {
6993
6644
  label.style.lineHeight = "1.3";
6994
6645
  const fromPlaceholder = input?.getAttribute("placeholder")?.trim();
6995
6646
  const text = fromPlaceholder && fromPlaceholder.length < 40 ? fromPlaceholder : key.replace(/[-_]/g, " ");
6996
- label.textContent = input?.hasAttribute("required") ? `${text} *` : text;
6647
+ label.textContent = text;
6997
6648
  if (input && input.parentElement === wrapper) wrapper.insertBefore(label, input);
6998
6649
  else wrapper.insertBefore(label, wrapper.firstChild);
6999
6650
  return label;
@@ -7049,8 +6700,11 @@ function readFieldsFromDom(form) {
7049
6700
  return {
7050
6701
  key: fieldKeyOf(wrapper),
7051
6702
  type: fieldTypeOf(wrapper),
7052
- label: fieldLabelOf(wrapper)?.textContent?.trim() ?? "",
7053
- placeholder: input?.getAttribute("placeholder") ?? "",
6703
+ label: fieldLabelText(fieldLabelOf(wrapper)).trim(),
6704
+ // While a field is selected its placeholder text lives in the value (see
6705
+ // beginPlaceholderEdit), so reading the attribute would store an empty one — whoever
6706
+ // happens to save at that moment must still record what the owner typed.
6707
+ placeholder: input ? input.hasAttribute(PLACEHOLDER_EDIT_ATTR) ? input.value : input.getAttribute("placeholder") ?? "" : "",
7054
6708
  required: Boolean(input?.hasAttribute("required"))
7055
6709
  };
7056
6710
  });
@@ -7078,7 +6732,7 @@ function applyFieldType(wrapper, type) {
7078
6732
  const followsDefaults = {
7079
6733
  // A label the owner wrote stays; one that still reads as a type name (or as the old
7080
6734
  // placeholder the template shipped) follows the new type.
7081
- label: isDefaultText(label?.textContent ?? "", (d) => d.label) || (label?.textContent ?? "").trim().replace(/\s*\*$/, "") === placeholder.trim()
6735
+ label: isDefaultText(label?.textContent ?? "", (d) => d.label) || fieldLabelText(label).trim() === placeholder.trim()
7082
6736
  };
7083
6737
  const { tag, inputType } = inputTagFor(type);
7084
6738
  wrapper.setAttribute(FIELD_TYPE_ATTR, type);
@@ -7092,8 +6746,7 @@ function applyFieldType(wrapper, type) {
7092
6746
  const applyDefaults = (el) => {
7093
6747
  el.setAttribute("placeholder", defaults.placeholder);
7094
6748
  if (label && followsDefaults.label) {
7095
- const required = (label.textContent ?? "").trim().endsWith("*");
7096
- label.textContent = required ? `${defaults.label} *` : defaults.label;
6749
+ label.textContent = defaults.label;
7097
6750
  }
7098
6751
  };
7099
6752
  if (input.tagName.toLowerCase() === tag) {
@@ -7113,13 +6766,19 @@ function applyFieldType(wrapper, type) {
7113
6766
  input.replaceWith(next);
7114
6767
  applyDefaults(next);
7115
6768
  }
6769
+ var REQUIRED_MARK_ATTR = "data-ohw-field-required";
6770
+ function fieldLabelText(label) {
6771
+ if (!label) return "";
6772
+ return (label.textContent ?? "").replace(/\s*\*\s*$/, "").trimEnd();
6773
+ }
7116
6774
  function syncRequiredMark(wrapper) {
7117
6775
  const label = fieldLabelOf(wrapper);
7118
6776
  if (!label) return;
7119
- const required = isFieldRequired(wrapper);
7120
- const base = (label.textContent ?? "").replace(/\s*\*\s*$/, "").trimEnd();
7121
- const next = required ? `${base} *` : base;
7122
- if (label.textContent !== next) label.textContent = next;
6777
+ label.querySelectorAll("[data-ohw-required-mark]").forEach((el) => el.remove());
6778
+ const words = fieldLabelText(label);
6779
+ if ((label.textContent ?? "") !== words) label.textContent = words;
6780
+ if (isFieldRequired(wrapper)) label.setAttribute(REQUIRED_MARK_ATTR, "");
6781
+ else label.removeAttribute(REQUIRED_MARK_ATTR);
7123
6782
  }
7124
6783
  function setFieldRequired(wrapper, required) {
7125
6784
  const input = fieldInputOf(wrapper);
@@ -7129,7 +6788,6 @@ function setFieldRequired(wrapper, required) {
7129
6788
  else input.removeAttribute("required");
7130
6789
  if (label) syncRequiredMark(wrapper);
7131
6790
  }
7132
- var PLACEHOLDER_EDIT_ATTR = "data-ohw-placeholder-edit";
7133
6791
  function beginPlaceholderEdit(wrapper) {
7134
6792
  const input = fieldInputOf(wrapper);
7135
6793
  if (!input || input.hasAttribute(PLACEHOLDER_EDIT_ATTR)) return;
@@ -7182,7 +6840,6 @@ function insertField(form, type) {
7182
6840
  const input = fieldInputOf(wrapper);
7183
6841
  if (input) {
7184
6842
  input.setAttribute("name", key);
7185
- input.setAttribute("data-ohw-key", key);
7186
6843
  input.removeAttribute("required");
7187
6844
  input.setAttribute("placeholder", defaults.placeholder);
7188
6845
  input.value = "";
@@ -7199,23 +6856,36 @@ function duplicateField(form, wrapper) {
7199
6856
  const input = fieldInputOf(copy);
7200
6857
  if (input) {
7201
6858
  input.setAttribute("name", key);
7202
- input.setAttribute("data-ohw-key", key);
6859
+ input.removeAttribute("data-ohw-key");
7203
6860
  input.value = "";
7204
6861
  }
6862
+ const label = fieldLabelOf(copy);
6863
+ if (label) label.setAttribute("data-ohw-key", `${key}-label`);
7205
6864
  wrapper.after(copy);
7206
6865
  return copy;
7207
6866
  }
7208
6867
  function removeField(wrapper) {
7209
6868
  wrapper.remove();
7210
6869
  }
7211
- function moveField(form, key, toIndex) {
6870
+ function applyFieldOrder(form, keys) {
7212
6871
  const wrappers = listFieldWrappers(form);
7213
- const moving = wrappers.find((wrapper) => fieldKeyOf(wrapper) === key);
7214
- if (!moving) return;
7215
- const rest = wrappers.filter((wrapper) => wrapper !== moving);
7216
- const target = rest[Math.max(0, Math.min(rest.length, toIndex))];
7217
- if (target) target.before(moving);
7218
- else rest[rest.length - 1]?.after(moving);
6872
+ const byKey = new Map(wrappers.map((wrapper) => [fieldKeyOf(wrapper), wrapper]));
6873
+ const ordered = keys.map((key) => byKey.get(key)).filter((w) => Boolean(w));
6874
+ if (ordered.length !== wrappers.length) return;
6875
+ const slots = wrappers.map((wrapper) => {
6876
+ const slot = document.createComment("ohw-field-slot");
6877
+ wrapper.replaceWith(slot);
6878
+ return slot;
6879
+ });
6880
+ ordered.forEach((wrapper, index) => slots[index].replaceWith(wrapper));
6881
+ }
6882
+ function moveField(form, key, toIndex) {
6883
+ const keys = listFieldWrappers(form).map(fieldKeyOf);
6884
+ const from = keys.indexOf(key);
6885
+ if (from === -1) return;
6886
+ const rest = keys.filter((k) => k !== key);
6887
+ rest.splice(Math.max(0, Math.min(rest.length, toIndex)), 0, key);
6888
+ applyFieldOrder(form, rest);
7219
6889
  }
7220
6890
  function reconcileFieldsFromContent(form, content) {
7221
6891
  const formKey = form.getAttribute("data-ohw-key");
@@ -7233,21 +6903,26 @@ function reconcileFieldsFromContent(form, content) {
7233
6903
  const input = fieldInputOf(wrapper);
7234
6904
  if (input) {
7235
6905
  input.setAttribute("name", spec.key);
7236
- input.setAttribute("data-ohw-key", spec.key);
7237
6906
  }
6907
+ fieldLabelOf(wrapper)?.setAttribute("data-ohw-key", `${spec.key}-label`);
7238
6908
  byKey.set(spec.key, wrapper);
7239
6909
  }
7240
6910
  applyFieldType(wrapper, spec.type);
7241
6911
  setFieldRequired(wrapper, spec.required);
7242
6912
  setFieldPlaceholder(wrapper, spec.placeholder);
7243
6913
  const label = fieldLabelOf(wrapper);
7244
- if (label && spec.label) label.textContent = spec.label;
6914
+ if (label && spec.label) label.textContent = spec.label.replace(/\s*\*\s*$/, "").trimEnd();
6915
+ syncRequiredMark(wrapper);
7245
6916
  });
7246
6917
  const wanted = new Set(stored.map((spec) => spec.key));
7247
6918
  listFieldWrappers(form).forEach((wrapper) => {
7248
6919
  if (!wanted.has(fieldKeyOf(wrapper))) wrapper.remove();
7249
6920
  });
7250
- stored.forEach((spec, index) => moveField(form, spec.key, index));
6921
+ const currentOrder = listFieldWrappers(form).map(fieldKeyOf).join("\0");
6922
+ const storedOrder = stored.map((spec) => spec.key).join("\0");
6923
+ if (currentOrder !== storedOrder) {
6924
+ applyFieldOrder(form, stored.map((spec) => spec.key));
6925
+ }
7251
6926
  }
7252
6927
 
7253
6928
  // src/ui/form-field-toolbar.tsx
@@ -7679,12 +7354,8 @@ function parseSectionsFromHtml(html) {
7679
7354
 
7680
7355
  // src/ui/ai-section/AiSectionOverlay.tsx
7681
7356
  var import_jsx_runtime17 = require("react/jsx-runtime");
7682
- function findSectionElement(instanceId) {
7683
- const escaped = CSS.escape(instanceId);
7684
- return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
7685
- }
7686
- function readRect(instanceId) {
7687
- const el = findSectionElement(instanceId);
7357
+ function readRect(sectionId) {
7358
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7688
7359
  if (!el) return null;
7689
7360
  const r2 = el.getBoundingClientRect();
7690
7361
  if (r2.width <= 0 || r2.height <= 0) return null;
@@ -7707,7 +7378,7 @@ function useLiveSectionRect(sectionId) {
7707
7378
  const opts = { capture: true, passive: true };
7708
7379
  window.addEventListener("scroll", update, opts);
7709
7380
  window.addEventListener("resize", update);
7710
- const el = findSectionElement(sectionId);
7381
+ const el = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
7711
7382
  const ro = el ? new ResizeObserver(update) : null;
7712
7383
  if (el && ro) ro.observe(el);
7713
7384
  const interval = setInterval(update, 500);
@@ -7720,14 +7391,6 @@ function useLiveSectionRect(sectionId) {
7720
7391
  }, [sectionId]);
7721
7392
  return rect;
7722
7393
  }
7723
- function computeSectionBoundaryFlags(instanceId) {
7724
- const topLevel = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
7725
- (el) => !el.parentElement?.closest("[data-ohw-section]")
7726
- );
7727
- const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
7728
- if (index === -1) return { isFirst: true, isLast: true };
7729
- return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
7730
- }
7731
7394
  var PRIMARY2 = "#0885FE";
7732
7395
  function edgeAwareRadius(rect) {
7733
7396
  const container = window.innerWidth <= 480 ? 16 : 24;
@@ -7801,7 +7464,6 @@ function AiSectionOverlay({
7801
7464
  }) {
7802
7465
  const [selectedId, setSelectedId] = (0, import_react8.useState)(null);
7803
7466
  const [reviewId, setReviewId] = (0, import_react8.useState)(null);
7804
- const [reviewButtonsHidden, setReviewButtonsHidden] = (0, import_react8.useState)(false);
7805
7467
  const reviewIdRef = (0, import_react8.useRef)(null);
7806
7468
  reviewIdRef.current = reviewId;
7807
7469
  const selectedIdRef = (0, import_react8.useRef)(null);
@@ -7810,7 +7472,7 @@ function AiSectionOverlay({
7810
7472
  (el) => {
7811
7473
  postToParent2({
7812
7474
  type: "ow:section-selected",
7813
- sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
7475
+ sectionId: el?.dataset.ohwSection ?? null,
7814
7476
  sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
7815
7477
  });
7816
7478
  },
@@ -7819,7 +7481,7 @@ function AiSectionOverlay({
7819
7481
  const selectFromElement = (0, import_react8.useCallback)(
7820
7482
  (el, options) => {
7821
7483
  const sectionEl = el?.closest("[data-ohw-section]") ?? null;
7822
- const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
7484
+ const id = sectionEl?.dataset.ohwSection ?? null;
7823
7485
  if (id === selectedIdRef.current) return;
7824
7486
  setSelectedId(id);
7825
7487
  if (options?.report !== false) report(sectionEl);
@@ -7860,10 +7522,9 @@ function AiSectionOverlay({
7860
7522
  }
7861
7523
  const found = readRect(sectionId) != null;
7862
7524
  setReviewId(found ? sectionId : null);
7863
- setReviewButtonsHidden(e.data.hideButtons === true);
7864
7525
  postToParent2({ type: "ow:ai-review-started", sectionId, found });
7865
7526
  if (found) {
7866
- 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" });
7867
7528
  }
7868
7529
  }
7869
7530
  };
@@ -7882,7 +7543,7 @@ function AiSectionOverlay({
7882
7543
  return;
7883
7544
  }
7884
7545
  const sec = t.closest("[data-ohw-section]");
7885
- setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
7546
+ setHoveredId(sec?.dataset.ohwSection ?? null);
7886
7547
  };
7887
7548
  const onLeave = () => setHoveredId(null);
7888
7549
  document.addEventListener("mousemove", onMove, { passive: true });
@@ -7914,29 +7575,9 @@ function AiSectionOverlay({
7914
7575
  },
7915
7576
  [postToParent2]
7916
7577
  );
7917
- const activeSelectionId = reviewId ? null : selectedId;
7918
- const selectionRect = useLiveSectionRect(activeSelectionId);
7578
+ const selectionRect = useLiveSectionRect(reviewId ? null : selectedId);
7919
7579
  const reviewRect = useLiveSectionRect(reviewId);
7920
7580
  const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
7921
- (0, import_react8.useEffect)(() => {
7922
- if (!activeSelectionId || !selectionRect) {
7923
- postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
7924
- return;
7925
- }
7926
- const { isFirst, isLast } = computeSectionBoundaryFlags(activeSelectionId);
7927
- postToParent2({
7928
- type: "ow:section-rect",
7929
- instanceId: activeSelectionId,
7930
- rect: {
7931
- top: selectionRect.top + window.scrollY,
7932
- left: selectionRect.left + window.scrollX,
7933
- width: selectionRect.width,
7934
- height: selectionRect.height
7935
- },
7936
- isFirst,
7937
- isLast
7938
- });
7939
- }, [activeSelectionId, selectionRect, postToParent2]);
7940
7581
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
7941
7582
  hoverRect && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
7942
7583
  "div",
@@ -7987,16 +7628,13 @@ function AiSectionOverlay({
7987
7628
  border: `2px solid ${PRIMARY2}`,
7988
7629
  borderRadius: edgeAwareRadius(reviewRect),
7989
7630
  zIndex: 2147483200,
7990
- // The veil itself: swallows clicks so the section stays locked until decided. This
7991
- // stopPropagation only guards the bubble phase; the bridge's capture-phase click
7992
- // handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
7993
- // 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.
7994
7632
  background: "rgba(8, 133, 254, 0.04)",
7995
7633
  pointerEvents: "auto",
7996
7634
  cursor: "default"
7997
7635
  },
7998
7636
  onClick: (e) => e.stopPropagation(),
7999
- children: !reviewButtonsHidden && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
7637
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
8000
7638
  "div",
8001
7639
  {
8002
7640
  style: {
@@ -11901,296 +11539,42 @@ function deleteFooterColumn(column) {
11901
11539
  };
11902
11540
  }
11903
11541
 
11904
- // src/lib/logo-identity.ts
11905
- var LOGO_TEXT_KEYS = ["nav-logo-text", "footer-logo-text", "logo-text"];
11906
- var LOGO_IMAGE_KEYS = ["nav-logo-image", "footer-logo", "footer-logo-image"];
11907
- var LOGO_HREF_KEYS = ["nav-logo-href", "footer-logo-href", "logo-href"];
11908
- var LOGO_PLACEHOLDER_KEY = "logo-is-placeholder";
11909
- var LOGO_ALT_KEY = "logo-alt";
11910
- var LOGO_IMAGE_URL_KEY = "nav-logo-image";
11911
- var PLACEHOLDER_BUSINESS_NAME = "Business name";
11912
- function resolveLogoDisplayText(text) {
11913
- const trimmed = (text ?? "").trim();
11914
- return trimmed || PLACEHOLDER_BUSINESS_NAME;
11915
- }
11916
- function isFooterLogoRoot(root) {
11917
- return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
11918
- }
11919
- function imageKeyForRoot(root) {
11920
- return isFooterLogoRoot(root) ? "footer-logo" : "nav-logo-image";
11921
- }
11922
- function textKeyForRoot(root) {
11923
- return isFooterLogoRoot(root) ? "footer-logo-text" : "nav-logo-text";
11924
- }
11925
- function ensureLogoHrefKey(root) {
11926
- if (!(root instanceof HTMLAnchorElement)) return;
11927
- if (root.hasAttribute("data-ohw-href-key")) return;
11928
- root.setAttribute("data-ohw-href-key", isFooterLogoRoot(root) ? "footer-logo-href" : "nav-logo-href");
11929
- }
11930
- function applyLogoIdentity(text, isPlaceholder) {
11931
- const display = resolveLogoDisplayText(text);
11932
- const placeholder = isPlaceholder || !text.trim() || display === PLACEHOLDER_BUSINESS_NAME;
11933
- for (const key of LOGO_TEXT_KEYS) {
11934
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
11935
- if (el.textContent !== display) el.textContent = display;
11936
- });
11937
- }
11938
- for (const key of LOGO_IMAGE_KEYS) {
11939
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
11940
- const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
11941
- if (img) img.alt = display;
11942
- });
11943
- }
11944
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((el) => {
11945
- if (placeholder) el.setAttribute("data-ohw-placeholder", "");
11946
- else el.removeAttribute("data-ohw-placeholder");
11947
- });
11948
- return display;
11949
- }
11950
- function applyLogoImage(url, alt) {
11951
- const displayAlt = resolveLogoDisplayText(alt);
11952
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
11953
- ensureLogoHrefKey(root);
11954
- const imageKey = imageKeyForRoot(root);
11955
- const textKey = textKeyForRoot(root);
11956
- let img = root.querySelector(`img[data-ohw-key="${imageKey}"]`) ?? (root.querySelector(`[data-ohw-key="${imageKey}"]`) instanceof HTMLImageElement ? root.querySelector(`[data-ohw-key="${imageKey}"]`) : null) ?? root.querySelector("img");
11957
- let textEl = root.querySelector(`[data-ohw-key="${textKey}"]`) ?? root.querySelector('[data-ohw-key="logo-text"]');
11958
- if (url) {
11959
- if (!img) {
11960
- img = document.createElement("img");
11961
- img.setAttribute("data-ohw-editable", "image");
11962
- img.setAttribute("data-ohw-key", imageKey);
11963
- img.alt = displayAlt;
11964
- img.style.height = "";
11965
- img.style.maxHeight = "none";
11966
- img.style.width = "auto";
11967
- img.style.display = "block";
11968
- img.style.objectFit = "contain";
11969
- root.insertBefore(img, root.firstChild);
11970
- } else {
11971
- img.setAttribute("data-ohw-editable", "image");
11972
- img.setAttribute("data-ohw-key", imageKey);
11973
- }
11974
- img.removeAttribute("srcset");
11975
- img.removeAttribute("sizes");
11976
- img.src = url;
11977
- img.alt = displayAlt;
11978
- img.style.display = "block";
11979
- if (textEl) textEl.style.display = "none";
11980
- root.removeAttribute("data-ohw-placeholder");
11981
- return;
11982
- }
11983
- if (img) {
11984
- img.removeAttribute("src");
11985
- img.removeAttribute("srcset");
11986
- img.removeAttribute("sizes");
11987
- img.alt = displayAlt;
11988
- img.style.display = "none";
11989
- }
11990
- if (!textEl) {
11991
- textEl = document.createElement("span");
11992
- textEl.setAttribute("data-ohw-editable", "plain");
11993
- textEl.setAttribute("data-ohw-key", textKey);
11994
- root.appendChild(textEl);
11995
- }
11996
- textEl.style.display = "";
11997
- if (textEl.textContent !== displayAlt) textEl.textContent = displayAlt;
11998
- if (!displayAlt.trim() || displayAlt === PLACEHOLDER_BUSINESS_NAME) {
11999
- root.setAttribute("data-ohw-placeholder", "");
12000
- } else {
12001
- root.removeAttribute("data-ohw-placeholder");
12002
- }
12003
- });
12004
- }
12005
- function applyLogoHref(href) {
12006
- const target = href.trim() || "/";
12007
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
12008
- ensureLogoHrefKey(root);
12009
- if (root instanceof HTMLAnchorElement) {
12010
- root.setAttribute("href", target);
12011
- }
12012
- });
12013
- for (const key of LOGO_HREF_KEYS) setStoredLinkHref(key, target);
12014
- }
12015
- function readLogoIdentityFromDom() {
12016
- let imageUrl = null;
12017
- for (const key of LOGO_IMAGE_KEYS) {
12018
- const el = document.querySelector(`[data-ohw-key="${key}"]`);
12019
- const img = el instanceof HTMLImageElement ? el : el?.querySelector("img");
12020
- const attrSrc = img?.getAttribute("src")?.trim() ?? "";
12021
- if (attrSrc && !attrSrc.startsWith("data:") && img && img.style.display !== "none") {
12022
- imageUrl = img.currentSrc || img.src;
12023
- break;
12024
- }
12025
- }
12026
- let text = PLACEHOLDER_BUSINESS_NAME;
12027
- let isPlaceholder = true;
12028
- for (const key of LOGO_TEXT_KEYS) {
12029
- const el = document.querySelector(`[data-ohw-key="${key}"]`);
12030
- if (el?.textContent?.trim()) {
12031
- text = el.textContent.trim();
12032
- const logoRoot2 = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
12033
- isPlaceholder = logoRoot2?.hasAttribute("data-ohw-placeholder") === true || text === PLACEHOLDER_BUSINESS_NAME;
12034
- break;
12035
- }
12036
- }
12037
- if (imageUrl) {
12038
- const logoImg = document.querySelector(
12039
- '[data-ohw-key="nav-logo-image"], [data-ohw-key="footer-logo"]'
12040
- );
12041
- const alt = logoImg?.alt?.trim() || text;
12042
- isPlaceholder = false;
12043
- const hrefEl = document.querySelector(
12044
- 'a[data-ohw-role="logo"], a[data-ohw-logo], [data-ohw-role="logo"]'
12045
- );
12046
- const href2 = (hrefEl instanceof HTMLAnchorElement ? hrefEl.getAttribute("href") : null) || hrefEl?.closest("a")?.getAttribute("href") || "/";
12047
- return { text, isPlaceholder, imageUrl, href: href2, alt };
12048
- }
12049
- const logoRoot = document.querySelector('[data-ohw-role="logo"], [data-ohw-logo]');
12050
- const href = (logoRoot instanceof HTMLAnchorElement ? logoRoot.getAttribute("href") : null) || logoRoot?.closest("a")?.getAttribute("href") || "/";
12051
- return { text, isPlaceholder, imageUrl: null, href, alt: text };
12052
- }
12053
- function applyLogoFromContent(content) {
12054
- const hasLogoIdentity = LOGO_PLACEHOLDER_KEY in content || LOGO_TEXT_KEYS.some((key) => key in content) || LOGO_IMAGE_KEYS.some((key) => key in content) || LOGO_ALT_KEY in content || LOGO_HREF_KEYS.some((key) => key in content);
12055
- if (!hasLogoIdentity) return false;
12056
- const logoText = content[LOGO_TEXT_KEYS[0]] ?? content[LOGO_TEXT_KEYS[1]] ?? readLogoIdentityFromDom().text;
12057
- const logoAlt = content[LOGO_ALT_KEY] ?? logoText;
12058
- const rawLogoImage = content[LOGO_IMAGE_URL_KEY] ?? content["footer-logo"] ?? content["footer-logo-image"] ?? null;
12059
- const logoImageUrl = typeof rawLogoImage === "string" && rawLogoImage.trim() ? rawLogoImage.trim() : null;
12060
- const imageExplicitlyCleared = LOGO_IMAGE_KEYS.some((key) => key in content) && !logoImageUrl;
12061
- const logoIsPlaceholder = LOGO_PLACEHOLDER_KEY in content ? content[LOGO_PLACEHOLDER_KEY] !== "false" : !logoImageUrl && (!logoText.trim() || logoText === PLACEHOLDER_BUSINESS_NAME);
12062
- if (logoImageUrl) {
12063
- applyLogoImage(logoImageUrl, logoAlt);
12064
- } else {
12065
- if (imageExplicitlyCleared) applyLogoImage(null, logoAlt);
12066
- applyLogoIdentity(logoText, logoIsPlaceholder);
12067
- }
12068
- const logoHref = content["nav-logo-href"] ?? content["footer-logo-href"] ?? content["logo-href"];
12069
- if (typeof logoHref === "string" && logoHref.trim()) {
12070
- applyLogoHref(logoHref);
12071
- }
12072
- return true;
12073
- }
12074
-
12075
- // src/lib/logo-size.ts
12076
- var LOGO_SIZE_DEFAULTS = {
12077
- navbar: 28,
12078
- footer: 32
12079
- };
12080
- var LOGO_SIZE_MIN = 16;
12081
- var LOGO_SIZE_MAX = 80;
12082
- var LOGO_SIZE_DESKTOP_KEYS = {
12083
- navbar: "nav-logo-size",
12084
- footer: "footer-logo-size"
12085
- };
12086
- var LOGO_SIZE_MOBILE_KEYS = {
12087
- navbar: "nav-logo-size-mobile",
12088
- footer: "footer-logo-size-mobile"
12089
- };
12090
- var LOGO_SIZE_KEYS = [
12091
- LOGO_SIZE_DESKTOP_KEYS.navbar,
12092
- LOGO_SIZE_DESKTOP_KEYS.footer,
12093
- LOGO_SIZE_MOBILE_KEYS.navbar,
12094
- LOGO_SIZE_MOBILE_KEYS.footer
12095
- ];
12096
- function isFooterLogoRoot2(root) {
12097
- return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
12098
- }
12099
- function getLogoPlacement(root) {
12100
- return isFooterLogoRoot2(root) ? "footer" : "navbar";
12101
- }
12102
- function parseLogoSizePx(raw, fallback) {
12103
- if (raw == null || raw === "") return fallback;
12104
- const n = Number.parseFloat(raw);
12105
- if (!Number.isFinite(n)) return fallback;
12106
- return Math.min(LOGO_SIZE_MAX, Math.max(LOGO_SIZE_MIN, Math.round(n)));
12107
- }
12108
- function isMobileLogoSizeFollowing(content, placement) {
12109
- const raw = content[LOGO_SIZE_MOBILE_KEYS[placement]];
12110
- return raw == null || raw.trim() === "";
12111
- }
12112
- function resolveDesktopLogoSize(content, placement) {
12113
- return parseLogoSizePx(content[LOGO_SIZE_DESKTOP_KEYS[placement]], LOGO_SIZE_DEFAULTS[placement]);
12114
- }
12115
- function resolveMobileLogoSize(content, placement) {
12116
- if (isMobileLogoSizeFollowing(content, placement)) {
12117
- return resolveDesktopLogoSize(content, placement);
12118
- }
12119
- return parseLogoSizePx(
12120
- content[LOGO_SIZE_MOBILE_KEYS[placement]],
12121
- resolveDesktopLogoSize(content, placement)
12122
- );
11542
+ // src/lib/add-footer-column.ts
11543
+ function buildFooterColumnEditContentPatch(result) {
11544
+ return {
11545
+ [result.headingKey]: result.heading,
11546
+ [result.hrefKey]: result.href,
11547
+ [result.labelKey]: result.label,
11548
+ [FOOTER_ORDER_KEY]: JSON.stringify(result.order)
11549
+ };
12123
11550
  }
12124
- function setRootSizeVars(root, desktopPx, mobilePx, following) {
12125
- root.style.setProperty("--ohw-logo-size", `${desktopPx}px`);
12126
- if (following) {
12127
- root.style.removeProperty("--ohw-logo-size-mobile");
12128
- } else {
12129
- root.style.setProperty("--ohw-logo-size-mobile", `${mobilePx}px`);
11551
+ function addFooterColumnWithPersist({
11552
+ postToParent: postToParent2
11553
+ }) {
11554
+ if (!canAddFooterColumn()) {
11555
+ postToParent2({
11556
+ type: "ow:toast",
11557
+ title: `Maximum ${MAX_FOOTER_COLUMNS} columns`,
11558
+ toastType: "error"
11559
+ });
11560
+ return null;
12130
11561
  }
12131
- root.querySelectorAll("img").forEach((img) => {
12132
- img.style.height = "";
12133
- img.style.maxHeight = "none";
12134
- img.style.width = "auto";
12135
- img.style.objectFit = "contain";
12136
- });
12137
- }
12138
- function applyLogoSizes(content) {
12139
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
12140
- const placement = getLogoPlacement(root);
12141
- const desktop = resolveDesktopLogoSize(content, placement);
12142
- const following = isMobileLogoSizeFollowing(content, placement);
12143
- const mobile = following ? desktop : resolveMobileLogoSize(content, placement);
12144
- setRootSizeVars(root, desktop, mobile, following);
12145
- });
12146
- }
12147
- function applyLogoSizeToPlacement(placement, desktopPx, mobilePx, following) {
12148
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
12149
- if (getLogoPlacement(root) !== placement) return;
12150
- setRootSizeVars(root, desktopPx, mobilePx, following);
11562
+ const result = insertFooterColumn();
11563
+ const patch = buildFooterColumnEditContentPatch(result);
11564
+ setStoredLinkHref(result.hrefKey, result.href);
11565
+ postToParent2({
11566
+ type: "ow:change",
11567
+ nodes: Object.entries(patch).map(([key, text]) => ({ key, text }))
12151
11568
  });
12152
- }
12153
- function logoHasUploadedImage(logoEl) {
12154
- if (logoEl.hasAttribute("data-ohw-placeholder")) return false;
12155
- const img = logoEl.querySelector('img[data-ohw-key="nav-logo-image"], img[data-ohw-key="footer-logo"], img[data-ohw-key="footer-logo-image"]') ?? logoEl.querySelector("img");
12156
- if (!img) return false;
12157
- const src = img.getAttribute("src")?.trim() ?? "";
12158
- if (!src || src.startsWith("data:")) return false;
12159
- if (img.style.display === "none") return false;
12160
- return true;
12161
- }
12162
- function getLogoInteractionRect(logoEl) {
12163
- if (logoHasUploadedImage(logoEl)) {
12164
- const img = logoEl.querySelector('img[data-ohw-key="nav-logo-image"], img[data-ohw-key="footer-logo"], img[data-ohw-key="footer-logo-image"]') ?? logoEl.querySelector("img");
12165
- if (img) {
12166
- const r2 = img.getBoundingClientRect();
12167
- if (r2.width > 0 && r2.height > 0) return r2;
12168
- }
12169
- }
12170
- const text = logoEl.querySelector(
12171
- '[data-ohw-key="nav-logo-text"], [data-ohw-key="footer-logo-text"]'
12172
- );
12173
- if (text) {
12174
- const style = window.getComputedStyle(text);
12175
- if (style.display !== "none" && style.visibility !== "hidden") {
12176
- const r2 = text.getBoundingClientRect();
12177
- if (r2.width > 0 && r2.height > 0) return r2;
12178
- }
12179
- }
12180
- return logoEl.getBoundingClientRect();
12181
- }
12182
- function readLogoSizeState(content, placement) {
12183
- const desktopPx = resolveDesktopLogoSize(content, placement);
12184
- const mobileFollowing = isMobileLogoSizeFollowing(content, placement);
12185
- const mobilePx = mobileFollowing ? desktopPx : resolveMobileLogoSize(content, placement);
12186
- return { desktopPx, mobilePx, mobileFollowing };
11569
+ postToParent2({ type: "ow:toast", title: "Item added", toastType: "success" });
11570
+ enforceLinkHrefs();
11571
+ return result;
12187
11572
  }
12188
11573
 
12189
11574
  // src/lib/site-wide-scope.ts
12190
11575
  function getLogoElement(el) {
12191
11576
  const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
12192
11577
  if (marked) return marked;
12193
- if (el.closest('[data-ohw-editable="icon"]')) return null;
12194
11578
  const root = el.closest("nav, [data-ohw-nav-root], footer");
12195
11579
  if (!root) return null;
12196
11580
  const anchor = el.closest("a");
@@ -12224,38 +11608,6 @@ function isSiteWideScopeActive(args) {
12224
11608
  return isSiteWideElement(args.selected) || isSiteWideElement(args.hoveredItem) || isSiteWideElement(args.hoveredNavContainer) || isSiteWideElement(args.active);
12225
11609
  }
12226
11610
 
12227
- // src/lib/add-footer-column.ts
12228
- function buildFooterColumnEditContentPatch(result) {
12229
- return {
12230
- [result.headingKey]: result.heading,
12231
- [result.hrefKey]: result.href,
12232
- [result.labelKey]: result.label,
12233
- [FOOTER_ORDER_KEY]: JSON.stringify(result.order)
12234
- };
12235
- }
12236
- function addFooterColumnWithPersist({
12237
- postToParent: postToParent2
12238
- }) {
12239
- if (!canAddFooterColumn()) {
12240
- postToParent2({
12241
- type: "ow:toast",
12242
- title: `Maximum ${MAX_FOOTER_COLUMNS} columns`,
12243
- toastType: "error"
12244
- });
12245
- return null;
12246
- }
12247
- const result = insertFooterColumn();
12248
- const patch = buildFooterColumnEditContentPatch(result);
12249
- setStoredLinkHref(result.hrefKey, result.href);
12250
- postToParent2({
12251
- type: "ow:change",
12252
- nodes: Object.entries(patch).map(([key, text]) => ({ key, text }))
12253
- });
12254
- postToParent2({ type: "ow:toast", title: "Item added", toastType: "success" });
12255
- enforceLinkHrefs();
12256
- return result;
12257
- }
12258
-
12259
11611
  // src/ui/FloatingPanel.tsx
12260
11612
  var import_react13 = require("react");
12261
11613
  var import_lucide_react14 = require("lucide-react");
@@ -12439,127 +11791,16 @@ function FloatingPanel({
12439
11791
  );
12440
11792
  }
12441
11793
 
12442
- // src/ui/logo-size-panel.tsx
12443
- var import_lucide_react15 = require("lucide-react");
11794
+ // src/ui/socials-display-panel.tsx
12444
11795
  var import_jsx_runtime28 = require("react/jsx-runtime");
12445
- function SizeSlider({
12446
- value,
11796
+ function DisplaySwitch({
11797
+ label,
11798
+ checked,
11799
+ disabled,
12447
11800
  onChange
12448
11801
  }) {
12449
- const pct = (value - LOGO_SIZE_MIN) / (LOGO_SIZE_MAX - LOGO_SIZE_MIN) * 100;
12450
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full flex-col gap-3", children: [
12451
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full items-center gap-2 text-sm font-medium leading-5", children: [
12452
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "min-w-0 flex-1 text-foreground", children: "Size" }),
12453
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "shrink-0 whitespace-nowrap text-muted-foreground", children: [
12454
- value,
12455
- " px"
12456
- ] })
12457
- ] }),
12458
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "relative h-2 w-full rounded-full bg-primary-50", children: [
12459
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12460
- "div",
12461
- {
12462
- className: "absolute inset-y-0 left-0 rounded-full bg-primary",
12463
- style: { width: `${pct}%` }
12464
- }
12465
- ),
12466
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12467
- "input",
12468
- {
12469
- type: "range",
12470
- min: LOGO_SIZE_MIN,
12471
- max: LOGO_SIZE_MAX,
12472
- step: 1,
12473
- value,
12474
- "aria-label": "Logo size",
12475
- className: cn(
12476
- "absolute inset-0 h-full w-full cursor-pointer appearance-none bg-transparent",
12477
- "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:size-5",
12478
- "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2",
12479
- "[&::-webkit-slider-thumb]:border-primary [&::-webkit-slider-thumb]:bg-background",
12480
- "[&::-moz-range-thumb]:size-5 [&::-moz-range-thumb]:rounded-full",
12481
- "[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary",
12482
- "[&::-moz-range-thumb]:bg-background"
12483
- ),
12484
- onChange: (e) => onChange(Number(e.target.value))
12485
- }
12486
- )
12487
- ] })
12488
- ] });
12489
- }
12490
- function LogoSizePanel({
12491
- viewport,
12492
- sizePx,
12493
- mobileFollowing = true,
12494
- onSizeChange,
12495
- onCustomizeMobile,
12496
- onResetMobile,
12497
- onUpdateEverywhere,
12498
- className
12499
- }) {
12500
- const showFollowing = viewport === "mobile" && mobileFollowing;
12501
- const showMobileSlider = viewport === "mobile" && !mobileFollowing;
12502
- const showDesktopSlider = viewport === "desktop";
12503
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: cn("flex w-full flex-col gap-4", className), children: [
12504
- showFollowing ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
12505
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-start gap-1", children: [
12506
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react15.Link, { size: 16, className: "mt-0.5 shrink-0 text-foreground", "aria-hidden": true }),
12507
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-sm font-semibold leading-5 text-foreground", children: "Following desktop size" })
12508
- ] }),
12509
- /* @__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." }),
12510
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12511
- Button,
12512
- {
12513
- type: "button",
12514
- variant: "outline",
12515
- size: "sm",
12516
- className: "h-9 w-full min-w-0 cursor-pointer",
12517
- onClick: onCustomizeMobile,
12518
- children: "Customize for mobile"
12519
- }
12520
- )
12521
- ] }) : null,
12522
- showDesktopSlider || showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(SizeSlider, { value: sizePx, onChange: onSizeChange }) : null,
12523
- showMobileSlider ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12524
- Button,
12525
- {
12526
- type: "button",
12527
- variant: "outline",
12528
- size: "sm",
12529
- className: "h-9 w-full min-w-0 cursor-pointer",
12530
- onClick: onResetMobile,
12531
- children: "Reset to desktop size"
12532
- }
12533
- ) : null,
12534
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "h-px w-full bg-border", role: "separator" }),
12535
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
12536
- Button,
12537
- {
12538
- type: "button",
12539
- variant: "outline",
12540
- size: "sm",
12541
- className: "h-9 w-full min-w-0 cursor-pointer gap-1",
12542
- onClick: onUpdateEverywhere,
12543
- children: [
12544
- "Update logo everywhere",
12545
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react15.ArrowUpRight, { size: 16, "aria-hidden": true })
12546
- ]
12547
- }
12548
- ),
12549
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-sm leading-5 text-muted-foreground", children: "Matches the right version to your background." })
12550
- ] });
12551
- }
12552
-
12553
- // src/ui/socials-display-panel.tsx
12554
- var import_jsx_runtime29 = require("react/jsx-runtime");
12555
- function DisplaySwitch({
12556
- label,
12557
- checked,
12558
- disabled,
12559
- onChange
12560
- }) {
12561
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
12562
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11802
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
11803
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12563
11804
  "span",
12564
11805
  {
12565
11806
  className: cn(
@@ -12569,7 +11810,7 @@ function DisplaySwitch({
12569
11810
  children: label
12570
11811
  }
12571
11812
  ),
12572
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11813
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12573
11814
  "button",
12574
11815
  {
12575
11816
  type: "button",
@@ -12583,7 +11824,7 @@ function DisplaySwitch({
12583
11824
  checked ? "bg-primary" : "bg-primary-50",
12584
11825
  disabled ? "cursor-default opacity-50" : "cursor-pointer"
12585
11826
  ),
12586
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11827
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12587
11828
  "span",
12588
11829
  {
12589
11830
  className: cn(
@@ -12597,8 +11838,8 @@ function DisplaySwitch({
12597
11838
  ] });
12598
11839
  }
12599
11840
  function SocialsDisplayPanel({ display, onChange, className }) {
12600
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: cn("flex w-full flex-col gap-3", className), children: [
12601
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11841
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: cn("flex w-full flex-col gap-3", className), children: [
11842
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12602
11843
  DisplaySwitch,
12603
11844
  {
12604
11845
  label: "Text",
@@ -12607,7 +11848,7 @@ function SocialsDisplayPanel({ display, onChange, className }) {
12607
11848
  onChange: (text) => onChange({ ...display, text })
12608
11849
  }
12609
11850
  ),
12610
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11851
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12611
11852
  DisplaySwitch,
12612
11853
  {
12613
11854
  label: "Icon",
@@ -13167,8 +12408,8 @@ function useNavItemDrag({
13167
12408
  }
13168
12409
 
13169
12410
  // src/ui/footer-container-chrome.tsx
13170
- var import_lucide_react16 = require("lucide-react");
13171
- var import_jsx_runtime30 = require("react/jsx-runtime");
12411
+ var import_lucide_react15 = require("lucide-react");
12412
+ var import_jsx_runtime29 = require("react/jsx-runtime");
13172
12413
  function FooterContainerChrome({
13173
12414
  rect,
13174
12415
  onAdd,
@@ -13176,7 +12417,7 @@ function FooterContainerChrome({
13176
12417
  }) {
13177
12418
  const chromeGap = 6;
13178
12419
  const buttonMargin = 7;
13179
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
12420
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13180
12421
  "div",
13181
12422
  {
13182
12423
  "data-ohw-footer-container-chrome": "",
@@ -13188,8 +12429,8 @@ function FooterContainerChrome({
13188
12429
  width: rect.width + chromeGap * 2,
13189
12430
  height: rect.height + chromeGap * 2
13190
12431
  },
13191
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(Tooltip, { children: [
13192
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
12432
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(Tooltip, { children: [
12433
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13193
12434
  "button",
13194
12435
  {
13195
12436
  type: "button",
@@ -13208,10 +12449,10 @@ function FooterContainerChrome({
13208
12449
  if (addDisabled) return;
13209
12450
  onAdd();
13210
12451
  },
13211
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react16.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12452
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
13212
12453
  }
13213
12454
  ) }),
13214
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
12455
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
13215
12456
  ] })
13216
12457
  }
13217
12458
  ) });
@@ -13318,8 +12559,10 @@ function getLinkHref3(el) {
13318
12559
  }
13319
12560
  function collectEditableNodes(extraContent, root = document) {
13320
12561
  const isScoped = root !== document;
13321
- const editableEls = Array.from(root.querySelectorAll("[data-ohw-editable]"));
13322
- if (isScoped && root instanceof HTMLElement && root.matches("[data-ohw-editable]")) {
12562
+ const editableEls = Array.from(
12563
+ root.querySelectorAll('[data-ohw-editable]:not([data-ohw-editable="form"])')
12564
+ );
12565
+ if (isScoped && root instanceof HTMLElement && root.matches('[data-ohw-editable]:not([data-ohw-editable="form"])')) {
13323
12566
  editableEls.unshift(root);
13324
12567
  }
13325
12568
  const nodes = editableEls.map((el) => {
@@ -13394,18 +12637,6 @@ function collectEditableNodes(extraContent, root = document) {
13394
12637
  }
13395
12638
  if (extraContent && !isScoped) {
13396
12639
  applyNavFooterDeleteOverrides(byKey, extraContent);
13397
- for (const key of LOGO_IMAGE_KEYS) {
13398
- if (!(key in extraContent)) continue;
13399
- byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
13400
- }
13401
- for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
13402
- if (!(key in extraContent)) continue;
13403
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
13404
- }
13405
- for (const key of LOGO_SIZE_KEYS) {
13406
- if (!(key in extraContent)) continue;
13407
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
13408
- }
13409
12640
  }
13410
12641
  return Array.from(byKey.values());
13411
12642
  }
@@ -13671,14 +12902,14 @@ function deleteSelectedNavFooterItem(deps) {
13671
12902
  }
13672
12903
 
13673
12904
  // src/ui/navbar-container-chrome.tsx
13674
- var import_lucide_react17 = require("lucide-react");
13675
- var import_jsx_runtime31 = require("react/jsx-runtime");
12905
+ var import_lucide_react16 = require("lucide-react");
12906
+ var import_jsx_runtime30 = require("react/jsx-runtime");
13676
12907
  function NavbarContainerChrome({
13677
12908
  rect,
13678
12909
  onAdd
13679
12910
  }) {
13680
12911
  const chromeGap = 6;
13681
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
12912
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13682
12913
  "div",
13683
12914
  {
13684
12915
  "data-ohw-navbar-container-chrome": "",
@@ -13690,7 +12921,7 @@ function NavbarContainerChrome({
13690
12921
  width: rect.width + chromeGap * 2,
13691
12922
  height: rect.height + chromeGap * 2
13692
12923
  },
13693
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
12924
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13694
12925
  "button",
13695
12926
  {
13696
12927
  type: "button",
@@ -13707,7 +12938,7 @@ function NavbarContainerChrome({
13707
12938
  e.stopPropagation();
13708
12939
  onAdd();
13709
12940
  },
13710
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react17.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12941
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react16.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
13711
12942
  }
13712
12943
  )
13713
12944
  }
@@ -13716,7 +12947,7 @@ function NavbarContainerChrome({
13716
12947
 
13717
12948
  // src/ui/drop-indicator.tsx
13718
12949
  var React10 = __toESM(require("react"), 1);
13719
- var import_jsx_runtime32 = require("react/jsx-runtime");
12950
+ var import_jsx_runtime31 = require("react/jsx-runtime");
13720
12951
  var dropIndicatorVariants = cva(
13721
12952
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
13722
12953
  {
@@ -13740,7 +12971,7 @@ var dropIndicatorVariants = cva(
13740
12971
  );
13741
12972
  var DropIndicator = React10.forwardRef(
13742
12973
  ({ className, direction, state, ...props }, ref) => {
13743
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
12974
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
13744
12975
  "div",
13745
12976
  {
13746
12977
  ref,
@@ -13757,7 +12988,7 @@ var DropIndicator = React10.forwardRef(
13757
12988
  DropIndicator.displayName = "DropIndicator";
13758
12989
 
13759
12990
  // src/ui/badge.tsx
13760
- var import_jsx_runtime33 = require("react/jsx-runtime");
12991
+ var import_jsx_runtime32 = require("react/jsx-runtime");
13761
12992
  var badgeVariants = cva(
13762
12993
  "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",
13763
12994
  {
@@ -13775,12 +13006,12 @@ var badgeVariants = cva(
13775
13006
  }
13776
13007
  );
13777
13008
  function Badge({ className, variant, ...props }) {
13778
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
13009
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
13779
13010
  }
13780
13011
 
13781
13012
  // src/OhhwellsBridge.tsx
13782
- var import_lucide_react18 = require("lucide-react");
13783
- var import_jsx_runtime34 = require("react/jsx-runtime");
13013
+ var import_lucide_react17 = require("lucide-react");
13014
+ var import_jsx_runtime33 = require("react/jsx-runtime");
13784
13015
  var PRIMARY3 = "#0885FE";
13785
13016
  var IMAGE_FADE_MS = 300;
13786
13017
  function runOpacityFade(el, onDone) {
@@ -13874,10 +13105,21 @@ function parseSchedulingInsertAfter(insertAfter) {
13874
13105
  insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
13875
13106
  };
13876
13107
  }
13877
- function resolveEntryAnchor(entry) {
13878
- if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
13879
- const parsed = parseSchedulingInsertAfter(entry.insertAfter);
13880
- return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
13108
+ function resolveSchedulingInsert(insertAfter, explicitInsertBefore) {
13109
+ const parsed = parseSchedulingInsertAfter(insertAfter);
13110
+ const insertBefore = explicitInsertBefore ?? parsed.insertBefore;
13111
+ const effectiveInsertAfter = insertBefore && parsed.insertBefore === null ? `${insertAfter}${INSERT_BEFORE_MARKER}${insertBefore}` : insertAfter;
13112
+ return { effectiveInsertAfter, insertBefore };
13113
+ }
13114
+ function getSchedulingMountPoint(insertAfter) {
13115
+ const { anchor } = parseSchedulingInsertAfter(insertAfter);
13116
+ let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
13117
+ if (!anchorEl && anchor === "scheduling") {
13118
+ const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
13119
+ anchorEl = widgets.at(-1) ?? null;
13120
+ }
13121
+ if (!anchorEl) return null;
13122
+ return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
13881
13123
  }
13882
13124
  function schedulingMountDepth(insertAfter) {
13883
13125
  if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
@@ -13894,7 +13136,8 @@ function getPageSchedulingEntries(raw) {
13894
13136
  }
13895
13137
  }
13896
13138
  function isSchedulingWidgetMissing(entry) {
13897
- return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
13139
+ const { effectiveInsertAfter } = resolveSchedulingInsert(entry.insertAfter);
13140
+ return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
13898
13141
  }
13899
13142
  function hasMissingSchedulingWidgets(entries) {
13900
13143
  return entries.some(isSchedulingWidgetMissing);
@@ -13924,17 +13167,16 @@ function initSectionsFromContent(content, removeExisting = false) {
13924
13167
  } catch {
13925
13168
  }
13926
13169
  }
13927
- function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
13928
- const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
13929
- const sectionId = schedulingSectionId(widgetId);
13170
+ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId, explicitInsertBefore) {
13171
+ const { effectiveInsertAfter, insertBefore } = resolveSchedulingInsert(insertAfter, explicitInsertBefore);
13172
+ const sectionId = schedulingSectionId(effectiveInsertAfter);
13930
13173
  if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
13931
- const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
13932
- if (!anchorEl) return false;
13933
- const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
13174
+ const mountPoint = getSchedulingMountPoint(effectiveInsertAfter);
13175
+ if (!mountPoint) return false;
13934
13176
  const container = document.createElement("div");
13935
13177
  container.dataset.ohwSectionContainer = "scheduling";
13936
- if (beforeId) {
13937
- const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
13178
+ if (insertBefore) {
13179
+ const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
13938
13180
  const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
13939
13181
  if (!beforePoint) return false;
13940
13182
  beforePoint.insertAdjacentElement("beforebegin", container);
@@ -13945,25 +13187,19 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
13945
13187
  }
13946
13188
  tail.insertAdjacentElement("afterend", container);
13947
13189
  }
13948
- try {
13949
- const root = (0, import_client2.createRoot)(container);
13950
- (0, import_react_dom3.flushSync)(() => {
13951
- root.render(
13952
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
13953
- SchedulingWidget,
13954
- {
13955
- notifyOnConnect,
13956
- initialScheduleId: scheduleId,
13957
- insertAfter: widgetId
13958
- }
13959
- )
13960
- );
13961
- });
13962
- } catch (err) {
13963
- console.error("[ow:scheduling] render threw", err);
13964
- container.remove();
13965
- return false;
13966
- }
13190
+ const root = (0, import_client2.createRoot)(container);
13191
+ (0, import_react_dom3.flushSync)(() => {
13192
+ root.render(
13193
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13194
+ SchedulingWidget,
13195
+ {
13196
+ notifyOnConnect,
13197
+ initialScheduleId: scheduleId,
13198
+ insertAfter: effectiveInsertAfter
13199
+ }
13200
+ )
13201
+ );
13202
+ });
13967
13203
  const tracker = getSectionsTracker();
13968
13204
  let sections = [];
13969
13205
  try {
@@ -13971,12 +13207,10 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
13971
13207
  } catch {
13972
13208
  }
13973
13209
  const inEditor = typeof window !== "undefined" && window.self !== window.top;
13974
- if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
13210
+ if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === effectiveInsertAfter)) {
13975
13211
  sections.push({
13976
13212
  type: "scheduling",
13977
- insertAfter: widgetId,
13978
- anchorId,
13979
- beforeId: beforeId ?? null,
13213
+ insertAfter: effectiveInsertAfter,
13980
13214
  pagePath: window.location.pathname,
13981
13215
  ...scheduleId ? { scheduleId } : {}
13982
13216
  });
@@ -13990,8 +13224,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
13990
13224
  for (let i = pending.length - 1; i >= 0; i--) {
13991
13225
  const entry = pending[i];
13992
13226
  const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
13993
- const { anchorId, beforeId } = resolveEntryAnchor(entry);
13994
- if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
13227
+ if (mountSchedulingWidget(entry.insertAfter, shouldNotify, entry.scheduleId)) {
13995
13228
  pending.splice(i, 1);
13996
13229
  }
13997
13230
  }
@@ -14064,6 +13297,10 @@ function isIconEditable(el) {
14064
13297
  return el.dataset.ohwEditable === "icon";
14065
13298
  }
14066
13299
  var MEDIA_SELECTOR = '[data-ohw-editable="image"], [data-ohw-editable="bg-image"], [data-ohw-editable="video"]';
13300
+ var EDITOR_CHROME_SELECTOR = '[data-ohw-toolbar], [data-ohw-form-toolbar], [data-ohw-field-toolbar], [data-ohw-item-toolbar], [data-ohw-more-menu], [data-ohw-state-toggle], [data-ohw-max-badge], [data-slot="dropdown-menu-content"], [data-slot="dropdown-menu-item"]';
13301
+ function isOverEditorChrome(x, y) {
13302
+ return document.elementsFromPoint(x, y).some((el) => el instanceof HTMLElement && el.matches(EDITOR_CHROME_SELECTOR));
13303
+ }
14067
13304
  var NON_MEDIA_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]):not([data-ohw-editable="icon"]):not([data-ohw-editable="form"])';
14068
13305
  function getVideoEl2(el) {
14069
13306
  return el instanceof HTMLVideoElement ? el : el.querySelector("video");
@@ -14135,13 +13372,6 @@ function isInsideLinkEditor(target) {
14135
13372
  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"]')
14136
13373
  );
14137
13374
  }
14138
- function isInsideFloatingPanel(target) {
14139
- return Boolean(target.closest("[data-ohw-floating-panel]"));
14140
- }
14141
- function isPointOverFloatingPanel(clientX, clientY) {
14142
- const el = document.elementFromPoint(clientX, clientY);
14143
- return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
14144
- }
14145
13375
  function getHrefKeyFromElement(el) {
14146
13376
  if (!el) return null;
14147
13377
  const anchor = el.closest("[data-ohw-href-key]");
@@ -14189,7 +13419,8 @@ function isNavItemPointerTarget(el) {
14189
13419
  function getNavigationItemAnchor(el) {
14190
13420
  const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
14191
13421
  if (!anchor) return null;
14192
- if (!anchor.querySelector('[data-ohw-editable="text"]') && !getSocialItem(anchor)) return null;
13422
+ if (!anchor.matches('[data-ohw-editable="text"], [data-ohw-editable="plain"]') && !anchor.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') && !getSocialItem(anchor))
13423
+ return null;
14193
13424
  if (!isNavItemPointerTarget(anchor)) return null;
14194
13425
  return anchor;
14195
13426
  }
@@ -14379,7 +13610,7 @@ function getNavigationSelectionParent(el) {
14379
13610
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
14380
13611
  return getFooterLinksContainer();
14381
13612
  }
14382
- 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)) {
13613
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
14383
13614
  return getNavigationRoot(el);
14384
13615
  }
14385
13616
  return null;
@@ -14625,7 +13856,7 @@ function EditGlowChrome({
14625
13856
  hideHandle = false
14626
13857
  }) {
14627
13858
  const GAP = SELECTION_CHROME_GAP2;
14628
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
13859
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
14629
13860
  "div",
14630
13861
  {
14631
13862
  ref: elRef,
@@ -14640,7 +13871,7 @@ function EditGlowChrome({
14640
13871
  zIndex: 2147483646
14641
13872
  },
14642
13873
  children: [
14643
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
13874
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14644
13875
  "div",
14645
13876
  {
14646
13877
  style: {
@@ -14653,7 +13884,7 @@ function EditGlowChrome({
14653
13884
  }
14654
13885
  }
14655
13886
  ),
14656
- reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
13887
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14657
13888
  "div",
14658
13889
  {
14659
13890
  "data-ohw-drag-handle-container": "",
@@ -14665,7 +13896,7 @@ function EditGlowChrome({
14665
13896
  transform: "translate(calc(-100% - 7px), -50%)",
14666
13897
  pointerEvents: dragDisabled ? "none" : "auto"
14667
13898
  },
14668
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
13899
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14669
13900
  DragHandle,
14670
13901
  {
14671
13902
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -14875,7 +14106,7 @@ function FloatingToolbar({
14875
14106
  return () => ro.disconnect();
14876
14107
  }, [showEditLink, activeCommands]);
14877
14108
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
14878
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14109
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14879
14110
  "div",
14880
14111
  {
14881
14112
  ref: setRefs,
@@ -14887,12 +14118,12 @@ function FloatingToolbar({
14887
14118
  zIndex: 2147483647,
14888
14119
  pointerEvents: "auto"
14889
14120
  },
14890
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(CustomToolbar, { children: [
14891
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react16.default.Fragment, { children: [
14892
- gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(CustomToolbarDivider, {}),
14121
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(CustomToolbar, { children: [
14122
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react16.default.Fragment, { children: [
14123
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CustomToolbarDivider, {}),
14893
14124
  btns.map((btn) => {
14894
14125
  const isActive = activeCommands.has(btn.cmd);
14895
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14126
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14896
14127
  CustomToolbarButton,
14897
14128
  {
14898
14129
  title: btn.title,
@@ -14901,7 +14132,7 @@ function FloatingToolbar({
14901
14132
  e.preventDefault();
14902
14133
  onCommand(btn.cmd);
14903
14134
  },
14904
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14135
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14905
14136
  "svg",
14906
14137
  {
14907
14138
  width: "16",
@@ -14922,7 +14153,7 @@ function FloatingToolbar({
14922
14153
  );
14923
14154
  })
14924
14155
  ] }, gi)),
14925
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14156
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14926
14157
  CustomToolbarButton,
14927
14158
  {
14928
14159
  type: "button",
@@ -14936,7 +14167,7 @@ function FloatingToolbar({
14936
14167
  e.preventDefault();
14937
14168
  e.stopPropagation();
14938
14169
  },
14939
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Link, { className: "size-4 shrink-0", "aria-hidden": true })
14170
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Link, { className: "size-4 shrink-0", "aria-hidden": true })
14940
14171
  }
14941
14172
  ) : null
14942
14173
  ] })
@@ -14953,7 +14184,7 @@ function StateToggle({
14953
14184
  states,
14954
14185
  onStateChange
14955
14186
  }) {
14956
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
14187
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
14957
14188
  ToggleGroup,
14958
14189
  {
14959
14190
  "data-ohw-state-toggle": "",
@@ -14967,12 +14198,11 @@ function StateToggle({
14967
14198
  left: rect.right - 8,
14968
14199
  transform: "translateX(-100%)"
14969
14200
  },
14970
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
14201
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
14971
14202
  }
14972
14203
  );
14973
14204
  }
14974
14205
  var contentCache = /* @__PURE__ */ new Map();
14975
- var fetchedContentPaths = /* @__PURE__ */ new Set();
14976
14206
  function resolveSubdomain(subdomainFromQuery) {
14977
14207
  if (subdomainFromQuery) return subdomainFromQuery;
14978
14208
  if (typeof window !== "undefined") {
@@ -15067,14 +14297,8 @@ function OhhwellsBridge() {
15067
14297
  });
15068
14298
  const selectFrameRef = (0, import_react16.useRef)(() => {
15069
14299
  });
15070
- const selectLogoRef = (0, import_react16.useRef)(() => {
15071
- });
15072
- const openLogoSizePanelRef = (0, import_react16.useRef)(() => {
15073
- });
15074
14300
  const deselectRef = (0, import_react16.useRef)(() => {
15075
14301
  });
15076
- const closeFloatingPanelOnlyRef = (0, import_react16.useRef)(() => {
15077
- });
15078
14302
  const reselectNavigationItemRef = (0, import_react16.useRef)(() => {
15079
14303
  });
15080
14304
  const commitNavigationTextEditRef = (0, import_react16.useRef)(() => {
@@ -15102,9 +14326,14 @@ function OhhwellsBridge() {
15102
14326
  const [fieldTypePickerOpen, setFieldTypePickerOpen] = (0, import_react16.useState)(false);
15103
14327
  const clearFormPick = (0, import_react16.useCallback)(() => {
15104
14328
  const form = formPickElRef.current;
14329
+ const editing = fieldPickElRef.current;
14330
+ if (commitPlaceholderEdit(editing) && editing) {
14331
+ const owner = editing.closest('[data-ohw-editable="form"]');
14332
+ if (owner) persistFieldsRef.current(owner);
14333
+ }
15105
14334
  if (form) {
15106
14335
  const key = formKeyOf(form);
15107
- if (key) setFormViewState(form, key, "default", DEFAULT_SUCCESS_TEXT);
14336
+ if (key) setFormViewState(form, key, "default", successInitialFor(form, key, editContentRef.current));
15108
14337
  }
15109
14338
  setFormViewStateUi("default");
15110
14339
  setFormPickCount(null);
@@ -15158,8 +14387,8 @@ function OhhwellsBridge() {
15158
14387
  if (!wrapper || !form) return;
15159
14388
  commitPlaceholderEdit(wrapper);
15160
14389
  run(form, wrapper);
15161
- beginPlaceholderEdit(wrapper);
15162
14390
  persistFields(form);
14391
+ beginPlaceholderEdit(wrapper);
15163
14392
  setFormPickRect(form.getBoundingClientRect());
15164
14393
  },
15165
14394
  [persistFields]
@@ -15210,17 +14439,37 @@ function OhhwellsBridge() {
15210
14439
  [persistFields, selectField]
15211
14440
  );
15212
14441
  const fieldDragRef = (0, import_react16.useRef)(null);
14442
+ const buildFieldDropSlots = (0, import_react16.useCallback)((form, draggedKey) => {
14443
+ const others = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== draggedKey);
14444
+ const slots = others.map((el) => {
14445
+ const rect = el.getBoundingClientRect();
14446
+ return { top: rect.top, left: rect.left, width: rect.width };
14447
+ });
14448
+ const last = others[others.length - 1];
14449
+ if (last) {
14450
+ const rect = last.getBoundingClientRect();
14451
+ slots.push({ top: rect.bottom, left: rect.left, width: rect.width });
14452
+ }
14453
+ return slots;
14454
+ }, []);
15213
14455
  const handleFieldDragStart = (0, import_react16.useCallback)(() => {
15214
14456
  const wrapper = fieldPickElRef.current;
15215
14457
  const form = formPickElRef.current;
15216
14458
  if (!wrapper || !form) return;
15217
- fieldDragRef.current = { key: fieldKeyOf(wrapper), form };
15218
- }, []);
14459
+ const key = fieldKeyOf(wrapper);
14460
+ fieldDragRef.current = { key, form };
14461
+ setFieldDragging(true);
14462
+ setFieldDropSlots(buildFieldDropSlots(form, key));
14463
+ }, [buildFieldDropSlots]);
15219
14464
  const handleFieldDragEnd = (0, import_react16.useCallback)(() => {
15220
14465
  fieldDragRef.current = null;
15221
14466
  setFieldDropIndex(null);
14467
+ setFieldDropSlots([]);
14468
+ setFieldDragging(false);
15222
14469
  }, []);
15223
14470
  const [fieldDropIndex, setFieldDropIndex] = (0, import_react16.useState)(null);
14471
+ const [fieldDropSlots, setFieldDropSlots] = (0, import_react16.useState)([]);
14472
+ const [fieldDragging, setFieldDragging] = (0, import_react16.useState)(false);
15224
14473
  const clearFormPickRef = (0, import_react16.useRef)(clearFormPick);
15225
14474
  clearFormPickRef.current = clearFormPick;
15226
14475
  (0, import_react16.useEffect)(() => {
@@ -15286,6 +14535,11 @@ function OhhwellsBridge() {
15286
14535
  const [isItemDragging, setIsItemDragging] = (0, import_react16.useState)(false);
15287
14536
  const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react16.useState)(false);
15288
14537
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
14538
+ const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
14539
+ const floatingPanelOpenRef = (0, import_react16.useRef)(false);
14540
+ floatingPanelOpenRef.current = floatingPanel !== null;
14541
+ const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
14542
+ const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
15289
14543
  const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react16.useState)(null);
15290
14544
  const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react16.useState)(null);
15291
14545
  const footerDragRef = (0, import_react16.useRef)(null);
@@ -15300,16 +14554,7 @@ function OhhwellsBridge() {
15300
14554
  const addNavAfterAnchorRef = (0, import_react16.useRef)(null);
15301
14555
  const editContentRef = (0, import_react16.useRef)({});
15302
14556
  const aiSectionsRef = (0, import_react16.useRef)("");
15303
- const brandKitRef = (0, import_react16.useRef)("");
15304
- const stylesRef = (0, import_react16.useRef)("");
15305
14557
  const pendingDeleteUndoRef = (0, import_react16.useRef)(null);
15306
- const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
15307
- const floatingPanelOpenRef = (0, import_react16.useRef)(false);
15308
- const setFloatingPanelRef = (0, import_react16.useRef)(setFloatingPanel);
15309
- const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
15310
- const [logoSizeDraft, setLogoSizeDraft] = (0, import_react16.useState)(null);
15311
- const [editorViewport, setEditorViewport] = (0, import_react16.useState)("desktop");
15312
- const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
15313
14558
  const [sitePages, setSitePages] = (0, import_react16.useState)([]);
15314
14559
  const [sectionsByPath, setSectionsByPath] = (0, import_react16.useState)({});
15315
14560
  const sectionsPrefetchGenRef = (0, import_react16.useRef)(0);
@@ -15318,18 +14563,7 @@ function OhhwellsBridge() {
15318
14563
  const linkPopoverOpenRef = (0, import_react16.useRef)(false);
15319
14564
  const linkPopoverGraceUntilRef = (0, import_react16.useRef)(0);
15320
14565
  setLinkPopoverRef.current = setLinkPopover;
15321
- setFloatingPanelRef.current = setFloatingPanel;
15322
14566
  linkPopoverSessionRef.current = linkPopover;
15323
- floatingPanelOpenRef.current = Boolean(floatingPanel);
15324
- (0, import_react16.useEffect)(() => {
15325
- const syncViewport = () => {
15326
- const next = window.innerWidth <= 480 ? "mobile" : "desktop";
15327
- setEditorViewport((prev) => prev === next ? prev : next);
15328
- };
15329
- syncViewport();
15330
- window.addEventListener("resize", syncViewport);
15331
- return () => window.removeEventListener("resize", syncViewport);
15332
- }, []);
15333
14567
  const {
15334
14568
  navDragRef,
15335
14569
  navDropSlots,
@@ -15498,7 +14732,9 @@ function OhhwellsBridge() {
15498
14732
  const deactivate = (0, import_react16.useCallback)(() => {
15499
14733
  const el = activeElRef.current;
15500
14734
  if (!el) return;
15501
- const key = el.dataset.ohwKey;
14735
+ const isFormBlock = el.dataset.ohwEditable === "form";
14736
+ const isFormControl = el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement;
14737
+ const key = isFormBlock || isFormControl ? void 0 : el.dataset.ohwKey;
15502
14738
  if (key) {
15503
14739
  const timer = autoSaveTimers.current.get(key);
15504
14740
  if (timer !== void 0) {
@@ -15515,6 +14751,12 @@ function OhhwellsBridge() {
15515
14751
  }
15516
14752
  el.removeAttribute("contenteditable");
15517
14753
  el.removeAttribute("data-ohw-editing");
14754
+ const labelField = getFieldWrapper(el);
14755
+ if (labelField) {
14756
+ syncRequiredMark(labelField);
14757
+ const owner = labelField.closest('[data-ohw-editable="form"]');
14758
+ if (owner) persistFieldsRef.current(owner);
14759
+ }
15518
14760
  activeElRef.current = null;
15519
14761
  setNavGroupForceOpen(null, false);
15520
14762
  setReorderHrefKey(null);
@@ -15554,8 +14796,6 @@ function OhhwellsBridge() {
15554
14796
  setHoveredNavContainerRect(null);
15555
14797
  hoveredItemElRef.current = null;
15556
14798
  setHoveredItemRect(null);
15557
- setFloatingPanel(null);
15558
- setLogoSizeDraft(null);
15559
14799
  if (!activeElRef.current) {
15560
14800
  setNavGroupForceOpen(null, false);
15561
14801
  setToolbarRect(null);
@@ -15670,6 +14910,12 @@ function OhhwellsBridge() {
15670
14910
  }
15671
14911
  el.removeAttribute("contenteditable");
15672
14912
  el.removeAttribute("data-ohw-editing");
14913
+ const labelField = getFieldWrapper(el);
14914
+ if (labelField) {
14915
+ syncRequiredMark(labelField);
14916
+ const owner = labelField.closest('[data-ohw-editable="form"]');
14917
+ if (owner) persistFieldsRef.current(owner);
14918
+ }
15673
14919
  activeElRef.current = null;
15674
14920
  setMaxBadge(null);
15675
14921
  setActiveCommands(/* @__PURE__ */ new Set());
@@ -16261,8 +15507,6 @@ function OhhwellsBridge() {
16261
15507
  setToolbarRect(anchor.getBoundingClientRect());
16262
15508
  setToolbarShowEditLink(false);
16263
15509
  setActiveCommands(/* @__PURE__ */ new Set());
16264
- setFloatingPanel(null);
16265
- setLogoSizeDraft(null);
16266
15510
  }, [deactivate, markSelected]);
16267
15511
  const selectFrame = (0, import_react16.useCallback)((el) => {
16268
15512
  if (!isNavigationContainer(el)) return;
@@ -16312,51 +15556,7 @@ function OhhwellsBridge() {
16312
15556
  setToolbarRect(el.getBoundingClientRect());
16313
15557
  setToolbarShowEditLink(false);
16314
15558
  setActiveCommands(/* @__PURE__ */ new Set());
16315
- setFloatingPanel(null);
16316
- setLogoSizeDraft(null);
16317
15559
  }, [deactivate, markSelected, postToParent2]);
16318
- const selectLogo = (0, import_react16.useCallback)(
16319
- (logoEl) => {
16320
- if (activeElRef.current) deactivate();
16321
- selectedElRef.current = logoEl;
16322
- selectedHrefKeyRef.current = null;
16323
- selectedFooterColAttrRef.current = null;
16324
- markSelected(logoEl);
16325
- setSelectedIsCta(false);
16326
- setSelectedIsSocial(false);
16327
- setSelectedIsSocialsRow(false);
16328
- clearHrefKeyHover(logoEl);
16329
- hoveredNavContainerRef.current = null;
16330
- setHoveredNavContainerRect(null);
16331
- setHoveredItemRect(null);
16332
- hoveredItemElRef.current = null;
16333
- siblingHintElRef.current = null;
16334
- setSiblingHintRect(null);
16335
- setSiblingHintRects([]);
16336
- setIsItemDragging(false);
16337
- setReorderHrefKey(null);
16338
- setReorderDragDisabled(false);
16339
- setIsFooterFrameSelection(false);
16340
- setToolbarVariant("logo");
16341
- setToolbarRect(getLogoInteractionRect(logoEl));
16342
- setToolbarShowEditLink(false);
16343
- setActiveCommands(/* @__PURE__ */ new Set());
16344
- },
16345
- [deactivate, markSelected]
16346
- );
16347
- const openLogoSizePanel = (0, import_react16.useCallback)((logoEl) => {
16348
- const placement = getLogoPlacement(logoEl);
16349
- const draft = readLogoSizeState(editContentRef.current, placement);
16350
- setLogoSizeDraft(draft);
16351
- setParentScrollSnap(parentScrollRef.current);
16352
- setFloatingPanel({
16353
- key: `logo-size:${placement}`,
16354
- title: "Logo",
16355
- context: placement === "navbar" ? "Navbar" : "Footer",
16356
- kind: "logo-size",
16357
- placement
16358
- });
16359
- }, []);
16360
15560
  const openSocialsDisplayPanel = (0, import_react16.useCallback)((row) => {
16361
15561
  setParentScrollSnap(parentScrollRef.current);
16362
15562
  setFloatingPanel({
@@ -16392,54 +15592,13 @@ function OhhwellsBridge() {
16392
15592
  );
16393
15593
  const closeFloatingPanelOnly = (0, import_react16.useCallback)(() => {
16394
15594
  setFloatingPanel(null);
16395
- setLogoSizeDraft(null);
16396
15595
  }, []);
15596
+ const closeFloatingPanelOnlyRef = (0, import_react16.useRef)(closeFloatingPanelOnly);
16397
15597
  closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
16398
15598
  const closeFloatingPanelAndDeselect = (0, import_react16.useCallback)(() => {
16399
15599
  setFloatingPanel(null);
16400
- setLogoSizeDraft(null);
16401
15600
  deselectRef.current();
16402
15601
  }, []);
16403
- const persistLogoSizeDraft = (0, import_react16.useCallback)(
16404
- (placement, draft) => {
16405
- const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
16406
- const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
16407
- const nodes = [
16408
- { key: desktopKey, text: String(draft.desktopPx) }
16409
- ];
16410
- if (draft.mobileFollowing) {
16411
- nodes.push({ key: mobileKey, text: "" });
16412
- } else {
16413
- nodes.push({ key: mobileKey, text: String(draft.mobilePx) });
16414
- }
16415
- editContentRef.current = {
16416
- ...editContentRef.current,
16417
- [desktopKey]: String(draft.desktopPx),
16418
- [mobileKey]: draft.mobileFollowing ? "" : String(draft.mobilePx)
16419
- };
16420
- applyLogoSizeToPlacement(
16421
- placement,
16422
- draft.desktopPx,
16423
- draft.mobileFollowing ? draft.desktopPx : draft.mobilePx,
16424
- draft.mobileFollowing
16425
- );
16426
- postToParent2({ type: "ow:change", nodes });
16427
- requestAnimationFrame(() => {
16428
- const selected = selectedElRef.current;
16429
- if (!selected || toolbarVariantRef.current !== "logo") return;
16430
- const rect = getLogoInteractionRect(selected);
16431
- setToolbarRect(rect);
16432
- if (glowElRef.current) {
16433
- const GAP = SELECTION_CHROME_GAP2;
16434
- glowElRef.current.style.top = `${rect.top - GAP}px`;
16435
- glowElRef.current.style.left = `${rect.left - GAP}px`;
16436
- glowElRef.current.style.width = `${rect.width + GAP * 2}px`;
16437
- glowElRef.current.style.height = `${rect.height + GAP * 2}px`;
16438
- }
16439
- });
16440
- },
16441
- [postToParent2]
16442
- );
16443
15602
  const activate = (0, import_react16.useCallback)((el, options) => {
16444
15603
  if (activeElRef.current === el) return;
16445
15604
  if (isIconEditable(el)) return;
@@ -16520,10 +15679,7 @@ function OhhwellsBridge() {
16520
15679
  deactivateRef.current = deactivate;
16521
15680
  selectRef.current = select;
16522
15681
  selectFrameRef.current = selectFrame;
16523
- selectLogoRef.current = selectLogo;
16524
- openLogoSizePanelRef.current = openLogoSizePanel;
16525
15682
  deselectRef.current = deselect;
16526
- closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
16527
15683
  const lastSiteWideScopeRef = (0, import_react16.useRef)(null);
16528
15684
  (0, import_react16.useEffect)(() => {
16529
15685
  if (!isEditMode) {
@@ -16562,23 +15718,9 @@ function OhhwellsBridge() {
16562
15718
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
16563
15719
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
16564
15720
  }
16565
- if (typeof content[BRAND_KIT_KEY] === "string") {
16566
- brandKitRef.current = content[BRAND_KIT_KEY];
16567
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
16568
- }
16569
- if (typeof content[STYLE_STORE_KEY] === "string") {
16570
- stylesRef.current = content[STYLE_STORE_KEY];
16571
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
16572
- }
16573
- applyBrandChrome(content);
16574
15721
  for (const [key, val] of Object.entries(content)) {
16575
15722
  if (key === "__ohw_sections") continue;
16576
15723
  if (key === AI_SECTIONS_KEY) continue;
16577
- if (key === LOGO_PLACEHOLDER_KEY) continue;
16578
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
16579
- if (key === BRAND_KIT_KEY) continue;
16580
- if (key === STYLE_STORE_KEY) continue;
16581
- if (BRAND_CHROME_KEYS.has(key)) continue;
16582
15724
  if (applyVideoSettingNode(key, val)) continue;
16583
15725
  if (applyCarouselNode(key, val)) continue;
16584
15726
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -16607,14 +15749,13 @@ function OhhwellsBridge() {
16607
15749
  applyLinkHref(el, val);
16608
15750
  } else if (el.dataset.ohwEditable === "icon") {
16609
15751
  applyIconMarkup(el, val);
15752
+ } else if (el.dataset.ohwEditable === "form") {
16610
15753
  } else if (el.innerHTML !== val) {
16611
15754
  el.innerHTML = val;
16612
15755
  }
16613
15756
  });
16614
15757
  applyLinkByKey(key, val);
16615
15758
  }
16616
- applyLogoFromContent(content);
16617
- applyLogoSizes(content);
16618
15759
  reconcileNavbarItemsFromContent(content);
16619
15760
  reconcileFooterOrderFromContent(content);
16620
15761
  reconcileSocialsFromContent(content);
@@ -16635,9 +15776,7 @@ function OhhwellsBridge() {
16635
15776
  let cancelled = false;
16636
15777
  setFetchState("loading");
16637
15778
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
16638
- const initialPath = pathname;
16639
- fetchedContentPaths.add(`${subdomain}::${initialPath}`);
16640
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
15779
+ fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
16641
15780
  if (cancelled) return;
16642
15781
  const content = data?.content ?? {};
16643
15782
  contentCache.set(subdomain, content);
@@ -16666,6 +15805,7 @@ function OhhwellsBridge() {
16666
15805
  e.preventDefault();
16667
15806
  e.stopPropagation();
16668
15807
  if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
15808
+ setFieldDropSlots(buildFieldDropSlots(session.form, session.key));
16669
15809
  setFieldDropIndex(resolveIndex(session.form, e.clientY));
16670
15810
  };
16671
15811
  const onDrop = (e) => {
@@ -16680,6 +15820,8 @@ function OhhwellsBridge() {
16680
15820
  setFormPickRect(session.form.getBoundingClientRect());
16681
15821
  fieldDragRef.current = null;
16682
15822
  setFieldDropIndex(null);
15823
+ setFieldDropSlots([]);
15824
+ setFieldDragging(false);
16683
15825
  };
16684
15826
  window.addEventListener("dragover", onDragOver, true);
16685
15827
  window.addEventListener("drop", onDrop, true);
@@ -16687,7 +15829,7 @@ function OhhwellsBridge() {
16687
15829
  window.removeEventListener("dragover", onDragOver, true);
16688
15830
  window.removeEventListener("drop", onDrop, true);
16689
15831
  };
16690
- }, [isEditMode, persistFields, selectField]);
15832
+ }, [buildFieldDropSlots, isEditMode, persistFields, selectField]);
16691
15833
  (0, import_react16.useEffect)(() => {
16692
15834
  if (!isEditMode) return;
16693
15835
  const mark = () => document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
@@ -16709,8 +15851,9 @@ function OhhwellsBridge() {
16709
15851
  const wrapper = getFieldWrapper(input);
16710
15852
  if (!wrapper || wrapper !== fieldPickElRef.current) return;
16711
15853
  if (saveTimer) clearTimeout(saveTimer);
15854
+ const owner = wrapper.closest('[data-ohw-editable="form"]');
16712
15855
  saveTimer = setTimeout(() => {
16713
- const form = formPickElRef.current;
15856
+ const form = owner ?? formPickElRef.current;
16714
15857
  if (!form) return;
16715
15858
  const previous = input.getAttribute("placeholder");
16716
15859
  input.setAttribute("placeholder", input.value);
@@ -16753,21 +15896,8 @@ function OhhwellsBridge() {
16753
15896
  initSectionInstancesFromContent(content, window.location.pathname);
16754
15897
  observer?.disconnect();
16755
15898
  try {
16756
- applyBrandChrome(content);
16757
- if (typeof content[BRAND_KIT_KEY] === "string") {
16758
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
16759
- }
16760
- if (typeof content[STYLE_STORE_KEY] === "string") {
16761
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
16762
- }
16763
15899
  for (const [key, val] of Object.entries(content)) {
16764
15900
  if (key === "__ohw_sections") continue;
16765
- if (key === LOGO_PLACEHOLDER_KEY) continue;
16766
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
16767
- if (key === BRAND_KIT_KEY) continue;
16768
- if (key === STYLE_STORE_KEY) continue;
16769
- if (key === STYLE_STORE_KEY) continue;
16770
- if (BRAND_CHROME_KEYS.has(key)) continue;
16771
15901
  if (applyVideoSettingNode(key, val)) continue;
16772
15902
  if (applyCarouselNode(key, val)) continue;
16773
15903
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -16782,17 +15912,23 @@ function OhhwellsBridge() {
16782
15912
  if (video && video.src !== val) applyVideoSrc(video, val);
16783
15913
  } else if (el.dataset.ohwEditable === "link") {
16784
15914
  applyLinkHref(el, val);
15915
+ } else if (el.dataset.ohwEditable === "form") {
16785
15916
  } else if (el.innerHTML !== val) {
16786
15917
  el.innerHTML = val;
16787
15918
  }
16788
15919
  });
16789
15920
  applyLinkByKey(key, val);
16790
15921
  }
16791
- applyLogoFromContent(content);
16792
15922
  reconcileNavbarItemsFromContent(content);
16793
15923
  reconcileFooterOrderFromContent(content);
16794
15924
  reconcileSocialsFromContent(content);
16795
15925
  applySocialsDisplayFromContent(content);
15926
+ document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
15927
+ if (!form.querySelector("[data-ohw-form-success]")) {
15928
+ reconcileFieldsFromContent(form, content);
15929
+ }
15930
+ listFieldWrappers(form).forEach(syncRequiredMark);
15931
+ });
16796
15932
  } finally {
16797
15933
  observer?.observe(document.body, { childList: true, subtree: true });
16798
15934
  }
@@ -16803,17 +15939,6 @@ function OhhwellsBridge() {
16803
15939
  debounceTimer = setTimeout(applyFromCache, 150);
16804
15940
  };
16805
15941
  applyFromCache();
16806
- const pathCacheKey = `${subdomain}::${pathname}`;
16807
- if (!fetchedContentPaths.has(pathCacheKey)) {
16808
- fetchedContentPaths.add(pathCacheKey);
16809
- const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
16810
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
16811
- if (!data?.content) return;
16812
- contentCache.set(subdomain, data.content);
16813
- applyFromCache();
16814
- }).catch(() => {
16815
- });
16816
- }
16817
15942
  observer = new MutationObserver(scheduleApply);
16818
15943
  observer.observe(document.body, { childList: true, subtree: true });
16819
15944
  return () => {
@@ -16907,31 +16032,26 @@ function OhhwellsBridge() {
16907
16032
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
16908
16033
  (0, import_react16.useEffect)(() => {
16909
16034
  if (!isEditMode) return;
16910
- let lastPosted = 0;
16911
16035
  const measure = () => {
16912
16036
  const h = document.body.scrollHeight;
16913
- if (h > 50 && Math.abs(h - lastPosted) > 1) {
16914
- lastPosted = h;
16915
- postToParent2({ type: "ow:height", height: h });
16916
- }
16917
- };
16918
- let raf = null;
16919
- const schedule = () => {
16920
- if (raf != null) return;
16921
- raf = requestAnimationFrame(() => {
16922
- raf = null;
16923
- measure();
16924
- });
16037
+ if (h > 50) postToParent2({ type: "ow:height", height: h });
16925
16038
  };
16926
16039
  const t1 = setTimeout(measure, 50);
16927
16040
  const t2 = setTimeout(measure, 500);
16928
- const ro = new ResizeObserver(schedule);
16929
- ro.observe(document.body);
16041
+ let lastWidth = window.innerWidth;
16042
+ let resizeTimer = null;
16043
+ const handleResize = () => {
16044
+ if (window.innerWidth === lastWidth) return;
16045
+ lastWidth = window.innerWidth;
16046
+ if (resizeTimer) clearTimeout(resizeTimer);
16047
+ resizeTimer = setTimeout(measure, 150);
16048
+ };
16049
+ window.addEventListener("resize", handleResize);
16930
16050
  return () => {
16931
16051
  clearTimeout(t1);
16932
16052
  clearTimeout(t2);
16933
- if (raf != null) cancelAnimationFrame(raf);
16934
- ro.disconnect();
16053
+ if (resizeTimer) clearTimeout(resizeTimer);
16054
+ window.removeEventListener("resize", handleResize);
16935
16055
  };
16936
16056
  }, [pathname, isEditMode, postToParent2]);
16937
16057
  (0, import_react16.useEffect)(() => {
@@ -17112,12 +16232,10 @@ function OhhwellsBridge() {
17112
16232
  return;
17113
16233
  }
17114
16234
  const target = e.target;
17115
- if (target.closest("[data-ohw-ai-review]")) return;
17116
16235
  if (target.closest("[data-ohw-toolbar]")) return;
17117
16236
  if (target.closest("[data-ohw-state-toggle]")) return;
17118
16237
  if (target.closest("[data-ohw-max-badge]")) return;
17119
16238
  if (isInsideLinkEditor(target)) return;
17120
- if (isInsideFloatingPanel(target)) return;
17121
16239
  if (target.closest("[data-ohw-form-toolbar]")) return;
17122
16240
  if (target.closest(
17123
16241
  '[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
@@ -17228,15 +16346,9 @@ function OhhwellsBridge() {
17228
16346
  if (logoEl) {
17229
16347
  e.preventDefault();
17230
16348
  e.stopPropagation();
17231
- if (!logoHasUploadedImage(logoEl)) {
17232
- deselectRef.current();
17233
- deactivateRef.current();
17234
- const identity = readLogoIdentityFromDom();
17235
- postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
17236
- return;
17237
- }
17238
- selectLogoRef.current(logoEl);
17239
- openLogoSizePanelRef.current(logoEl);
16349
+ deselectRef.current();
16350
+ deactivateRef.current();
16351
+ postToParentRef.current({ type: "ow:open-logo-settings" });
17240
16352
  return;
17241
16353
  }
17242
16354
  const editable = target.closest("[data-ohw-editable]");
@@ -17391,12 +16503,10 @@ function OhhwellsBridge() {
17391
16503
  };
17392
16504
  const handleDblClick = (e) => {
17393
16505
  const target = e.target;
17394
- if (target.closest("[data-ohw-ai-review]")) return;
17395
16506
  if (target.closest("[data-ohw-toolbar]")) return;
17396
16507
  if (target.closest("[data-ohw-state-toggle]")) return;
17397
16508
  if (target.closest("[data-ohw-max-badge]")) return;
17398
16509
  if (isInsideLinkEditor(target)) return;
17399
- if (isInsideFloatingPanel(target)) return;
17400
16510
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
17401
16511
  return;
17402
16512
  }
@@ -17424,16 +16534,26 @@ function OhhwellsBridge() {
17424
16534
  setHoveredNavContainerRect(null);
17425
16535
  return;
17426
16536
  }
17427
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
16537
+ if (target.closest(EDITOR_CHROME_SELECTOR) || isOverEditorChrome(e.clientX, e.clientY) || isInsideLinkEditor(target)) {
16538
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
17428
16539
  hoveredItemElRef.current = null;
17429
16540
  setHoveredItemRect(null);
17430
16541
  hoveredNavContainerRef.current = null;
17431
16542
  setHoveredNavContainerRect(null);
16543
+ formHoverElRef.current = null;
16544
+ setFormHoverRect(null);
17432
16545
  siblingHintElRef.current = null;
17433
16546
  setSiblingHintRect(null);
17434
16547
  setSiblingHintRects([]);
17435
16548
  return;
17436
16549
  }
16550
+ if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || target.closest("[data-ohw-floating-panel]")) {
16551
+ hoveredItemElRef.current = null;
16552
+ setHoveredItemRect(null);
16553
+ hoveredNavContainerRef.current = null;
16554
+ setHoveredNavContainerRect(null);
16555
+ return;
16556
+ }
17437
16557
  {
17438
16558
  const selected2 = selectedElRef.current;
17439
16559
  const selectedIsFooterColumn = Boolean(selected2) && !isFooterLinksContainer(selected2) && (selected2.hasAttribute("data-ohw-footer-col") || selected2.hasAttribute("data-ohw-footer-column") || Boolean(selected2.closest("footer") && isInferredFooterGroup2(selected2)));
@@ -17476,7 +16596,7 @@ function OhhwellsBridge() {
17476
16596
  setHoveredNavContainerRect(null);
17477
16597
  if (selectedElRef.current === logoEl) return;
17478
16598
  hoveredItemElRef.current = logoEl;
17479
- setHoveredItemRect(getLogoInteractionRect(logoEl));
16599
+ setHoveredItemRect(logoEl.getBoundingClientRect());
17480
16600
  return;
17481
16601
  }
17482
16602
  const navAnchor = getNavigationItemAnchor(target);
@@ -17540,6 +16660,7 @@ function OhhwellsBridge() {
17540
16660
  hoveredNavContainerRef.current = null;
17541
16661
  setHoveredNavContainerRect(null);
17542
16662
  hoveredItemElRef.current = editable;
16663
+ setHoveredItemRect(editable.getBoundingClientRect());
17543
16664
  }
17544
16665
  }
17545
16666
  }
@@ -17747,7 +16868,7 @@ function OhhwellsBridge() {
17747
16868
  setHoveredNavContainerRect(null);
17748
16869
  if (selectedElRef.current !== logo) {
17749
16870
  hoveredItemElRef.current = logo;
17750
- setHoveredItemRect(getLogoInteractionRect(logo));
16871
+ setHoveredItemRect(logo.getBoundingClientRect());
17751
16872
  }
17752
16873
  return;
17753
16874
  }
@@ -17836,7 +16957,7 @@ function OhhwellsBridge() {
17836
16957
  }
17837
16958
  };
17838
16959
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
17839
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
16960
+ if (linkPopoverOpenRef.current) {
17840
16961
  if (hoveredImageRef.current) {
17841
16962
  hoveredImageRef.current = null;
17842
16963
  hoveredImageHasTextOverlapRef.current = false;
@@ -18090,7 +17211,7 @@ function OhhwellsBridge() {
18090
17211
  }
18091
17212
  };
18092
17213
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
18093
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
17214
+ if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
18094
17215
  if (activeStateElRef.current) {
18095
17216
  activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
18096
17217
  activeStateElRef.current = null;
@@ -18165,17 +17286,15 @@ function OhhwellsBridge() {
18165
17286
  };
18166
17287
  const handleMouseMove = (e) => {
18167
17288
  const { clientX, clientY } = e;
18168
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
17289
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
17290
+ if (isOverEditorChrome(clientX, clientY)) {
17291
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
17292
+ formHoverElRef.current = null;
17293
+ setFormHoverRect(null);
18169
17294
  hoveredItemElRef.current = null;
18170
17295
  setHoveredItemRect(null);
18171
17296
  hoveredNavContainerRef.current = null;
18172
17297
  setHoveredNavContainerRect(null);
18173
- siblingHintElRef.current = null;
18174
- setSiblingHintRect(null);
18175
- setSiblingHintRects([]);
18176
- dismissImageHover();
18177
- clearImageHover();
18178
- setSectionGap(null);
18179
17298
  return;
18180
17299
  }
18181
17300
  probeSectionGapAt(clientX, clientY);
@@ -18186,11 +17305,7 @@ function OhhwellsBridge() {
18186
17305
  if (e.data?.type !== "ow:pointer-sync") return;
18187
17306
  const { clientX, clientY } = e.data;
18188
17307
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
18189
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
18190
- dismissImageHover();
18191
- clearImageHover();
18192
- return;
18193
- }
17308
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
18194
17309
  probeSectionGapAt(clientX, clientY);
18195
17310
  probeImageAt(clientX, clientY);
18196
17311
  probeHoverCardsAt(clientX, clientY);
@@ -18440,15 +17555,6 @@ function OhhwellsBridge() {
18440
17555
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
18441
17556
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
18442
17557
  }
18443
- if (typeof content[BRAND_KIT_KEY] === "string") {
18444
- brandKitRef.current = content[BRAND_KIT_KEY];
18445
- applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
18446
- }
18447
- if (typeof content[STYLE_STORE_KEY] === "string") {
18448
- stylesRef.current = content[STYLE_STORE_KEY];
18449
- applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
18450
- }
18451
- applyBrandChrome(content);
18452
17558
  let sectionsJson = null;
18453
17559
  for (const [key, val] of Object.entries(content)) {
18454
17560
  if (key === "__ohw_sections") {
@@ -18456,11 +17562,6 @@ function OhhwellsBridge() {
18456
17562
  continue;
18457
17563
  }
18458
17564
  if (key === AI_SECTIONS_KEY) continue;
18459
- if (key === LOGO_PLACEHOLDER_KEY) continue;
18460
- if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
18461
- if (key === BRAND_KIT_KEY) continue;
18462
- if (key === STYLE_STORE_KEY) continue;
18463
- if (BRAND_CHROME_KEYS.has(key)) continue;
18464
17565
  if (applyVideoSettingNode(key, val)) continue;
18465
17566
  if (applyCarouselNode(key, val)) continue;
18466
17567
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -18480,8 +17581,6 @@ function OhhwellsBridge() {
18480
17581
  });
18481
17582
  applyLinkByKey(key, val);
18482
17583
  }
18483
- applyLogoFromContent(content);
18484
- applyLogoSizes(content);
18485
17584
  if (sectionsJson) {
18486
17585
  initSectionsFromContent({ __ohw_sections: sectionsJson }, true);
18487
17586
  sectionsLoadedRef.current = true;
@@ -18497,58 +17596,6 @@ function OhhwellsBridge() {
18497
17596
  if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
18498
17597
  postToParentRef.current({ type: "ow:hydrate-done" });
18499
17598
  };
18500
- const handleUpdateLogoIdentity = (e) => {
18501
- if (e.data?.type !== "ow:update-logo-identity") return;
18502
- const rawText = typeof e.data.text === "string" ? e.data.text : "";
18503
- const alt = typeof e.data.alt === "string" ? e.data.alt : rawText;
18504
- const href = typeof e.data.href === "string" ? e.data.href : void 0;
18505
- const imageProvided = "image" in e.data;
18506
- const imageUrl = imageProvided && typeof e.data.image === "string" && e.data.image.trim() ? e.data.image.trim() : imageProvided ? null : void 0;
18507
- let isPlaceholder = e.data.isPlaceholder !== false;
18508
- if (imageUrl) isPlaceholder = false;
18509
- else if (imageProvided && imageUrl === null) {
18510
- isPlaceholder = e.data.isPlaceholder === true || !rawText.trim() || resolveLogoDisplayText(rawText) === PLACEHOLDER_BUSINESS_NAME;
18511
- }
18512
- const display = applyLogoIdentity(rawText, isPlaceholder);
18513
- const displayAlt = resolveLogoDisplayText(alt || display);
18514
- if (imageUrl !== void 0) {
18515
- applyLogoImage(imageUrl, displayAlt);
18516
- } else {
18517
- for (const key of LOGO_IMAGE_KEYS) {
18518
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
18519
- const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
18520
- if (img) img.alt = displayAlt;
18521
- });
18522
- }
18523
- }
18524
- if (href !== void 0) {
18525
- applyLogoHref(href);
18526
- applyLinkByKey("nav-logo-href", href);
18527
- applyLinkByKey("footer-logo-href", href);
18528
- applyLinkByKey("logo-href", href);
18529
- }
18530
- const nodes = [
18531
- ...LOGO_TEXT_KEYS.map((key) => ({ key, text: display })),
18532
- { key: LOGO_PLACEHOLDER_KEY, text: isPlaceholder ? "true" : "false" },
18533
- { key: LOGO_ALT_KEY, text: displayAlt }
18534
- ];
18535
- if (imageUrl !== void 0) {
18536
- if (imageUrl) {
18537
- for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: imageUrl });
18538
- } else {
18539
- for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: "" });
18540
- }
18541
- }
18542
- if (href !== void 0) {
18543
- for (const key of LOGO_HREF_KEYS) nodes.push({ key, text: href.trim() || "/" });
18544
- }
18545
- editContentRef.current = {
18546
- ...editContentRef.current,
18547
- ...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
18548
- };
18549
- applyLogoSizes(editContentRef.current);
18550
- postToParentRef.current({ type: "ow:change", nodes });
18551
- };
18552
17599
  window.addEventListener("message", handleHydrate);
18553
17600
  const postAiSectionsChanged = () => {
18554
17601
  postToParentRef.current({
@@ -18562,10 +17609,7 @@ function OhhwellsBridge() {
18562
17609
  const payload = e.data.payload;
18563
17610
  if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
18564
17611
  const previous = aiSectionsRef.current;
18565
- const nextState = applyTreeToState(parseAiSectionsState(previous), {
18566
- ...payload,
18567
- path: payload.path ?? window.location.pathname
18568
- });
17612
+ const nextState = applyTreeToState(parseAiSectionsState(previous), payload);
18569
17613
  const nextValue = serializeAiSectionsState(nextState);
18570
17614
  aiSectionsRef.current = nextValue;
18571
17615
  applyAiSectionsToDom(nextState);
@@ -18602,42 +17646,12 @@ function OhhwellsBridge() {
18602
17646
  const value = typeof e.data.value === "string" ? e.data.value : "";
18603
17647
  aiSectionsRef.current = value;
18604
17648
  applyAiSectionsToDom(parseAiSectionsState(value));
18605
- applyStylesToDom(parseStyleStore(stylesRef.current));
18606
17649
  const restoredHeight = document.documentElement.scrollHeight;
18607
17650
  if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
18608
17651
  postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
18609
17652
  postAiSectionsChanged();
18610
17653
  };
18611
17654
  window.addEventListener("message", handleAiSetSections);
18612
- const handleAiSetBrand = (e) => {
18613
- if (e.data?.type !== "ow:ai-set-brand") return;
18614
- const value = typeof e.data.value === "string" ? e.data.value : "";
18615
- const previous = brandKitRef.current;
18616
- brandKitRef.current = value;
18617
- applyBrandToDom(parseBrandKit(value));
18618
- if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
18619
- applyStylesToDom(parseStyleStore(stylesRef.current));
18620
- postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
18621
- postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
18622
- };
18623
- window.addEventListener("message", handleAiSetBrand);
18624
- const handleAiSetStyles = (e) => {
18625
- if (e.data?.type !== "ow:ai-set-styles") return;
18626
- const value = typeof e.data.value === "string" ? e.data.value : "";
18627
- const previous = stylesRef.current;
18628
- stylesRef.current = value;
18629
- applyStylesToDom(parseStyleStore(value));
18630
- postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
18631
- postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
18632
- };
18633
- window.addEventListener("message", handleAiSetStyles);
18634
- const handleGetBrand = (e) => {
18635
- if (e.data?.type !== "ow:get-brand") return;
18636
- const template = deriveTemplateBrand();
18637
- const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
18638
- postToParentRef.current({ type: "ow:brand-value", value });
18639
- };
18640
- window.addEventListener("message", handleGetBrand);
18641
17655
  const handleDeactivate = (e) => {
18642
17656
  if (e.data?.type !== "ow:deactivate") return;
18643
17657
  if (Date.now() < linkPopoverGraceUntilRef.current) return;
@@ -18646,12 +17660,6 @@ function OhhwellsBridge() {
18646
17660
  closeLinkPopoverRef.current();
18647
17661
  return;
18648
17662
  }
18649
- if (floatingPanelOpenRef.current) {
18650
- setFloatingPanelRef.current(null);
18651
- deselectRef.current();
18652
- deactivateRef.current();
18653
- return;
18654
- }
18655
17663
  deselectRef.current();
18656
17664
  deactivateRef.current();
18657
17665
  };
@@ -18705,10 +17713,6 @@ function OhhwellsBridge() {
18705
17713
  return;
18706
17714
  }
18707
17715
  if (selectedElRef.current) {
18708
- if (toolbarVariantRef.current === "logo") {
18709
- deselectRef.current();
18710
- return;
18711
- }
18712
17716
  if (toolbarVariantRef.current === "select-frame") {
18713
17717
  const parent2 = getNavigationSelectionParent(selectedElRef.current);
18714
17718
  if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
@@ -18760,10 +17764,6 @@ function OhhwellsBridge() {
18760
17764
  return;
18761
17765
  }
18762
17766
  if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
18763
- if (toolbarVariantRef.current === "logo") {
18764
- deselectRef.current();
18765
- return;
18766
- }
18767
17767
  if (toolbarVariantRef.current === "select-frame") {
18768
17768
  const parent2 = getNavigationSelectionParent(selectedElRef.current);
18769
17769
  if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
@@ -18841,8 +17841,7 @@ function OhhwellsBridge() {
18841
17841
  const handleScroll = () => {
18842
17842
  const focusEl = activeElRef.current ?? selectedElRef.current;
18843
17843
  if (focusEl) {
18844
- const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
18845
- const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
17844
+ const r2 = activeElRef.current ? getEditMeasureEl(activeElRef.current).getBoundingClientRect() : focusEl.getBoundingClientRect();
18846
17845
  applyToolbarPos(r2);
18847
17846
  setToolbarRect(r2);
18848
17847
  setMaxBadge((prev) => prev && activeElRef.current ? { ...prev, rect: r2 } : prev);
@@ -18852,9 +17851,7 @@ function OhhwellsBridge() {
18852
17851
  setToggleState((prev) => prev ? { ...prev, rect } : null);
18853
17852
  }
18854
17853
  if (hoveredItemElRef.current) {
18855
- const hoverEl = hoveredItemElRef.current;
18856
- const logo = getLogoElement(hoverEl);
18857
- setHoveredItemRect(logo ? getLogoInteractionRect(logo) : hoverEl.getBoundingClientRect());
17854
+ setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
18858
17855
  }
18859
17856
  if (hoveredNavContainerRef.current) {
18860
17857
  setHoveredNavContainerRect(hoveredNavContainerRef.current.getBoundingClientRect());
@@ -18898,12 +17895,13 @@ function OhhwellsBridge() {
18898
17895
  if (aiSectionsRef.current) {
18899
17896
  nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
18900
17897
  }
18901
- if (stylesRef.current) {
18902
- nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
18903
- }
18904
- if (brandKitRef.current) {
18905
- nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
18906
- }
17898
+ document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
17899
+ const formKey = formKeyOf(form);
17900
+ if (!formKey) return;
17901
+ const specs = readFieldsFromDom(form);
17902
+ const text = specs.length ? JSON.stringify(specs) : editContentRef.current[fieldsKey(formKey)];
17903
+ if (text) nodes.push({ key: fieldsKey(formKey), type: "text", text });
17904
+ });
18907
17905
  postToParentRef.current({ type: "ow:save-result", nodes });
18908
17906
  };
18909
17907
  const handleInsertSection = (e) => {
@@ -18914,12 +17912,8 @@ function OhhwellsBridge() {
18914
17912
  if (inserted) {
18915
17913
  const tracker = getSectionsTracker();
18916
17914
  postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
18917
- const reportHeight = () => {
18918
- const h = document.body.scrollHeight;
18919
- if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
18920
- };
18921
- reportHeight();
18922
- setTimeout(reportHeight, 500);
17915
+ const h = document.documentElement.scrollHeight;
17916
+ if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
18923
17917
  }
18924
17918
  };
18925
17919
  const handleSwitchSchedule = (e) => {
@@ -19112,17 +18106,13 @@ function OhhwellsBridge() {
19112
18106
  if (e.data?.type !== "ow:parent-scroll") return;
19113
18107
  const { iframeOffsetTop, headerH, canvasH } = e.data;
19114
18108
  parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
19115
- if (floatingPanelOpenRef.current) {
19116
- setParentScrollSnap({ iframeOffsetTop, headerH, canvasH });
19117
- }
19118
18109
  if (visibleViewportRef.current) {
19119
18110
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
19120
18111
  }
19121
18112
  const focusEl = activeElRef.current ?? selectedElRef.current;
19122
18113
  if (focusEl) {
19123
- const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
19124
- const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
19125
- applyToolbarPos(r2);
18114
+ const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
18115
+ applyToolbarPos(measureEl.getBoundingClientRect());
19126
18116
  }
19127
18117
  };
19128
18118
  const handleClickAt = (e) => {
@@ -19155,15 +18145,9 @@ function OhhwellsBridge() {
19155
18145
  return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
19156
18146
  });
19157
18147
  if (logoAtPoint) {
19158
- if (!logoHasUploadedImage(logoAtPoint)) {
19159
- deselectRef.current();
19160
- deactivateRef.current();
19161
- const identity = readLogoIdentityFromDom();
19162
- postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
19163
- return;
19164
- }
19165
- selectLogoRef.current(logoAtPoint);
19166
- openLogoSizePanelRef.current(logoAtPoint);
18148
+ deselectRef.current();
18149
+ deactivateRef.current();
18150
+ postToParentRef.current({ type: "ow:open-logo-settings" });
19167
18151
  return;
19168
18152
  }
19169
18153
  const textEditable = Array.from(
@@ -19237,14 +18221,6 @@ function OhhwellsBridge() {
19237
18221
  window.addEventListener("message", handleParentScroll);
19238
18222
  window.addEventListener("message", handlePointerSync);
19239
18223
  window.addEventListener("message", handleClickAt);
19240
- window.addEventListener("message", handleUpdateLogoIdentity);
19241
- const handleViewMode = (e) => {
19242
- if (e.data?.type !== "ow:view-mode") return;
19243
- const mode = e.data.mode === "Mobile" || e.data.mode === "mobile" ? "mobile" : "desktop";
19244
- setEditorViewport(mode);
19245
- applyLogoSizes(editContentRef.current);
19246
- };
19247
- window.addEventListener("message", handleViewMode);
19248
18224
  const handleViewportResize = () => {
19249
18225
  if (visibleViewportRef.current) {
19250
18226
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
@@ -19300,15 +18276,10 @@ function OhhwellsBridge() {
19300
18276
  window.removeEventListener("resize", handleViewportResize);
19301
18277
  window.removeEventListener("message", handlePointerSync);
19302
18278
  window.removeEventListener("message", handleClickAt);
19303
- window.removeEventListener("message", handleUpdateLogoIdentity);
19304
- window.removeEventListener("message", handleViewMode);
19305
18279
  window.removeEventListener("message", handleHydrate);
19306
18280
  window.removeEventListener("message", handleAiApplyTree);
19307
18281
  window.removeEventListener("message", handleAiDeleteSection);
19308
18282
  window.removeEventListener("message", handleAiSetSections);
19309
- window.removeEventListener("message", handleAiSetBrand);
19310
- window.removeEventListener("message", handleAiSetStyles);
19311
- window.removeEventListener("message", handleGetBrand);
19312
18283
  window.removeEventListener("message", handleDeactivate);
19313
18284
  window.removeEventListener("message", handleToastAction);
19314
18285
  window.removeEventListener("message", handleFormCount);
@@ -19515,7 +18486,7 @@ function OhhwellsBridge() {
19515
18486
  postToParent2({
19516
18487
  type: "ow:ready",
19517
18488
  version: "1",
19518
- bridgeVersion: "0.1.64",
18489
+ bridgeVersion: "0.1.63",
19519
18490
  path: pathname,
19520
18491
  nodes: collectEditableNodes(editContentRef.current),
19521
18492
  sections
@@ -19910,10 +18881,10 @@ function OhhwellsBridge() {
19910
18881
  [postToParent2]
19911
18882
  );
19912
18883
  return bridgeRoot ? (0, import_react_dom4.createPortal)(
19913
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
19914
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
19915
- isEditMode && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
19916
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
18884
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
18885
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
18886
+ isEditMode && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
18887
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19917
18888
  MediaOverlay,
19918
18889
  {
19919
18890
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -19924,7 +18895,7 @@ function OhhwellsBridge() {
19924
18895
  },
19925
18896
  `uploading-${key}`
19926
18897
  )),
19927
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
18898
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19928
18899
  MediaOverlay,
19929
18900
  {
19930
18901
  hover: mediaHover,
@@ -19933,11 +18904,11 @@ function OhhwellsBridge() {
19933
18904
  onVideoSettingsChange: handleVideoSettingsChange
19934
18905
  }
19935
18906
  ),
19936
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
19937
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
19938
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
19939
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
19940
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
18907
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
18908
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
18909
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
18910
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
18911
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19941
18912
  "div",
19942
18913
  {
19943
18914
  className: "pointer-events-none fixed z-2147483646",
@@ -19947,7 +18918,7 @@ function OhhwellsBridge() {
19947
18918
  width: slot.width,
19948
18919
  height: slot.height
19949
18920
  },
19950
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
18921
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19951
18922
  DropIndicator,
19952
18923
  {
19953
18924
  direction: slot.direction,
@@ -19958,7 +18929,7 @@ function OhhwellsBridge() {
19958
18929
  },
19959
18930
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
19960
18931
  )),
19961
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
18932
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19962
18933
  "div",
19963
18934
  {
19964
18935
  className: "pointer-events-none fixed z-2147483646",
@@ -19968,7 +18939,7 @@ function OhhwellsBridge() {
19968
18939
  width: slot.width,
19969
18940
  height: slot.height
19970
18941
  },
19971
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
18942
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19972
18943
  DropIndicator,
19973
18944
  {
19974
18945
  direction: slot.direction,
@@ -19979,10 +18950,10 @@ function OhhwellsBridge() {
19979
18950
  },
19980
18951
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
19981
18952
  )),
19982
- hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
19983
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
19984
- hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
19985
- formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
18953
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
18954
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
18955
+ hoveredTextRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
18956
+ formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19986
18957
  ItemInteractionLayer,
19987
18958
  {
19988
18959
  rect: formPickRect,
@@ -19990,13 +18961,13 @@ function OhhwellsBridge() {
19990
18961
  itemDragSurface: false,
19991
18962
  toolbarAlign: "left",
19992
18963
  chromeGap: 24,
19993
- toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
18964
+ toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
19994
18965
  "div",
19995
18966
  {
19996
18967
  "data-ohw-form-toolbar": "",
19997
18968
  className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
19998
18969
  children: [
19999
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
18970
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20000
18971
  "button",
20001
18972
  {
20002
18973
  type: "button",
@@ -20004,11 +18975,11 @@ function OhhwellsBridge() {
20004
18975
  className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
20005
18976
  onClick: () => setFieldTypePickerOpen((open) => !open),
20006
18977
  "data-ohw-add-field": "",
20007
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Plus, { size: 15, "aria-hidden": true })
18978
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Plus, { size: 15, "aria-hidden": true })
20008
18979
  }
20009
18980
  ),
20010
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20011
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
18981
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
18982
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
20012
18983
  "button",
20013
18984
  {
20014
18985
  type: "button",
@@ -20023,11 +18994,11 @@ function OhhwellsBridge() {
20023
18994
  });
20024
18995
  },
20025
18996
  children: [
20026
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Settings, { size: 14, "aria-hidden": true }),
18997
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Settings, { size: 14, "aria-hidden": true }),
20027
18998
  "Form settings",
20028
18999
  formPickCount ? (
20029
19000
  // Counter pill, per the design — not a text suffix.
20030
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19001
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20031
19002
  "span",
20032
19003
  {
20033
19004
  "data-ohw-form-count": "",
@@ -20039,30 +19010,8 @@ function OhhwellsBridge() {
20039
19010
  ]
20040
19011
  }
20041
19012
  ),
20042
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20043
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
20044
- "button",
20045
- {
20046
- type: "button",
20047
- 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",
20048
- onClick: () => {
20049
- const form = formPickElRef.current;
20050
- if (!form) return;
20051
- postToParent2({
20052
- type: "ow:form-submissions",
20053
- formKey: formKeyOf(form),
20054
- hasLongText: formHasLongText(form)
20055
- });
20056
- },
20057
- "data-ohw-view-submissions": "",
20058
- children: [
20059
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Table, { size: 14, "aria-hidden": true }),
20060
- "View submissions"
20061
- ]
20062
- }
20063
- ),
20064
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20065
- /* @__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)(
19013
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
19014
+ /* @__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)(
20066
19015
  "button",
20067
19016
  {
20068
19017
  type: "button",
@@ -20072,7 +19021,7 @@ function OhhwellsBridge() {
20072
19021
  const form = formPickElRef.current;
20073
19022
  const key = form ? formKeyOf(form) : null;
20074
19023
  if (!form || !key) return;
20075
- const initial = editContentRef.current[formSuccessKey(key)] ?? DEFAULT_SUCCESS_TEXT;
19024
+ const initial = successInitialFor(form, key, editContentRef.current);
20076
19025
  setFormViewState(form, key, state, initial);
20077
19026
  setFormViewStateUi(state);
20078
19027
  setFormPickRect(form.getBoundingClientRect());
@@ -20092,7 +19041,7 @@ function OhhwellsBridge() {
20092
19041
  )
20093
19042
  }
20094
19043
  ),
20095
- formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19044
+ formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20096
19045
  ItemInteractionLayer,
20097
19046
  {
20098
19047
  rect: formHoverRect,
@@ -20100,11 +19049,11 @@ function OhhwellsBridge() {
20100
19049
  chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
20101
19050
  }
20102
19051
  ),
20103
- fieldPickRect && fieldPickState && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19052
+ fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20104
19053
  ItemInteractionLayer,
20105
19054
  {
20106
19055
  rect: fieldPickRect,
20107
- state: "active-top",
19056
+ state: fieldDragging ? "dragging" : "active-top",
20108
19057
  itemDragSurface: false,
20109
19058
  toolbarAlign: "left",
20110
19059
  chromeGap: 10,
@@ -20112,7 +19061,7 @@ function OhhwellsBridge() {
20112
19061
  dragHandleLabel: "Reorder field",
20113
19062
  onDragHandleDragStart: handleFieldDragStart,
20114
19063
  onDragHandleDragEnd: handleFieldDragEnd,
20115
- toolbar: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19064
+ toolbar: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20116
19065
  FormFieldToolbar,
20117
19066
  {
20118
19067
  type: fieldPickState.type,
@@ -20125,33 +19074,32 @@ function OhhwellsBridge() {
20125
19074
  )
20126
19075
  }
20127
19076
  ),
20128
- fieldDropIndex !== null && formPickElRef.current ? (() => {
20129
- const wrappers = listFieldWrappers(formPickElRef.current).filter(
20130
- (el) => fieldKeyOf(el) !== fieldDragRef.current?.key
20131
- );
20132
- const anchor = wrappers[Math.min(fieldDropIndex, wrappers.length - 1)];
20133
- if (!anchor) return null;
20134
- const rect = anchor.getBoundingClientRect();
20135
- const atEnd = fieldDropIndex >= wrappers.length;
20136
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20137
- "div",
20138
- {
20139
- className: "pointer-events-none fixed z-[2147483644]",
20140
- style: { top: atEnd ? rect.bottom : rect.top, left: rect.left, width: rect.width },
20141
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(DropIndicator, { direction: "horizontal", state: "dragActive" })
20142
- }
20143
- );
20144
- })() : null,
20145
- fieldTypePickerOpen && formPickRect && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19077
+ fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19078
+ "div",
19079
+ {
19080
+ className: "pointer-events-none fixed z-[2147483644]",
19081
+ style: { top: slot.top, left: slot.left, width: slot.width },
19082
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19083
+ DropIndicator,
19084
+ {
19085
+ direction: "horizontal",
19086
+ state: fieldDropIndex === i ? "dragActive" : "dragIdle",
19087
+ className: "!w-full"
19088
+ }
19089
+ )
19090
+ },
19091
+ `field-drop-${i}`
19092
+ )) : null,
19093
+ fieldTypePickerOpen && formPickRect && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20146
19094
  "div",
20147
19095
  {
20148
19096
  className: "pointer-events-none fixed z-[2147483645]",
20149
19097
  style: { top: formPickRect.top + 16, left: formPickRect.left + 24 },
20150
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(FieldTypePicker, { onPick: handleAddField })
19098
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FieldTypePicker, { onPick: handleAddField })
20151
19099
  }
20152
19100
  ),
20153
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
20154
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19101
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
19102
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20155
19103
  FooterContainerChrome,
20156
19104
  {
20157
19105
  rect: toolbarRect,
@@ -20159,7 +19107,7 @@ function OhhwellsBridge() {
20159
19107
  addDisabled: !canAddFooterColumn()
20160
19108
  }
20161
19109
  ),
20162
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19110
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20163
19111
  ItemInteractionLayer,
20164
19112
  {
20165
19113
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -20171,10 +19119,10 @@ function OhhwellsBridge() {
20171
19119
  dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
20172
19120
  onDragHandleDragStart: handleItemDragStart,
20173
19121
  onDragHandleDragEnd: handleItemDragEnd,
20174
- onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
20175
- onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
20176
- itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
20177
- toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19122
+ onItemPointerDown: handleItemChromePointerDown,
19123
+ onItemClick: handleItemChromeClick,
19124
+ itemDragSurface: !isFooterFrameSelection,
19125
+ toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20178
19126
  ItemActionToolbar,
20179
19127
  {
20180
19128
  onEditLink: openLinkPopoverForSelected,
@@ -20210,8 +19158,8 @@ function OhhwellsBridge() {
20210
19158
  ) : void 0
20211
19159
  }
20212
19160
  ),
20213
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
20214
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19161
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
19162
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20215
19163
  EditGlowChrome,
20216
19164
  {
20217
19165
  rect: toolbarRect,
@@ -20221,7 +19169,7 @@ function OhhwellsBridge() {
20221
19169
  hideHandle: isItemDragging
20222
19170
  }
20223
19171
  ),
20224
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19172
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20225
19173
  FloatingToolbar,
20226
19174
  {
20227
19175
  rect: toolbarRect,
@@ -20234,7 +19182,7 @@ function OhhwellsBridge() {
20234
19182
  }
20235
19183
  )
20236
19184
  ] }),
20237
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
19185
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
20238
19186
  "div",
20239
19187
  {
20240
19188
  "data-ohw-max-badge": "",
@@ -20260,7 +19208,7 @@ function OhhwellsBridge() {
20260
19208
  ]
20261
19209
  }
20262
19210
  ),
20263
- toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19211
+ toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20264
19212
  StateToggle,
20265
19213
  {
20266
19214
  rect: toggleState.rect,
@@ -20269,15 +19217,15 @@ function OhhwellsBridge() {
20269
19217
  onStateChange: handleStateChange
20270
19218
  }
20271
19219
  ),
20272
- sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
19220
+ sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
20273
19221
  "div",
20274
19222
  {
20275
19223
  "data-ohw-section-insert-line": "",
20276
19224
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
20277
19225
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
20278
19226
  children: [
20279
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
20280
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19227
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
19228
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20281
19229
  Badge,
20282
19230
  {
20283
19231
  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",
@@ -20294,11 +19242,11 @@ function OhhwellsBridge() {
20294
19242
  children: "Add Section"
20295
19243
  }
20296
19244
  ),
20297
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
19245
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
20298
19246
  ]
20299
19247
  }
20300
19248
  ),
20301
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19249
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20302
19250
  LinkPopover,
20303
19251
  {
20304
19252
  panelRef: linkPopoverPanelRef,
@@ -20315,7 +19263,7 @@ function OhhwellsBridge() {
20315
19263
  },
20316
19264
  linkPopover.key
20317
19265
  ) : null,
20318
- floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19266
+ floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20319
19267
  FloatingPanel,
20320
19268
  {
20321
19269
  open: true,
@@ -20325,7 +19273,7 @@ function OhhwellsBridge() {
20325
19273
  onPositionChange: setFloatingPanelPos,
20326
19274
  parentScroll: parentScrollSnap ?? parentScrollRef.current,
20327
19275
  onClose: closeFloatingPanelOnly,
20328
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19276
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20329
19277
  SocialsDisplayPanel,
20330
19278
  {
20331
19279
  display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
@@ -20336,115 +19284,11 @@ function OhhwellsBridge() {
20336
19284
  }
20337
19285
  )
20338
19286
  }
20339
- ) : null,
20340
- floatingPanel && floatingPanel.kind === "logo-size" && logoSizeDraft ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20341
- FloatingPanel,
20342
- {
20343
- open: true,
20344
- title: floatingPanel.title,
20345
- context: floatingPanel.context,
20346
- position: floatingPanelPos,
20347
- onPositionChange: setFloatingPanelPos,
20348
- parentScroll: parentScrollSnap ?? parentScrollRef.current,
20349
- onClose: closeFloatingPanelAndDeselect,
20350
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20351
- LogoSizePanel,
20352
- {
20353
- viewport: editorViewport,
20354
- sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
20355
- mobileFollowing: logoSizeDraft.mobileFollowing,
20356
- onSizeChange: (px) => {
20357
- const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
20358
- ...logoSizeDraft,
20359
- desktopPx: px,
20360
- mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
20361
- };
20362
- setLogoSizeDraft(next);
20363
- persistLogoSizeDraft(floatingPanel.placement, next);
20364
- },
20365
- onCustomizeMobile: () => {
20366
- const next = {
20367
- ...logoSizeDraft,
20368
- mobileFollowing: false,
20369
- mobilePx: logoSizeDraft.desktopPx
20370
- };
20371
- setLogoSizeDraft(next);
20372
- persistLogoSizeDraft(floatingPanel.placement, next);
20373
- },
20374
- onResetMobile: () => {
20375
- const next = {
20376
- ...logoSizeDraft,
20377
- mobileFollowing: true,
20378
- mobilePx: logoSizeDraft.desktopPx
20379
- };
20380
- setLogoSizeDraft(next);
20381
- persistLogoSizeDraft(floatingPanel.placement, next);
20382
- },
20383
- onUpdateEverywhere: () => {
20384
- const identity = readLogoIdentityFromDom();
20385
- postToParent2({ type: "ow:open-logo-settings", ...identity });
20386
- }
20387
- }
20388
- )
20389
- }
20390
19287
  ) : null
20391
19288
  ] }),
20392
19289
  bridgeRoot
20393
19290
  ) : null;
20394
19291
  }
20395
-
20396
- // src/ui/EmptySection.tsx
20397
- var import_link = __toESM(require("next/link"), 1);
20398
- var import_jsx_runtime35 = require("react/jsx-runtime");
20399
- function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
20400
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
20401
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
20402
- "p",
20403
- {
20404
- style: {
20405
- fontFamily: "var(--brand-font-body)",
20406
- fontSize: "0.75rem",
20407
- fontWeight: 500,
20408
- letterSpacing: "0.15em",
20409
- textTransform: "uppercase",
20410
- color: "var(--brand-accent)",
20411
- marginBottom: "1.5rem"
20412
- },
20413
- 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" }) })
20414
- }
20415
- ),
20416
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
20417
- "h1",
20418
- {
20419
- style: {
20420
- fontFamily: "var(--brand-font-heading)",
20421
- fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
20422
- lineHeight: 1.1,
20423
- letterSpacing: "-0.025em",
20424
- color: "var(--brand-text)",
20425
- marginBottom: "1rem"
20426
- },
20427
- ...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
20428
- children: title
20429
- }
20430
- ),
20431
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
20432
- "p",
20433
- {
20434
- style: {
20435
- fontFamily: "var(--brand-font-body)",
20436
- fontSize: "1rem",
20437
- lineHeight: 1.7,
20438
- fontWeight: 300,
20439
- color: "var(--brand-text-muted)",
20440
- maxWidth: "340px"
20441
- },
20442
- ...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
20443
- children: "This page doesn't have any content yet."
20444
- }
20445
- )
20446
- ] });
20447
- }
20448
19292
  // Annotate the CommonJS export names for ESM import in node:
20449
19293
  0 && (module.exports = {
20450
19294
  AI_DEFAULT_BRAND,
@@ -20462,7 +19306,6 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
20462
19306
  DropdownMenuItem,
20463
19307
  DropdownMenuSeparator,
20464
19308
  DropdownMenuTrigger,
20465
- EmptySection,
20466
19309
  ItemActionToolbar,
20467
19310
  ItemInteractionLayer,
20468
19311
  LinkEditorPanel,