@ohhwells/bridge 0.1.68 → 0.1.69-next.208
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 +2228 -836
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -7
- package/dist/index.d.ts +21 -7
- package/dist/index.js +2220 -829
- package/dist/index.js.map +1 -1
- package/dist/pages.cjs +141 -0
- package/dist/pages.cjs.map +1 -0
- package/dist/pages.d.cts +45 -0
- package/dist/pages.d.ts +45 -0
- package/dist/pages.js +107 -0
- package/dist/pages.js.map +1 -0
- package/dist/styles.css +66 -0
- package/package.json +6 -1
package/dist/index.cjs
CHANGED
|
@@ -46,6 +46,7 @@ __export(index_exports, {
|
|
|
46
46
|
DropdownMenuItem: () => DropdownMenuItem,
|
|
47
47
|
DropdownMenuSeparator: () => DropdownMenuSeparator,
|
|
48
48
|
DropdownMenuTrigger: () => DropdownMenuTrigger,
|
|
49
|
+
EmptySection: () => EmptySection,
|
|
49
50
|
ItemActionToolbar: () => ItemActionToolbar,
|
|
50
51
|
ItemInteractionLayer: () => ItemInteractionLayer,
|
|
51
52
|
LinkEditorPanel: () => LinkEditorPanel,
|
|
@@ -74,7 +75,7 @@ __export(index_exports, {
|
|
|
74
75
|
module.exports = __toCommonJS(index_exports);
|
|
75
76
|
|
|
76
77
|
// src/OhhwellsBridge.tsx
|
|
77
|
-
var
|
|
78
|
+
var import_react17 = __toESM(require("react"), 1);
|
|
78
79
|
var import_client2 = require("react-dom/client");
|
|
79
80
|
var import_react_dom3 = require("react-dom");
|
|
80
81
|
|
|
@@ -156,7 +157,12 @@ function parseAiSectionsState(raw) {
|
|
|
156
157
|
media: entry.media && typeof entry.media === "object" ? entry.media : {}
|
|
157
158
|
}));
|
|
158
159
|
const removed = Array.isArray(parsed.removed) ? parsed.removed.filter((id) => typeof id === "string" && id.length > 0) : [];
|
|
159
|
-
return {
|
|
160
|
+
return {
|
|
161
|
+
v: 1,
|
|
162
|
+
sections,
|
|
163
|
+
...removed.length ? { removed } : {},
|
|
164
|
+
...parsed.hideTemplate === true ? { hideTemplate: true } : {}
|
|
165
|
+
};
|
|
160
166
|
} catch {
|
|
161
167
|
return EMPTY_AI_SECTIONS;
|
|
162
168
|
}
|
|
@@ -169,6 +175,7 @@ function applyTreeToState(state, payload) {
|
|
|
169
175
|
const entry = {
|
|
170
176
|
id: payload.id,
|
|
171
177
|
label: payload.label ?? "Generated section",
|
|
178
|
+
...typeof payload.path === "string" && payload.path ? { path: payload.path } : {},
|
|
172
179
|
afterSection: payload.mode === "insert" && !insertBefore ? payload.targetSectionId ?? null : null,
|
|
173
180
|
...insertBefore && payload.targetSectionId ? { beforeSection: payload.targetSectionId } : {},
|
|
174
181
|
...payload.mode === "replace" && payload.targetSectionId ? { replaces: payload.targetSectionId } : {},
|
|
@@ -191,6 +198,317 @@ function deleteSectionFromState(state, sectionId) {
|
|
|
191
198
|
return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
|
|
192
199
|
}
|
|
193
200
|
|
|
201
|
+
// src/lib/brand-chrome.ts
|
|
202
|
+
var BRAND_NAME_KEY = "__ohw_brand_name";
|
|
203
|
+
var BRAND_TITLE_KEY = "__ohw_site_title";
|
|
204
|
+
var BRAND_FAVICON_LETTER_KEY = "__ohw_favicon_letter";
|
|
205
|
+
var BRAND_CHROME_KEYS = /* @__PURE__ */ new Set([
|
|
206
|
+
BRAND_NAME_KEY,
|
|
207
|
+
BRAND_TITLE_KEY,
|
|
208
|
+
BRAND_FAVICON_LETTER_KEY
|
|
209
|
+
]);
|
|
210
|
+
function upsertMeta(selector, attr, token, value) {
|
|
211
|
+
let el = document.head.querySelector(selector);
|
|
212
|
+
if (!el) {
|
|
213
|
+
el = document.createElement("meta");
|
|
214
|
+
el.setAttribute(attr, token);
|
|
215
|
+
document.head.appendChild(el);
|
|
216
|
+
}
|
|
217
|
+
if (el.getAttribute("content") !== value) el.setAttribute("content", value);
|
|
218
|
+
}
|
|
219
|
+
function escapeXml(value) {
|
|
220
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
221
|
+
}
|
|
222
|
+
function applyLetterFavicon(letter) {
|
|
223
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" rx="12" fill="#111827"/><text x="32" y="46" font-family="system-ui,-apple-system,Segoe UI,sans-serif" font-size="40" font-weight="700" text-anchor="middle" fill="#ffffff">${escapeXml(letter)}</text></svg>`;
|
|
224
|
+
const href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
225
|
+
let link = document.head.querySelector('link[rel="icon"]');
|
|
226
|
+
if (!link) {
|
|
227
|
+
link = document.createElement("link");
|
|
228
|
+
link.rel = "icon";
|
|
229
|
+
document.head.appendChild(link);
|
|
230
|
+
}
|
|
231
|
+
link.type = "image/svg+xml";
|
|
232
|
+
if (link.href !== href) link.href = href;
|
|
233
|
+
}
|
|
234
|
+
function applyBrandChrome(content) {
|
|
235
|
+
const name = content[BRAND_NAME_KEY];
|
|
236
|
+
if (typeof name === "string" && name.length > 0) {
|
|
237
|
+
document.querySelectorAll("[data-ohw-wordmark]").forEach((el) => {
|
|
238
|
+
if (el.textContent !== name) el.textContent = name;
|
|
239
|
+
if (el.getAttribute("title") !== name) el.setAttribute("title", name);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
const title = content[BRAND_TITLE_KEY];
|
|
243
|
+
if (typeof title === "string" && title.length > 0) {
|
|
244
|
+
if (document.title !== title) document.title = title;
|
|
245
|
+
upsertMeta('meta[property="og:title"]', "property", "og:title", title);
|
|
246
|
+
upsertMeta('meta[name="twitter:title"]', "name", "twitter:title", title);
|
|
247
|
+
}
|
|
248
|
+
const letter = content[BRAND_FAVICON_LETTER_KEY];
|
|
249
|
+
if (typeof letter === "string" && letter.length > 0) {
|
|
250
|
+
applyLetterFavicon(letter);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// src/lib/brand-kit.ts
|
|
255
|
+
var BRAND_KIT_KEY = "__ohw_brand";
|
|
256
|
+
var BRAND_VAR_PREFIX = "--ohw-brand-";
|
|
257
|
+
var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
|
|
258
|
+
(role) => `${BRAND_VAR_PREFIX}${role}`
|
|
259
|
+
);
|
|
260
|
+
var FONT_VARS = {
|
|
261
|
+
heading: ["--font-heading", "--font-display", "--brand-font-heading"],
|
|
262
|
+
body: ["--font-body", "--brand-font-body"]
|
|
263
|
+
};
|
|
264
|
+
var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
|
|
265
|
+
function brandColorVars(kit) {
|
|
266
|
+
const { dark, primary, accent, light } = kit.palette;
|
|
267
|
+
const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
|
|
268
|
+
return {
|
|
269
|
+
[`${BRAND_VAR_PREFIX}primary`]: primary,
|
|
270
|
+
[`${BRAND_VAR_PREFIX}accent`]: accent,
|
|
271
|
+
[`${BRAND_VAR_PREFIX}light`]: light,
|
|
272
|
+
[`${BRAND_VAR_PREFIX}dark`]: dark,
|
|
273
|
+
[`${BRAND_VAR_PREFIX}surface`]: mix(light, 95, dark),
|
|
274
|
+
[`${BRAND_VAR_PREFIX}border`]: mix(light, 85, dark),
|
|
275
|
+
[`${BRAND_VAR_PREFIX}muted`]: mix(dark, 62, light)
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function parseBrandKit(raw) {
|
|
279
|
+
if (!raw) return null;
|
|
280
|
+
try {
|
|
281
|
+
const parsed = JSON.parse(raw);
|
|
282
|
+
const p = parsed?.palette;
|
|
283
|
+
const f = parsed?.fonts;
|
|
284
|
+
if (!p || !f || typeof p.dark !== "string" || typeof p.primary !== "string" || typeof p.accent !== "string" || typeof p.light !== "string" || typeof f.heading !== "string" || typeof f.body !== "string") {
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
|
|
289
|
+
fonts: { heading: f.heading, body: f.body }
|
|
290
|
+
};
|
|
291
|
+
} catch {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
function familyOf(stack) {
|
|
296
|
+
const first = stack.split(",")[0]?.trim() ?? "";
|
|
297
|
+
return first.replace(/^['"]|['"]$/g, "");
|
|
298
|
+
}
|
|
299
|
+
function loadBrandFonts(families) {
|
|
300
|
+
const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
|
|
301
|
+
if (unique.length === 0) return;
|
|
302
|
+
const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
|
|
303
|
+
const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
|
|
304
|
+
let link = document.getElementById(BRAND_FONT_LINK_ID);
|
|
305
|
+
if (!link) {
|
|
306
|
+
link = document.createElement("link");
|
|
307
|
+
link.id = BRAND_FONT_LINK_ID;
|
|
308
|
+
link.rel = "stylesheet";
|
|
309
|
+
document.head.appendChild(link);
|
|
310
|
+
}
|
|
311
|
+
if (link.href !== href) link.href = href;
|
|
312
|
+
}
|
|
313
|
+
function applyBrandToDom(kit) {
|
|
314
|
+
const root = document.documentElement;
|
|
315
|
+
if (!kit) {
|
|
316
|
+
for (const name of BRAND_VAR_NAMES) root.style.removeProperty(name);
|
|
317
|
+
for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
|
|
318
|
+
document.getElementById(BRAND_FONT_LINK_ID)?.remove();
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
|
|
322
|
+
for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
|
|
323
|
+
for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
|
|
324
|
+
loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// src/lib/section-styles.ts
|
|
328
|
+
var STYLE_STORE_KEY = "__ohw_styles";
|
|
329
|
+
var STYLE_SHEET_ID = "ohw-section-styles";
|
|
330
|
+
function parseStyleStore(raw) {
|
|
331
|
+
if (!raw) return null;
|
|
332
|
+
try {
|
|
333
|
+
const parsed = JSON.parse(raw);
|
|
334
|
+
if (parsed?.v !== 1) return null;
|
|
335
|
+
return {
|
|
336
|
+
v: 1,
|
|
337
|
+
sections: typeof parsed.sections === "object" && parsed.sections ? parsed.sections : {},
|
|
338
|
+
nodes: typeof parsed.nodes === "object" && parsed.nodes ? parsed.nodes : {}
|
|
339
|
+
};
|
|
340
|
+
} catch {
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
var BG_VALUES = {
|
|
345
|
+
surface: "color-mix(in srgb, var(--ohw-brand-light, var(--color-light, #ECECEB)) 94%, var(--ohw-brand-dark, var(--color-dark, #0C0A09)))",
|
|
346
|
+
accent: "var(--ohw-brand-primary, var(--color-primary, #0078E5))",
|
|
347
|
+
"accent-soft": "color-mix(in srgb, var(--ohw-brand-primary, var(--color-primary, #0078E5)) 12%, var(--ohw-brand-light, var(--color-light, #FFFFFF)))"
|
|
348
|
+
};
|
|
349
|
+
var HEADLINE_SIZES = { md: 24, lg: 32, xl: 40, display: 56 };
|
|
350
|
+
function styleSheetCss() {
|
|
351
|
+
const rules = [];
|
|
352
|
+
for (const [tone, value] of Object.entries(BG_VALUES)) {
|
|
353
|
+
rules.push(`[data-ohw-style-bg="${tone}"] { background: ${value} !important; }`);
|
|
354
|
+
}
|
|
355
|
+
rules.push(
|
|
356
|
+
`[data-ohw-style-bg="accent"] { color: var(--ohw-brand-light, var(--color-light, #FFFFFF)) !important; }`
|
|
357
|
+
);
|
|
358
|
+
rules.push(
|
|
359
|
+
`[data-ohw-style-distribution="space-between"] { display: flex !important; flex-direction: column; justify-content: space-between; }`,
|
|
360
|
+
`[data-ohw-style-distribution="center"] { display: flex !important; flex-direction: column; justify-content: center; }`
|
|
361
|
+
);
|
|
362
|
+
for (const [scale, size] of Object.entries(HEADLINE_SIZES)) {
|
|
363
|
+
rules.push(
|
|
364
|
+
`[data-ohw-style-headline="${scale}"] :is(h1, h2, h3) { font-size: ${size}px !important; line-height: 1.15 !important; }`
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
rules.push(
|
|
368
|
+
`[data-ohw-style-aspect="fill-height"] img { height: 100% !important; aspect-ratio: auto !important; object-fit: cover; }`
|
|
369
|
+
);
|
|
370
|
+
for (const aspect of ["1:1", "4:5", "3:4", "3:2", "16:9", "2:1", "3:1"]) {
|
|
371
|
+
rules.push(
|
|
372
|
+
`[data-ohw-style-aspect="${aspect.replace(":", "-")}"] img { aspect-ratio: ${aspect.replace(":", " / ")} !important; height: auto !important; object-fit: cover; }`
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
const pad = { tight: 40, balanced: 64, airy: 96 };
|
|
376
|
+
for (const [spacing, px] of Object.entries(pad)) {
|
|
377
|
+
rules.push(
|
|
378
|
+
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
return rules.join("\n");
|
|
382
|
+
}
|
|
383
|
+
var STYLE_FONT_LINK_ID = "ohw-style-fonts";
|
|
384
|
+
function loadStyleFonts(families) {
|
|
385
|
+
const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
|
|
386
|
+
const existing = document.getElementById(STYLE_FONT_LINK_ID);
|
|
387
|
+
if (unique.length === 0) {
|
|
388
|
+
existing?.remove();
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
|
|
392
|
+
const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
|
|
393
|
+
let link = existing;
|
|
394
|
+
if (!link) {
|
|
395
|
+
link = document.createElement("link");
|
|
396
|
+
link.id = STYLE_FONT_LINK_ID;
|
|
397
|
+
link.rel = "stylesheet";
|
|
398
|
+
document.head.appendChild(link);
|
|
399
|
+
}
|
|
400
|
+
if (link.href !== href) link.href = href;
|
|
401
|
+
}
|
|
402
|
+
var SECTION_ATTRS = {
|
|
403
|
+
sectionBackground: "data-ohw-style-bg",
|
|
404
|
+
textDistribution: "data-ohw-style-distribution",
|
|
405
|
+
headlineScale: "data-ohw-style-headline",
|
|
406
|
+
imageAspect: "data-ohw-style-aspect",
|
|
407
|
+
spacing: "data-ohw-style-spacing"
|
|
408
|
+
};
|
|
409
|
+
var NODE_WROTE_ATTR = "data-ohw-style-node";
|
|
410
|
+
var NODE_PROPS = ["color", "font-family", "font-size", "background"];
|
|
411
|
+
function saveInline(el, prop) {
|
|
412
|
+
const attr = `data-ohw-style-prev-${prop}`;
|
|
413
|
+
if (!el.hasAttribute(attr)) el.setAttribute(attr, el.style.getPropertyValue(prop));
|
|
414
|
+
}
|
|
415
|
+
function restoreInline(el, prop) {
|
|
416
|
+
const attr = `data-ohw-style-prev-${prop}`;
|
|
417
|
+
if (!el.hasAttribute(attr)) return;
|
|
418
|
+
const prev = el.getAttribute(attr) ?? "";
|
|
419
|
+
if (prev) el.style.setProperty(prop, prev);
|
|
420
|
+
else el.style.removeProperty(prop);
|
|
421
|
+
el.removeAttribute(attr);
|
|
422
|
+
}
|
|
423
|
+
function ensureStyleSheet() {
|
|
424
|
+
let el = document.getElementById(STYLE_SHEET_ID);
|
|
425
|
+
if (!el) {
|
|
426
|
+
el = document.createElement("style");
|
|
427
|
+
el.id = STYLE_SHEET_ID;
|
|
428
|
+
document.head.appendChild(el);
|
|
429
|
+
}
|
|
430
|
+
const css = styleSheetCss();
|
|
431
|
+
if (el.textContent !== css) el.textContent = css;
|
|
432
|
+
}
|
|
433
|
+
function clearSectionAttrs(root) {
|
|
434
|
+
for (const attr of Object.values(SECTION_ATTRS)) {
|
|
435
|
+
for (const el of Array.from(root.querySelectorAll(`[${attr}]`))) el.removeAttribute(attr);
|
|
436
|
+
}
|
|
437
|
+
for (const el of Array.from(root.querySelectorAll("[data-ohw-style-bgcolor]"))) {
|
|
438
|
+
restoreInline(el, "background");
|
|
439
|
+
el.removeAttribute("data-ohw-style-bgcolor");
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
function clearNodeProps(root) {
|
|
443
|
+
for (const el of Array.from(root.querySelectorAll(`[${NODE_WROTE_ATTR}]`))) {
|
|
444
|
+
const h = el;
|
|
445
|
+
for (const prop of NODE_PROPS) restoreInline(h, prop);
|
|
446
|
+
h.removeAttribute(NODE_WROTE_ATTR);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
function buttonSurfaceOf(el) {
|
|
450
|
+
return el.closest("a, button") ?? el;
|
|
451
|
+
}
|
|
452
|
+
function applyStylesToDom(store) {
|
|
453
|
+
ensureStyleSheet();
|
|
454
|
+
clearSectionAttrs(document);
|
|
455
|
+
clearNodeProps(document);
|
|
456
|
+
loadStyleFonts(
|
|
457
|
+
store ? Object.values(store.nodes).flatMap((n) => n.fontFamily ? [n.fontFamily] : []) : []
|
|
458
|
+
);
|
|
459
|
+
if (!store) return;
|
|
460
|
+
for (const [sectionId, override] of Object.entries(store.sections)) {
|
|
461
|
+
const sections = document.querySelectorAll(
|
|
462
|
+
`[data-ohw-section="${CSS.escape(sectionId)}"]`
|
|
463
|
+
);
|
|
464
|
+
for (const section of Array.from(sections)) {
|
|
465
|
+
for (const [prop, attr] of Object.entries(SECTION_ATTRS)) {
|
|
466
|
+
const value = override[prop];
|
|
467
|
+
if (value === void 0) continue;
|
|
468
|
+
if (prop === "sectionBackground" && override.sectionBackgroundColor !== void 0) continue;
|
|
469
|
+
section.setAttribute(attr, String(value).replace(":", "-"));
|
|
470
|
+
}
|
|
471
|
+
if (override.sectionBackgroundColor !== void 0) {
|
|
472
|
+
saveInline(section, "background");
|
|
473
|
+
section.style.setProperty("background", override.sectionBackgroundColor, "important");
|
|
474
|
+
section.setAttribute("data-ohw-style-bgcolor", "");
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
for (const [key, override] of Object.entries(store.nodes)) {
|
|
479
|
+
const nodes = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
|
|
480
|
+
for (const el of Array.from(nodes)) {
|
|
481
|
+
if (override.color !== void 0) {
|
|
482
|
+
saveInline(el, "color");
|
|
483
|
+
el.style.setProperty("color", override.color, "important");
|
|
484
|
+
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
485
|
+
}
|
|
486
|
+
if (override.fontFamily !== void 0) {
|
|
487
|
+
saveInline(el, "font-family");
|
|
488
|
+
el.style.setProperty("font-family", `'${override.fontFamily}'`, "important");
|
|
489
|
+
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
490
|
+
}
|
|
491
|
+
if (override.fontSize !== void 0) {
|
|
492
|
+
saveInline(el, "font-size");
|
|
493
|
+
el.style.setProperty("font-size", `${override.fontSize}px`, "important");
|
|
494
|
+
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
495
|
+
}
|
|
496
|
+
if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
|
|
497
|
+
const surface = buttonSurfaceOf(el);
|
|
498
|
+
if (override.buttonBackground !== void 0) {
|
|
499
|
+
saveInline(surface, "background");
|
|
500
|
+
surface.style.setProperty("background", override.buttonBackground, "important");
|
|
501
|
+
}
|
|
502
|
+
if (override.buttonText !== void 0) {
|
|
503
|
+
saveInline(surface, "color");
|
|
504
|
+
surface.style.setProperty("color", override.buttonText, "important");
|
|
505
|
+
}
|
|
506
|
+
surface.setAttribute(NODE_WROTE_ATTR, "");
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
194
512
|
// src/ui/ai-tree/aiSectionsManager.tsx
|
|
195
513
|
var import_react_dom = require("react-dom");
|
|
196
514
|
var import_client = require("react-dom/client");
|
|
@@ -205,7 +523,8 @@ function lucideByName(name) {
|
|
|
205
523
|
}
|
|
206
524
|
var typeStyle = (spec, font) => ({
|
|
207
525
|
fontFamily: font,
|
|
208
|
-
|
|
526
|
+
// Headings shrink with the viewport (reaching full size around ~900px wide); body copy stays put.
|
|
527
|
+
fontSize: spec.size >= 24 ? `clamp(${Math.max(18, Math.round(spec.size * 0.6))}px, ${(spec.size / 9).toFixed(2)}vw, ${spec.size}px)` : spec.size,
|
|
209
528
|
lineHeight: spec.line,
|
|
210
529
|
fontWeight: spec.weight
|
|
211
530
|
});
|
|
@@ -220,6 +539,36 @@ var FEATURE_LINE_CSS = [
|
|
|
220
539
|
`background-color:currentColor;-webkit-mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px;`,
|
|
221
540
|
`mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px}`
|
|
222
541
|
].join("");
|
|
542
|
+
function hexLuminance(color) {
|
|
543
|
+
const m = /^#([0-9a-f]{6})$/i.exec(color.trim());
|
|
544
|
+
if (!m) return null;
|
|
545
|
+
const [r2, g, b] = [0, 2, 4].map((i) => {
|
|
546
|
+
const c = parseInt(m[1].slice(i, i + 2), 16) / 255;
|
|
547
|
+
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
548
|
+
});
|
|
549
|
+
return 0.2126 * r2 + 0.7152 * g + 0.0722 * b;
|
|
550
|
+
}
|
|
551
|
+
function hexContrast(a, b) {
|
|
552
|
+
const la = hexLuminance(a);
|
|
553
|
+
const lb = hexLuminance(b);
|
|
554
|
+
if (la === null || lb === null) return null;
|
|
555
|
+
const [hi, lo] = la > lb ? [la, lb] : [lb, la];
|
|
556
|
+
return (hi + 0.05) / (lo + 0.05);
|
|
557
|
+
}
|
|
558
|
+
function accentBandContext(brand) {
|
|
559
|
+
const p = brand.palette;
|
|
560
|
+
const lightWins = (hexContrast(p.light, p.primary) ?? 99) >= (hexContrast(p.dark, p.primary) ?? 0);
|
|
561
|
+
if (lightWins) {
|
|
562
|
+
return {
|
|
563
|
+
brand: { ...brand, palette: { dark: p.light, primary: p.light, accent: p.light, light: p.primary } },
|
|
564
|
+
buttonLabel: p.primary
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
return {
|
|
568
|
+
brand: { ...brand, palette: { dark: p.dark, primary: p.dark, accent: p.dark, light: p.light } },
|
|
569
|
+
buttonLabel: p.light
|
|
570
|
+
};
|
|
571
|
+
}
|
|
223
572
|
function textAttrs(ctx, path) {
|
|
224
573
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
225
574
|
}
|
|
@@ -231,7 +580,12 @@ var AI_RESPONSIVE_CSS = [
|
|
|
231
580
|
"@media (max-width: 640px) {",
|
|
232
581
|
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
233
582
|
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
583
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
584
|
+
" [data-ai-responsive] [data-ai-group] { display: flex !important; flex-direction: column !important; }",
|
|
585
|
+
" [data-ai-responsive] [data-ai-group] > * { grid-column: auto !important; }",
|
|
234
586
|
" [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
587
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
588
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
235
589
|
"}"
|
|
236
590
|
].join("\n");
|
|
237
591
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
@@ -309,7 +663,7 @@ function ButtonEl({
|
|
|
309
663
|
}) {
|
|
310
664
|
const secondary = slots.variant === "secondary";
|
|
311
665
|
const href = str(slots.href);
|
|
312
|
-
const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`) } : {};
|
|
666
|
+
const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`), "data-ohw-role": "button" } : {};
|
|
313
667
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
314
668
|
"a",
|
|
315
669
|
{
|
|
@@ -325,7 +679,7 @@ function ButtonEl({
|
|
|
325
679
|
textDecoration: "none",
|
|
326
680
|
cursor: "pointer",
|
|
327
681
|
...typeStyle(AI_TREE_TOKENS.type.button, ctx.brand.fonts.body),
|
|
328
|
-
...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color: AI_TREE_TOKENS.textPrimaryForeground }
|
|
682
|
+
...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color: ctx.buttonLabel ?? AI_TREE_TOKENS.textPrimaryForeground }
|
|
329
683
|
},
|
|
330
684
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
|
|
331
685
|
}
|
|
@@ -831,7 +1185,24 @@ function CardBlock({ node, ctx, path }) {
|
|
|
831
1185
|
minWidth: 0
|
|
832
1186
|
},
|
|
833
1187
|
children: [
|
|
834
|
-
media && (horizontal ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1188
|
+
media && (horizontal ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1189
|
+
"div",
|
|
1190
|
+
{
|
|
1191
|
+
style: (
|
|
1192
|
+
// An icon hugs its glyph — flex:1 gave a 48px icon half the card and pushed the
|
|
1193
|
+
// text to the far side. Photos keep the half-and-half split. The inset has no
|
|
1194
|
+
// inner padding (the photo split absorbed that), so the icon carries its own gap.
|
|
1195
|
+
/^(lucide|simple):/.test(mediaRef) ? {
|
|
1196
|
+
flexShrink: 0,
|
|
1197
|
+
display: "flex",
|
|
1198
|
+
alignItems: "center",
|
|
1199
|
+
padding: mediaInset,
|
|
1200
|
+
[mediaPosition === "right" ? "marginLeft" : "marginRight"]: 20
|
|
1201
|
+
} : { flex: 1, minWidth: 0, display: "flex", alignItems: "center", padding: mediaInset }
|
|
1202
|
+
),
|
|
1203
|
+
children: media
|
|
1204
|
+
}
|
|
1205
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
835
1206
|
"div",
|
|
836
1207
|
{
|
|
837
1208
|
style: /^(lucide|simple):/.test(mediaRef) ? { padding: `${AI_TREE_TOKENS.paddingBlock}px ${AI_TREE_TOKENS.paddingBlock}px 0` } : hasBg ? void 0 : { borderRadius: AI_TREE_TOKENS.radiusCard, overflow: "hidden" },
|
|
@@ -1095,6 +1466,49 @@ function renderNode(node, ctx, path) {
|
|
|
1095
1466
|
switch (node.type) {
|
|
1096
1467
|
case "text":
|
|
1097
1468
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextBlock, { slots, ctx, path });
|
|
1469
|
+
// Layout container: arranges child blocks, contributes no content of its own. `grid` is a
|
|
1470
|
+
// nested 12-column grid the children span (a collage is 3–5 media on it, bottom-aligned so
|
|
1471
|
+
// mixed aspects read as a composition); `split` is exactly two children at a ratio; `stack`
|
|
1472
|
+
// is a column. Children render through this same dispatcher, so edit markers, media
|
|
1473
|
+
// resolution, and copy paths all work unchanged inside a group.
|
|
1474
|
+
case "group": {
|
|
1475
|
+
const layout = str(slots.layout);
|
|
1476
|
+
const gap = slots.spacing === "tight" ? AI_TREE_TOKENS.spacing3 : slots.spacing === "airy" ? AI_TREE_TOKENS.spacing8 : AI_TREE_TOKENS.spacing6;
|
|
1477
|
+
const kids = (node.children ?? []).map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1478
|
+
"div",
|
|
1479
|
+
{
|
|
1480
|
+
style: layout === "grid" ? {
|
|
1481
|
+
gridColumn: `span ${typeof child.span === "number" ? Math.min(12, Math.max(1, child.span)) : 12}`,
|
|
1482
|
+
minWidth: 0
|
|
1483
|
+
} : { minWidth: 0 },
|
|
1484
|
+
children: renderNode(child, ctx, `${path}.c${i}`)
|
|
1485
|
+
},
|
|
1486
|
+
i
|
|
1487
|
+
));
|
|
1488
|
+
if (layout === "grid") {
|
|
1489
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1490
|
+
"div",
|
|
1491
|
+
{
|
|
1492
|
+
"data-ai-group": "grid",
|
|
1493
|
+
style: { display: "grid", gridTemplateColumns: "repeat(12, 1fr)", gap, alignItems: "end" },
|
|
1494
|
+
children: kids
|
|
1495
|
+
}
|
|
1496
|
+
);
|
|
1497
|
+
}
|
|
1498
|
+
if (layout === "split") {
|
|
1499
|
+
const ratio = str(slots.ratio);
|
|
1500
|
+
const cols = ratio === "3:5" ? "3fr 5fr" : ratio === "5:3" ? "5fr 3fr" : "1fr 1fr";
|
|
1501
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1502
|
+
"div",
|
|
1503
|
+
{
|
|
1504
|
+
"data-ai-group": "split",
|
|
1505
|
+
style: { display: "grid", gridTemplateColumns: cols, gap, alignItems: "center" },
|
|
1506
|
+
children: kids
|
|
1507
|
+
}
|
|
1508
|
+
);
|
|
1509
|
+
}
|
|
1510
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "data-ai-group": "stack", style: { display: "flex", flexDirection: "column", gap }, children: kids });
|
|
1511
|
+
}
|
|
1098
1512
|
case "button":
|
|
1099
1513
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ButtonEl, { slots, ctx, path });
|
|
1100
1514
|
case "button-row":
|
|
@@ -1227,11 +1641,14 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1227
1641
|
return null;
|
|
1228
1642
|
}
|
|
1229
1643
|
const resolvedBrand = brand ?? AI_DEFAULT_BRAND;
|
|
1644
|
+
const band = (tree.settings ?? {}).sectionBackground === "accent" ? accentBandContext(resolvedBrand) : null;
|
|
1645
|
+
const blockBrand = band?.brand ?? resolvedBrand;
|
|
1230
1646
|
const ctx = {
|
|
1231
|
-
brand:
|
|
1647
|
+
brand: blockBrand,
|
|
1232
1648
|
resolveMedia: resolveMedia ?? (() => null),
|
|
1233
|
-
cardSurface:
|
|
1234
|
-
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null
|
|
1649
|
+
cardSurface: blockBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${blockBrand.palette.light} 90%, ${blockBrand.palette.dark})`,
|
|
1650
|
+
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
|
|
1651
|
+
...band ? { buttonLabel: band.buttonLabel } : {}
|
|
1235
1652
|
};
|
|
1236
1653
|
const settings = tree.settings ?? {};
|
|
1237
1654
|
const pad = AI_TREE_TOKENS.sectionPadding[settings.spacing ?? "balanced"];
|
|
@@ -1239,6 +1656,20 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1239
1656
|
const overlayAlpha = { low: 0.25, medium: 0.45, high: 0.65 }[settings.overlayIntensity ?? "medium"];
|
|
1240
1657
|
const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
|
|
1241
1658
|
const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
|
|
1659
|
+
const toneBackground = (() => {
|
|
1660
|
+
const { dark, primary, light } = resolvedBrand.palette;
|
|
1661
|
+
switch (settings.sectionBackground) {
|
|
1662
|
+
case "surface":
|
|
1663
|
+
return `color-mix(in srgb, ${light} 94%, ${dark})`;
|
|
1664
|
+
case "accent":
|
|
1665
|
+
return primary;
|
|
1666
|
+
case "accent-soft":
|
|
1667
|
+
return `color-mix(in srgb, ${primary} 12%, ${light})`;
|
|
1668
|
+
default:
|
|
1669
|
+
return void 0;
|
|
1670
|
+
}
|
|
1671
|
+
})();
|
|
1672
|
+
const distributed = !isOverlay && settings.textDistribution;
|
|
1242
1673
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1243
1674
|
"section",
|
|
1244
1675
|
{
|
|
@@ -1248,10 +1679,11 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1248
1679
|
style: {
|
|
1249
1680
|
position: "relative",
|
|
1250
1681
|
padding: `${pad}px 0`,
|
|
1251
|
-
background: isOverlay && !backgroundUrl ? "#DBEAFE" : void 0,
|
|
1682
|
+
background: toneBackground ?? (isOverlay && !backgroundUrl ? "#DBEAFE" : void 0),
|
|
1252
1683
|
backgroundImage: backgroundUrl ? `url(${backgroundUrl})` : void 0,
|
|
1253
1684
|
backgroundSize: "cover",
|
|
1254
|
-
backgroundPosition: "center"
|
|
1685
|
+
backgroundPosition: "center",
|
|
1686
|
+
color: settings.sectionBackground === "accent" ? blockBrand.palette.dark : void 0
|
|
1255
1687
|
},
|
|
1256
1688
|
children: [
|
|
1257
1689
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
|
|
@@ -1275,10 +1707,24 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1275
1707
|
display: "grid",
|
|
1276
1708
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
1277
1709
|
gap: AI_TREE_TOKENS.spacing6,
|
|
1278
|
-
alignItems: settings.verticalPosition === "top" ? "start" : "center",
|
|
1710
|
+
alignItems: distributed === "space-between" ? "stretch" : (distributed ?? settings.verticalPosition) === "top" ? "start" : "center",
|
|
1279
1711
|
marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
|
|
1280
1712
|
},
|
|
1281
|
-
children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1713
|
+
children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1714
|
+
"div",
|
|
1715
|
+
{
|
|
1716
|
+
"data-ai-cell": "",
|
|
1717
|
+
style: {
|
|
1718
|
+
gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
|
|
1719
|
+
minWidth: 0,
|
|
1720
|
+
// space-between: each column becomes a flex column whose content spreads over
|
|
1721
|
+
// the full row height instead of clumping at the top.
|
|
1722
|
+
...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
|
|
1723
|
+
},
|
|
1724
|
+
children: renderNode(block, ctx, `r${r2}.b${b}`)
|
|
1725
|
+
},
|
|
1726
|
+
b
|
|
1727
|
+
))
|
|
1282
1728
|
},
|
|
1283
1729
|
r2
|
|
1284
1730
|
))
|
|
@@ -1294,17 +1740,36 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
|
1294
1740
|
var CONTAINER_ATTR = "data-ohw-ai-generated";
|
|
1295
1741
|
var REPLACED_ATTR = "data-ohw-ai-replaced-by";
|
|
1296
1742
|
var REMOVED_ATTR = "data-ohw-ai-removed";
|
|
1743
|
+
var TEMPLATE_HIDDEN_ATTR = "data-ohw-ai-template-hidden";
|
|
1744
|
+
var CHROME_SECTION_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
1745
|
+
function readRootVar(name) {
|
|
1746
|
+
if (typeof document === "undefined") return "";
|
|
1747
|
+
return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
|
1748
|
+
}
|
|
1749
|
+
function deriveBrandOverride() {
|
|
1750
|
+
const dark = readRootVar("--ohw-brand-dark");
|
|
1751
|
+
const primary = readRootVar("--ohw-brand-primary");
|
|
1752
|
+
const light = readRootVar("--ohw-brand-light");
|
|
1753
|
+
if (!dark || !primary || !light) return null;
|
|
1754
|
+
const accent = readRootVar("--ohw-brand-accent");
|
|
1755
|
+
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
1756
|
+
const body = readRootVar("--font-body");
|
|
1757
|
+
return {
|
|
1758
|
+
palette: { dark, primary, accent: accent || dark, light },
|
|
1759
|
+
fonts: {
|
|
1760
|
+
heading: heading || AI_DEFAULT_BRAND.fonts.heading,
|
|
1761
|
+
body: body || AI_DEFAULT_BRAND.fonts.body
|
|
1762
|
+
}
|
|
1763
|
+
};
|
|
1764
|
+
}
|
|
1297
1765
|
function deriveTemplateBrand() {
|
|
1298
|
-
|
|
1299
|
-
const
|
|
1300
|
-
const
|
|
1301
|
-
const dark = read("--color-dark");
|
|
1302
|
-
const primary = read("--color-primary");
|
|
1303
|
-
const light = read("--color-light");
|
|
1766
|
+
const dark = readRootVar("--color-dark");
|
|
1767
|
+
const primary = readRootVar("--color-primary");
|
|
1768
|
+
const light = readRootVar("--color-light");
|
|
1304
1769
|
if (!dark || !primary || !light) return null;
|
|
1305
|
-
const accent =
|
|
1306
|
-
const heading =
|
|
1307
|
-
const body =
|
|
1770
|
+
const accent = readRootVar("--color-accent");
|
|
1771
|
+
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
1772
|
+
const body = readRootVar("--font-body");
|
|
1308
1773
|
return {
|
|
1309
1774
|
palette: { dark, primary, accent: accent || dark, light },
|
|
1310
1775
|
fonts: {
|
|
@@ -1376,6 +1841,24 @@ function syncRemovedSections(state) {
|
|
|
1376
1841
|
}
|
|
1377
1842
|
}
|
|
1378
1843
|
}
|
|
1844
|
+
function syncTemplateHidden(state, pageHasSections) {
|
|
1845
|
+
const hide = state.hideTemplate === true && pageHasSections;
|
|
1846
|
+
for (const el of Array.from(document.querySelectorAll(`[${TEMPLATE_HIDDEN_ATTR}]`))) {
|
|
1847
|
+
if (!hide) {
|
|
1848
|
+
el.style.removeProperty("display");
|
|
1849
|
+
el.removeAttribute(TEMPLATE_HIDDEN_ATTR);
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
if (!hide) return;
|
|
1853
|
+
for (const el of Array.from(document.querySelectorAll("[data-ohw-section]"))) {
|
|
1854
|
+
if (el.hasAttribute(CONTAINER_ATTR)) continue;
|
|
1855
|
+
if (CHROME_SECTION_IDS.has(el.getAttribute("data-ohw-section") ?? "")) continue;
|
|
1856
|
+
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
1857
|
+
if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(REMOVED_ATTR)) continue;
|
|
1858
|
+
el.style.display = "none";
|
|
1859
|
+
el.setAttribute(TEMPLATE_HIDDEN_ATTR, "");
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1379
1862
|
function syncReplacedOriginals(state) {
|
|
1380
1863
|
for (const el of document.querySelectorAll(`[${REPLACED_ATTR}]`)) {
|
|
1381
1864
|
const byId = el.getAttribute(REPLACED_ATTR) ?? "";
|
|
@@ -1396,8 +1879,12 @@ function syncReplacedOriginals(state) {
|
|
|
1396
1879
|
}
|
|
1397
1880
|
function applyAiSectionsToDom(state, options) {
|
|
1398
1881
|
if (typeof document === "undefined") return;
|
|
1882
|
+
const brandOverride = deriveBrandOverride();
|
|
1399
1883
|
const templateBrand = deriveTemplateBrand();
|
|
1400
|
-
const
|
|
1884
|
+
const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
|
|
1885
|
+
const pagePath = window.location.pathname;
|
|
1886
|
+
const pageSections = state.sections.filter((entry) => (entry.path ?? "/") === pagePath);
|
|
1887
|
+
const activeIds = new Set(pageSections.map((entry) => entry.id));
|
|
1401
1888
|
for (const [id, section] of mounted) {
|
|
1402
1889
|
if (!activeIds.has(id)) {
|
|
1403
1890
|
section.root.unmount();
|
|
@@ -1405,8 +1892,8 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1405
1892
|
mounted.delete(id);
|
|
1406
1893
|
}
|
|
1407
1894
|
}
|
|
1408
|
-
for (const entry of
|
|
1409
|
-
const serialized = JSON.stringify(entry);
|
|
1895
|
+
for (const entry of pageSections) {
|
|
1896
|
+
const serialized = JSON.stringify(entry) + brandKey;
|
|
1410
1897
|
const existing = mounted.get(entry.id);
|
|
1411
1898
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
1412
1899
|
continue;
|
|
@@ -1420,6 +1907,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1420
1907
|
mounted.delete(entry.id);
|
|
1421
1908
|
}
|
|
1422
1909
|
container.setAttribute("data-ohw-section", entry.id);
|
|
1910
|
+
container.setAttribute("data-ohw-instance", entry.id);
|
|
1423
1911
|
container.setAttribute("data-ohw-section-label", entry.label);
|
|
1424
1912
|
placeContainer(container, entry);
|
|
1425
1913
|
const root = mounted.get(entry.id)?.root ?? (0, import_client.createRoot)(container);
|
|
@@ -1430,7 +1918,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1430
1918
|
AiTreeRenderer,
|
|
1431
1919
|
{
|
|
1432
1920
|
tree: entry.tree,
|
|
1433
|
-
brand: entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
1921
|
+
brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
1434
1922
|
resolveMedia,
|
|
1435
1923
|
editKeyPrefix: `ai.${entry.id}`
|
|
1436
1924
|
}
|
|
@@ -1441,6 +1929,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1441
1929
|
}
|
|
1442
1930
|
syncReplacedOriginals(state);
|
|
1443
1931
|
syncRemovedSections(state);
|
|
1932
|
+
syncTemplateHidden(state, pageSections.length > 0);
|
|
1444
1933
|
}
|
|
1445
1934
|
|
|
1446
1935
|
// src/useLinkHrefGuardian.ts
|
|
@@ -2047,7 +2536,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
2047
2536
|
const autoId = (0, import_react5.useId)();
|
|
2048
2537
|
const insertAfter = insertAfterProp ?? autoId;
|
|
2049
2538
|
const [schedule, setSchedule] = (0, import_react5.useState)(null);
|
|
2050
|
-
const [loading, setLoading] = (0, import_react5.useState)(
|
|
2539
|
+
const [loading, setLoading] = (0, import_react5.useState)(initialScheduleId !== null);
|
|
2051
2540
|
const [inEditor, setInEditor] = (0, import_react5.useState)(false);
|
|
2052
2541
|
const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
|
|
2053
2542
|
const [modalState, setModalState] = (0, import_react5.useState)(null);
|
|
@@ -2221,8 +2710,10 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
2221
2710
|
"*"
|
|
2222
2711
|
);
|
|
2223
2712
|
};
|
|
2224
|
-
if (!inEditor && !loading && !schedule) return null;
|
|
2225
2713
|
const sectionId = `scheduling-${insertAfter}`;
|
|
2714
|
+
if (!inEditor && !loading && !schedule) {
|
|
2715
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
|
|
2716
|
+
}
|
|
2226
2717
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2227
2718
|
"section",
|
|
2228
2719
|
{
|
|
@@ -7130,13 +7621,17 @@ function MediaOverlay({
|
|
|
7130
7621
|
hover,
|
|
7131
7622
|
isUploading,
|
|
7132
7623
|
fadingOut = false,
|
|
7624
|
+
selected = false,
|
|
7625
|
+
hovered = false,
|
|
7133
7626
|
onFadeOutComplete,
|
|
7134
7627
|
onReplace,
|
|
7628
|
+
onSelect,
|
|
7135
7629
|
onVideoSettingsChange
|
|
7136
7630
|
}) {
|
|
7137
7631
|
const { rect } = hover;
|
|
7138
7632
|
const skeletonRef = React7.useRef(null);
|
|
7139
7633
|
const isVideo = hover.elementType === "video";
|
|
7634
|
+
const showChrome = !selected || hovered;
|
|
7140
7635
|
const autoplay = hover.videoAutoplay ?? true;
|
|
7141
7636
|
const muted = hover.videoMuted ?? true;
|
|
7142
7637
|
const box = {
|
|
@@ -7171,7 +7666,7 @@ function MediaOverlay({
|
|
|
7171
7666
|
}
|
|
7172
7667
|
);
|
|
7173
7668
|
}
|
|
7174
|
-
const settingsBar = isVideo && !hover.isDragOver ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
7669
|
+
const settingsBar = isVideo && !hover.isDragOver && showChrome ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
7175
7670
|
"div",
|
|
7176
7671
|
{
|
|
7177
7672
|
"data-ohw-bridge": "",
|
|
@@ -7241,11 +7736,13 @@ function MediaOverlay({
|
|
|
7241
7736
|
// in-document, pointer-events does it natively. The button below opts back in, so
|
|
7242
7737
|
// Replace still works.
|
|
7243
7738
|
pointerEvents: hover.hasTextOverlap ? "none" : "auto",
|
|
7244
|
-
|
|
7245
|
-
|
|
7739
|
+
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
7740
|
+
// than hovered. Hover keeps the existing tinted preview.
|
|
7741
|
+
boxShadow: selected ? "inset 0 0 0 2px var(--color-primary)" : "inset 0 0 0 1.5px var(--color-primary)",
|
|
7742
|
+
background: selected ? "transparent" : "color-mix(in srgb, var(--color-primary) 20%, transparent)"
|
|
7246
7743
|
},
|
|
7247
|
-
onClick: () => onReplace(hover.key),
|
|
7248
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
7744
|
+
onClick: () => onSelect && !selected ? onSelect(hover.key) : onReplace(hover.key),
|
|
7745
|
+
children: showChrome && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
7249
7746
|
Button,
|
|
7250
7747
|
{
|
|
7251
7748
|
"data-ohw-media-overlay": "",
|
|
@@ -7264,7 +7761,7 @@ function MediaOverlay({
|
|
|
7264
7761
|
},
|
|
7265
7762
|
children: [
|
|
7266
7763
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
7267
|
-
isVideo ? "Replace video" : "Replace image"
|
|
7764
|
+
isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image"
|
|
7268
7765
|
]
|
|
7269
7766
|
}
|
|
7270
7767
|
)
|
|
@@ -7334,6 +7831,9 @@ var import_lucide_react7 = require("lucide-react");
|
|
|
7334
7831
|
|
|
7335
7832
|
// src/lib/sections.ts
|
|
7336
7833
|
var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
7834
|
+
function isChromeSection(el) {
|
|
7835
|
+
return el.matches("header, nav, footer, aside");
|
|
7836
|
+
}
|
|
7337
7837
|
function titleCaseSectionId(id) {
|
|
7338
7838
|
return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
7339
7839
|
}
|
|
@@ -7344,6 +7844,8 @@ function parseSectionsFromRoot(root) {
|
|
|
7344
7844
|
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
7345
7845
|
if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
|
|
7346
7846
|
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
7847
|
+
if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
|
|
7848
|
+
continue;
|
|
7347
7849
|
seen.add(id);
|
|
7348
7850
|
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
7349
7851
|
sections.push({ id, label });
|
|
@@ -7361,8 +7863,12 @@ function parseSectionsFromHtml(html) {
|
|
|
7361
7863
|
|
|
7362
7864
|
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
7363
7865
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
7364
|
-
function
|
|
7365
|
-
const
|
|
7866
|
+
function findSectionElement(instanceId) {
|
|
7867
|
+
const escaped = CSS.escape(instanceId);
|
|
7868
|
+
return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
|
|
7869
|
+
}
|
|
7870
|
+
function readRect(instanceId) {
|
|
7871
|
+
const el = findSectionElement(instanceId);
|
|
7366
7872
|
if (!el) return null;
|
|
7367
7873
|
const r2 = el.getBoundingClientRect();
|
|
7368
7874
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
@@ -7385,7 +7891,7 @@ function useLiveSectionRect(sectionId) {
|
|
|
7385
7891
|
const opts = { capture: true, passive: true };
|
|
7386
7892
|
window.addEventListener("scroll", update, opts);
|
|
7387
7893
|
window.addEventListener("resize", update);
|
|
7388
|
-
const el =
|
|
7894
|
+
const el = findSectionElement(sectionId);
|
|
7389
7895
|
const ro = el ? new ResizeObserver(update) : null;
|
|
7390
7896
|
if (el && ro) ro.observe(el);
|
|
7391
7897
|
const interval = setInterval(update, 500);
|
|
@@ -7398,6 +7904,14 @@ function useLiveSectionRect(sectionId) {
|
|
|
7398
7904
|
}, [sectionId]);
|
|
7399
7905
|
return rect;
|
|
7400
7906
|
}
|
|
7907
|
+
function computeSectionBoundaryFlags(instanceId) {
|
|
7908
|
+
const topLevel = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
7909
|
+
(el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
|
|
7910
|
+
);
|
|
7911
|
+
const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
|
|
7912
|
+
if (index === -1) return { isFirst: true, isLast: true };
|
|
7913
|
+
return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
|
|
7914
|
+
}
|
|
7401
7915
|
var PRIMARY2 = "#0885FE";
|
|
7402
7916
|
function edgeAwareRadius(rect) {
|
|
7403
7917
|
const container = window.innerWidth <= 480 ? 16 : 24;
|
|
@@ -7471,6 +7985,7 @@ function AiSectionOverlay({
|
|
|
7471
7985
|
}) {
|
|
7472
7986
|
const [selectedId, setSelectedId] = (0, import_react8.useState)(null);
|
|
7473
7987
|
const [reviewId, setReviewId] = (0, import_react8.useState)(null);
|
|
7988
|
+
const [reviewButtonsHidden, setReviewButtonsHidden] = (0, import_react8.useState)(false);
|
|
7474
7989
|
const reviewIdRef = (0, import_react8.useRef)(null);
|
|
7475
7990
|
reviewIdRef.current = reviewId;
|
|
7476
7991
|
const selectedIdRef = (0, import_react8.useRef)(null);
|
|
@@ -7479,7 +7994,7 @@ function AiSectionOverlay({
|
|
|
7479
7994
|
(el) => {
|
|
7480
7995
|
postToParent2({
|
|
7481
7996
|
type: "ow:section-selected",
|
|
7482
|
-
sectionId: el
|
|
7997
|
+
sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
|
|
7483
7998
|
sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
|
|
7484
7999
|
});
|
|
7485
8000
|
},
|
|
@@ -7488,7 +8003,7 @@ function AiSectionOverlay({
|
|
|
7488
8003
|
const selectFromElement = (0, import_react8.useCallback)(
|
|
7489
8004
|
(el, options) => {
|
|
7490
8005
|
const sectionEl = el?.closest("[data-ohw-section]") ?? null;
|
|
7491
|
-
const id = sectionEl
|
|
8006
|
+
const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
|
|
7492
8007
|
if (id === selectedIdRef.current) return;
|
|
7493
8008
|
setSelectedId(id);
|
|
7494
8009
|
if (options?.report !== false) report(sectionEl);
|
|
@@ -7529,9 +8044,10 @@ function AiSectionOverlay({
|
|
|
7529
8044
|
}
|
|
7530
8045
|
const found = readRect(sectionId) != null;
|
|
7531
8046
|
setReviewId(found ? sectionId : null);
|
|
8047
|
+
setReviewButtonsHidden(e.data.hideButtons === true);
|
|
7532
8048
|
postToParent2({ type: "ow:ai-review-started", sectionId, found });
|
|
7533
8049
|
if (found) {
|
|
7534
|
-
document.querySelector(`[data-ohw-
|
|
8050
|
+
document.querySelector(`[data-ohw-instance="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
7535
8051
|
}
|
|
7536
8052
|
}
|
|
7537
8053
|
};
|
|
@@ -7550,7 +8066,7 @@ function AiSectionOverlay({
|
|
|
7550
8066
|
return;
|
|
7551
8067
|
}
|
|
7552
8068
|
const sec = t.closest("[data-ohw-section]");
|
|
7553
|
-
setHoveredId(sec
|
|
8069
|
+
setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
|
|
7554
8070
|
};
|
|
7555
8071
|
const onLeave = () => setHoveredId(null);
|
|
7556
8072
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -7582,9 +8098,30 @@ function AiSectionOverlay({
|
|
|
7582
8098
|
},
|
|
7583
8099
|
[postToParent2]
|
|
7584
8100
|
);
|
|
7585
|
-
const
|
|
8101
|
+
const activeSelectionId = reviewId ? null : selectedId;
|
|
8102
|
+
const selectionRect = useLiveSectionRect(activeSelectionId);
|
|
7586
8103
|
const reviewRect = useLiveSectionRect(reviewId);
|
|
7587
8104
|
const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
|
|
8105
|
+
(0, import_react8.useEffect)(() => {
|
|
8106
|
+
const selectedEl = activeSelectionId ? findSectionElement(activeSelectionId) : null;
|
|
8107
|
+
if (!activeSelectionId || !selectionRect || selectedEl && isChromeSection(selectedEl)) {
|
|
8108
|
+
postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
|
|
8109
|
+
return;
|
|
8110
|
+
}
|
|
8111
|
+
const { isFirst, isLast } = computeSectionBoundaryFlags(activeSelectionId);
|
|
8112
|
+
postToParent2({
|
|
8113
|
+
type: "ow:section-rect",
|
|
8114
|
+
instanceId: activeSelectionId,
|
|
8115
|
+
rect: {
|
|
8116
|
+
top: selectionRect.top + window.scrollY,
|
|
8117
|
+
left: selectionRect.left + window.scrollX,
|
|
8118
|
+
width: selectionRect.width,
|
|
8119
|
+
height: selectionRect.height
|
|
8120
|
+
},
|
|
8121
|
+
isFirst,
|
|
8122
|
+
isLast
|
|
8123
|
+
});
|
|
8124
|
+
}, [activeSelectionId, selectionRect, postToParent2]);
|
|
7588
8125
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
7589
8126
|
hoverRect && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
7590
8127
|
"div",
|
|
@@ -7635,13 +8172,16 @@ function AiSectionOverlay({
|
|
|
7635
8172
|
border: `2px solid ${PRIMARY2}`,
|
|
7636
8173
|
borderRadius: edgeAwareRadius(reviewRect),
|
|
7637
8174
|
zIndex: 2147483200,
|
|
7638
|
-
// The veil itself: swallows clicks so the section stays locked until decided.
|
|
8175
|
+
// The veil itself: swallows clicks so the section stays locked until decided. This
|
|
8176
|
+
// stopPropagation only guards the bubble phase; the bridge's capture-phase click
|
|
8177
|
+
// handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
|
|
8178
|
+
// Accept/Discard resolves to the media beneath and opens the file picker.
|
|
7639
8179
|
background: "rgba(8, 133, 254, 0.04)",
|
|
7640
8180
|
pointerEvents: "auto",
|
|
7641
8181
|
cursor: "default"
|
|
7642
8182
|
},
|
|
7643
8183
|
onClick: (e) => e.stopPropagation(),
|
|
7644
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
8184
|
+
children: !reviewButtonsHidden && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
7645
8185
|
"div",
|
|
7646
8186
|
{
|
|
7647
8187
|
style: {
|
|
@@ -7666,6 +8206,59 @@ function AiSectionOverlay({
|
|
|
7666
8206
|
|
|
7667
8207
|
// src/lib/section-instances.ts
|
|
7668
8208
|
var SECTION_ORDER_KEY = "__ohw_section_order";
|
|
8209
|
+
function topLevelSections() {
|
|
8210
|
+
return Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
8211
|
+
(el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
|
|
8212
|
+
);
|
|
8213
|
+
}
|
|
8214
|
+
function instanceIdOf(el) {
|
|
8215
|
+
return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
|
|
8216
|
+
}
|
|
8217
|
+
function planSectionMove(instanceId, targetIndex, currentPath) {
|
|
8218
|
+
const sections = topLevelSections();
|
|
8219
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8220
|
+
if (index === -1) return null;
|
|
8221
|
+
const dragged = sections[index];
|
|
8222
|
+
const others = sections.filter((_, i) => i !== index);
|
|
8223
|
+
const clamped = Math.max(0, Math.min(targetIndex, others.length));
|
|
8224
|
+
const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
|
|
8225
|
+
return reordered.map((el, order) => ({
|
|
8226
|
+
instanceId: instanceIdOf(el),
|
|
8227
|
+
type: el.getAttribute("data-ohw-section") ?? "",
|
|
8228
|
+
order,
|
|
8229
|
+
pagePath: currentPath
|
|
8230
|
+
}));
|
|
8231
|
+
}
|
|
8232
|
+
function moveSectionInstance(instanceId, direction, currentPath) {
|
|
8233
|
+
const sections = topLevelSections();
|
|
8234
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8235
|
+
if (index === -1) return null;
|
|
8236
|
+
const siblingIndex = direction === "up" ? index - 1 : index + 1;
|
|
8237
|
+
if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
|
|
8238
|
+
const entries = planSectionMove(instanceId, siblingIndex, currentPath);
|
|
8239
|
+
if (!entries) return null;
|
|
8240
|
+
applyPersistedOrder(entries);
|
|
8241
|
+
return entries;
|
|
8242
|
+
}
|
|
8243
|
+
function applyPersistedOrder(entries) {
|
|
8244
|
+
if (entries.length === 0) return;
|
|
8245
|
+
const sections = topLevelSections();
|
|
8246
|
+
if (sections.length === 0) return;
|
|
8247
|
+
const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
|
|
8248
|
+
const ordered = [...sections].sort((a, b) => {
|
|
8249
|
+
const aOrder = orderIndex.get(instanceIdOf(a));
|
|
8250
|
+
const bOrder = orderIndex.get(instanceIdOf(b));
|
|
8251
|
+
if (aOrder === void 0 && bOrder === void 0) return 0;
|
|
8252
|
+
if (aOrder === void 0) return 1;
|
|
8253
|
+
if (bOrder === void 0) return -1;
|
|
8254
|
+
return aOrder - bOrder;
|
|
8255
|
+
});
|
|
8256
|
+
let prev = null;
|
|
8257
|
+
for (const el of ordered) {
|
|
8258
|
+
if (prev) prev.after(el);
|
|
8259
|
+
prev = el;
|
|
8260
|
+
}
|
|
8261
|
+
}
|
|
7669
8262
|
function getPageSectionOrderEntries(raw, currentPath) {
|
|
7670
8263
|
if (!raw) return [];
|
|
7671
8264
|
try {
|
|
@@ -7703,6 +8296,7 @@ function initSectionInstancesFromContent(content, currentPath) {
|
|
|
7703
8296
|
rekeySectionSubtree(clone, entry.instanceId);
|
|
7704
8297
|
original.insertAdjacentElement("afterend", clone);
|
|
7705
8298
|
}
|
|
8299
|
+
applyPersistedOrder(entries);
|
|
7706
8300
|
}
|
|
7707
8301
|
|
|
7708
8302
|
// src/OhhwellsBridge.tsx
|
|
@@ -10247,8 +10841,13 @@ var GLYPH_SELECTOR = "svg, img";
|
|
|
10247
10841
|
function referenceBox(slot) {
|
|
10248
10842
|
const row = slot.closest("[data-ohw-socials-row]") ?? slot.closest("a")?.parentElement ?? null;
|
|
10249
10843
|
const neighbour = row ? Array.from(row.querySelectorAll('[data-ohw-editable="icon"]')).find((el) => el !== slot) : null;
|
|
10250
|
-
|
|
10251
|
-
|
|
10844
|
+
if (neighbour) {
|
|
10845
|
+
const box2 = neighbour.querySelector(GLYPH_SELECTOR)?.getBoundingClientRect();
|
|
10846
|
+
if (box2?.width && box2.height) return box2;
|
|
10847
|
+
}
|
|
10848
|
+
const own = slot.getBoundingClientRect();
|
|
10849
|
+
if (own.width && own.height) return own;
|
|
10850
|
+
const box = slot.querySelector(GLYPH_SELECTOR)?.getBoundingClientRect() ?? null;
|
|
10252
10851
|
return box?.width && box.height ? box : null;
|
|
10253
10852
|
}
|
|
10254
10853
|
function iconMarkupSizedFor(slot, markup) {
|
|
@@ -10327,7 +10926,8 @@ function findSocialsRow(el) {
|
|
|
10327
10926
|
}
|
|
10328
10927
|
function isSocialsRow(el) {
|
|
10329
10928
|
const anchors = Array.from(el.querySelectorAll("a"));
|
|
10330
|
-
|
|
10929
|
+
if (!anchors.length || !anchors.some((anchor) => isSocialItem(anchor))) return false;
|
|
10930
|
+
return findSocialsRow(anchors[0]) === el;
|
|
10331
10931
|
}
|
|
10332
10932
|
var MAX_SOCIAL_ITEMS_PER_ROW = 7;
|
|
10333
10933
|
function canAddSocialItem(row) {
|
|
@@ -10365,6 +10965,7 @@ function markSocialsRows(root = document) {
|
|
|
10365
10965
|
});
|
|
10366
10966
|
listSocialsRows(root).forEach((row) => {
|
|
10367
10967
|
row.setAttribute(SOCIALS_ROW_ATTR, "");
|
|
10968
|
+
allowRowToWrap(row);
|
|
10368
10969
|
const items = listSocialItems(row);
|
|
10369
10970
|
const firstUnit = items[0] ? socialRowUnit(items[0], row) : null;
|
|
10370
10971
|
if (firstUnit) rowTemplates.set(rowKeyOf(row), firstUnit.outerHTML);
|
|
@@ -10659,7 +11260,29 @@ function applySocialsDisplayToRow(row, display) {
|
|
|
10659
11260
|
const icon = item.querySelector(ICON_SELECTOR);
|
|
10660
11261
|
if (label) label.style.display = display.text ? "" : "none";
|
|
10661
11262
|
if (icon) icon.style.display = display.icon ? "" : "none";
|
|
11263
|
+
layOutIconAndLabel(item, Boolean(display.text && display.icon));
|
|
10662
11264
|
});
|
|
11265
|
+
allowRowToWrap(row);
|
|
11266
|
+
}
|
|
11267
|
+
function layOutIconAndLabel(item, on) {
|
|
11268
|
+
const hasBoth = Boolean(item.querySelector(ICON_SELECTOR)) && Boolean(socialLabelElement(item));
|
|
11269
|
+
if (!hasBoth) {
|
|
11270
|
+
item.style.display = "";
|
|
11271
|
+
item.style.alignItems = "";
|
|
11272
|
+
item.style.gap = "";
|
|
11273
|
+
item.style.whiteSpace = "";
|
|
11274
|
+
item.style.flex = "";
|
|
11275
|
+
return;
|
|
11276
|
+
}
|
|
11277
|
+
item.style.display = on ? "inline-flex" : "";
|
|
11278
|
+
item.style.alignItems = on ? "center" : "";
|
|
11279
|
+
item.style.gap = on ? "8px" : "";
|
|
11280
|
+
item.style.whiteSpace = on ? "nowrap" : "";
|
|
11281
|
+
item.style.flex = on ? "0 0 auto" : "";
|
|
11282
|
+
}
|
|
11283
|
+
function allowRowToWrap(row) {
|
|
11284
|
+
const display = row.ownerDocument.defaultView?.getComputedStyle(row).display ?? "";
|
|
11285
|
+
if (display === "flex" || display === "inline-flex") row.style.flexWrap = "wrap";
|
|
10663
11286
|
}
|
|
10664
11287
|
function applySocialsDisplayFromContent(content, root = document) {
|
|
10665
11288
|
const stored = parseSocialsDisplay(content[SOCIALS_DISPLAY_KEY]);
|
|
@@ -11869,6 +12492,7 @@ function readLogoSizeState(content, placement) {
|
|
|
11869
12492
|
function getLogoElement(el) {
|
|
11870
12493
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
11871
12494
|
if (marked) return marked;
|
|
12495
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
11872
12496
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
11873
12497
|
if (!root) return null;
|
|
11874
12498
|
const anchor = el.closest("a");
|
|
@@ -12742,98 +13366,425 @@ function useNavItemDrag({
|
|
|
12742
13366
|
};
|
|
12743
13367
|
}
|
|
12744
13368
|
|
|
12745
|
-
// src/
|
|
12746
|
-
var import_lucide_react15 = require("lucide-react");
|
|
12747
|
-
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
12748
|
-
function FooterContainerChrome({
|
|
12749
|
-
rect,
|
|
12750
|
-
onAdd,
|
|
12751
|
-
addDisabled = false
|
|
12752
|
-
}) {
|
|
12753
|
-
const chromeGap = 6;
|
|
12754
|
-
const buttonMargin = 7;
|
|
12755
|
-
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
12756
|
-
"div",
|
|
12757
|
-
{
|
|
12758
|
-
"data-ohw-footer-container-chrome": "",
|
|
12759
|
-
"data-ohw-bridge": "",
|
|
12760
|
-
className: "pointer-events-none fixed z-[2147483647]",
|
|
12761
|
-
style: {
|
|
12762
|
-
top: rect.top - chromeGap,
|
|
12763
|
-
left: rect.left - chromeGap,
|
|
12764
|
-
width: rect.width + chromeGap * 2,
|
|
12765
|
-
height: rect.height + chromeGap * 2
|
|
12766
|
-
},
|
|
12767
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(Tooltip, { children: [
|
|
12768
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
12769
|
-
"button",
|
|
12770
|
-
{
|
|
12771
|
-
type: "button",
|
|
12772
|
-
"data-ohw-footer-add-button": "",
|
|
12773
|
-
disabled: addDisabled,
|
|
12774
|
-
className: "pointer-events-auto absolute left-1/2 flex size-7 -translate-x-1/2 -translate-y-full items-center justify-center rounded-[10px] border border-border bg-background p-0.5 shadow-sm transition-colors hover:bg-muted/80 disabled:pointer-events-none disabled:opacity-40",
|
|
12775
|
-
style: { top: chromeGap - buttonMargin },
|
|
12776
|
-
"aria-label": "Add item",
|
|
12777
|
-
onMouseDown: (e) => {
|
|
12778
|
-
e.preventDefault();
|
|
12779
|
-
e.stopPropagation();
|
|
12780
|
-
},
|
|
12781
|
-
onClick: (e) => {
|
|
12782
|
-
e.preventDefault();
|
|
12783
|
-
e.stopPropagation();
|
|
12784
|
-
if (addDisabled) return;
|
|
12785
|
-
onAdd();
|
|
12786
|
-
},
|
|
12787
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
12788
|
-
}
|
|
12789
|
-
) }),
|
|
12790
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
12791
|
-
] })
|
|
12792
|
-
}
|
|
12793
|
-
) });
|
|
12794
|
-
}
|
|
12795
|
-
|
|
12796
|
-
// src/lib/carousel.ts
|
|
13369
|
+
// src/useSectionDrag.ts
|
|
12797
13370
|
var import_react15 = require("react");
|
|
12798
|
-
|
|
12799
|
-
|
|
12800
|
-
|
|
12801
|
-
|
|
12802
|
-
function listCarouselKeys() {
|
|
12803
|
-
const keys = /* @__PURE__ */ new Set();
|
|
12804
|
-
document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
|
|
12805
|
-
const key = el.getAttribute("data-ohw-key");
|
|
12806
|
-
if (key) keys.add(key);
|
|
12807
|
-
});
|
|
12808
|
-
return [...keys];
|
|
13371
|
+
|
|
13372
|
+
// src/lib/section-dnd.ts
|
|
13373
|
+
function isFooterSection(el) {
|
|
13374
|
+
return el.dataset.ohwSection === "footer";
|
|
12809
13375
|
}
|
|
12810
|
-
function
|
|
12811
|
-
|
|
12812
|
-
|
|
13376
|
+
function buildSectionDropSlots(draggedInstanceId) {
|
|
13377
|
+
const sections = topLevelSections().filter(
|
|
13378
|
+
(el) => instanceIdOf(el) !== draggedInstanceId && !isFooterSection(el)
|
|
12813
13379
|
);
|
|
13380
|
+
const slots = [];
|
|
13381
|
+
if (sections.length === 0) return slots;
|
|
13382
|
+
const left = 0;
|
|
13383
|
+
const width = document.documentElement.clientWidth;
|
|
13384
|
+
for (let i = 0; i <= sections.length; i++) {
|
|
13385
|
+
let y;
|
|
13386
|
+
if (i === 0) {
|
|
13387
|
+
y = sections[0].getBoundingClientRect().top;
|
|
13388
|
+
} else if (i === sections.length) {
|
|
13389
|
+
y = sections[sections.length - 1].getBoundingClientRect().bottom;
|
|
13390
|
+
} else {
|
|
13391
|
+
const prev = sections[i - 1].getBoundingClientRect();
|
|
13392
|
+
const next = sections[i].getBoundingClientRect();
|
|
13393
|
+
y = (prev.bottom + next.top) / 2;
|
|
13394
|
+
}
|
|
13395
|
+
slots.push({ insertIndex: i, y, left, width });
|
|
13396
|
+
}
|
|
13397
|
+
return slots;
|
|
12814
13398
|
}
|
|
12815
|
-
function
|
|
12816
|
-
|
|
12817
|
-
|
|
12818
|
-
|
|
12819
|
-
|
|
12820
|
-
try {
|
|
12821
|
-
const parsed = JSON.parse(raw);
|
|
12822
|
-
if (!Array.isArray(parsed)) return [];
|
|
12823
|
-
return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
|
|
12824
|
-
} catch {
|
|
12825
|
-
return [];
|
|
13399
|
+
function hitTestSectionDropSlot(y, slots) {
|
|
13400
|
+
let best = null;
|
|
13401
|
+
for (const slot of slots) {
|
|
13402
|
+
const dist = Math.abs(y - slot.y);
|
|
13403
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
12826
13404
|
}
|
|
13405
|
+
return best?.slot ?? null;
|
|
12827
13406
|
}
|
|
12828
|
-
|
|
12829
|
-
|
|
12830
|
-
|
|
12831
|
-
|
|
12832
|
-
|
|
12833
|
-
|
|
12834
|
-
|
|
12835
|
-
|
|
12836
|
-
|
|
13407
|
+
|
|
13408
|
+
// src/useSectionDrag.ts
|
|
13409
|
+
var PRESS_THRESHOLD = 10;
|
|
13410
|
+
var EDGE_ZONE = 60;
|
|
13411
|
+
var MAX_AUTO_SCROLL_SPEED = 18;
|
|
13412
|
+
var SECTION_DRAG_EXCLUDED_SELECTOR = [
|
|
13413
|
+
"[data-ohw-toolbar]",
|
|
13414
|
+
"[data-ohw-edit-chrome]",
|
|
13415
|
+
"[data-ohw-item-interaction]",
|
|
13416
|
+
"[data-ohw-drag-handle-container]",
|
|
13417
|
+
'[data-slot="drag-handle"]',
|
|
13418
|
+
"[data-ohw-item-toolbar-anchor]",
|
|
13419
|
+
"[data-ohw-item-drag-surface]",
|
|
13420
|
+
"[data-ohw-more-menu]",
|
|
13421
|
+
'[data-slot="dropdown-menu-content"]',
|
|
13422
|
+
'[data-slot="dropdown-menu-item"]',
|
|
13423
|
+
"[data-ohw-state-toggle]",
|
|
13424
|
+
"[data-ohw-max-badge]",
|
|
13425
|
+
"[data-ohw-floating-panel]",
|
|
13426
|
+
"[data-ohw-section-picker]",
|
|
13427
|
+
"[data-ohw-link-popover-root]",
|
|
13428
|
+
"[data-ohw-link-modal-root]",
|
|
13429
|
+
"[data-ohw-link-page-dropdown]",
|
|
13430
|
+
'[data-slot="popover-content"]',
|
|
13431
|
+
'[data-slot="dialog-content"]',
|
|
13432
|
+
'[data-slot="dialog-overlay"]',
|
|
13433
|
+
"[data-ohw-ai-review]",
|
|
13434
|
+
"[data-ohw-editable]",
|
|
13435
|
+
"[data-ohw-editable-state]",
|
|
13436
|
+
"[contenteditable]",
|
|
13437
|
+
"[data-ohw-href-key]",
|
|
13438
|
+
"[data-ohw-footer-col]",
|
|
13439
|
+
"[data-ohw-social-label]",
|
|
13440
|
+
"a",
|
|
13441
|
+
"button",
|
|
13442
|
+
'[role="button"]',
|
|
13443
|
+
'[data-ohw-role="navbar-button"]',
|
|
13444
|
+
'[data-ohw-role="button"]',
|
|
13445
|
+
"[data-ohw-carousel]",
|
|
13446
|
+
"[data-ohw-carousel-value]",
|
|
13447
|
+
"[data-ohw-carousel-slide]",
|
|
13448
|
+
"[data-ohw-carousel-overlay]",
|
|
13449
|
+
"[data-ohw-media-chrome]",
|
|
13450
|
+
"[data-ohw-media-overlay]",
|
|
13451
|
+
"[data-ohw-media-skeleton]"
|
|
13452
|
+
].join(", ");
|
|
13453
|
+
function visibleClip(ps) {
|
|
13454
|
+
if (!ps) return null;
|
|
13455
|
+
const top = Math.max(0, ps.headerH - ps.iframeOffsetTop);
|
|
13456
|
+
const bottom = Math.min(window.innerHeight, ps.headerH + ps.canvasH - ps.iframeOffsetTop);
|
|
13457
|
+
return { top, bottom: Math.max(top, bottom) };
|
|
13458
|
+
}
|
|
13459
|
+
function useSectionDrag({
|
|
13460
|
+
isEditMode,
|
|
13461
|
+
editContentRef,
|
|
13462
|
+
postToParentRef,
|
|
13463
|
+
parentScrollRef,
|
|
13464
|
+
navDragRef,
|
|
13465
|
+
footerDragRef,
|
|
13466
|
+
suppressNextClickRef,
|
|
13467
|
+
suppressClickUntilRef
|
|
13468
|
+
}) {
|
|
13469
|
+
const sectionDragRef = (0, import_react15.useRef)(null);
|
|
13470
|
+
const [sectionDropSlots, setSectionDropSlots] = (0, import_react15.useState)([]);
|
|
13471
|
+
const [activeSectionDropIndex, setActiveSectionDropIndex] = (0, import_react15.useState)(null);
|
|
13472
|
+
const [isSectionDragging, setIsSectionDragging] = (0, import_react15.useState)(false);
|
|
13473
|
+
const sectionPointerDragRef = (0, import_react15.useRef)(null);
|
|
13474
|
+
const autoScrollRafRef = (0, import_react15.useRef)(null);
|
|
13475
|
+
const autoScrollDeltaRef = (0, import_react15.useRef)(0);
|
|
13476
|
+
const stopAutoScroll = (0, import_react15.useCallback)(() => {
|
|
13477
|
+
if (autoScrollRafRef.current != null) {
|
|
13478
|
+
cancelAnimationFrame(autoScrollRafRef.current);
|
|
13479
|
+
autoScrollRafRef.current = null;
|
|
13480
|
+
}
|
|
13481
|
+
autoScrollDeltaRef.current = 0;
|
|
13482
|
+
}, []);
|
|
13483
|
+
const tickAutoScroll = (0, import_react15.useCallback)(() => {
|
|
13484
|
+
if (!sectionDragRef.current) {
|
|
13485
|
+
stopAutoScroll();
|
|
13486
|
+
return;
|
|
13487
|
+
}
|
|
13488
|
+
if (autoScrollDeltaRef.current !== 0) {
|
|
13489
|
+
postToParentRef.current({ type: "ow:request-scroll", deltaY: autoScrollDeltaRef.current });
|
|
13490
|
+
}
|
|
13491
|
+
autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
|
|
13492
|
+
}, [postToParentRef, stopAutoScroll]);
|
|
13493
|
+
const updateAutoScroll = (0, import_react15.useCallback)(
|
|
13494
|
+
(clientY) => {
|
|
13495
|
+
const clip = visibleClip(parentScrollRef.current);
|
|
13496
|
+
let delta = 0;
|
|
13497
|
+
if (clip) {
|
|
13498
|
+
const distTop = clientY - clip.top;
|
|
13499
|
+
const distBottom = clip.bottom - clientY;
|
|
13500
|
+
if (distTop >= 0 && distTop < EDGE_ZONE) {
|
|
13501
|
+
delta = -MAX_AUTO_SCROLL_SPEED * (1 - distTop / EDGE_ZONE);
|
|
13502
|
+
} else if (distBottom >= 0 && distBottom < EDGE_ZONE) {
|
|
13503
|
+
delta = MAX_AUTO_SCROLL_SPEED * (1 - distBottom / EDGE_ZONE);
|
|
13504
|
+
}
|
|
13505
|
+
}
|
|
13506
|
+
autoScrollDeltaRef.current = delta;
|
|
13507
|
+
if (delta !== 0 && autoScrollRafRef.current == null) {
|
|
13508
|
+
autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
|
|
13509
|
+
} else if (delta === 0) {
|
|
13510
|
+
stopAutoScroll();
|
|
13511
|
+
}
|
|
13512
|
+
},
|
|
13513
|
+
[parentScrollRef, stopAutoScroll, tickAutoScroll]
|
|
13514
|
+
);
|
|
13515
|
+
const clearSectionDragVisuals = (0, import_react15.useCallback)(() => {
|
|
13516
|
+
sectionDragRef.current?.draggedEl.removeAttribute("data-ohw-section-dragging");
|
|
13517
|
+
sectionDragRef.current = null;
|
|
13518
|
+
setSectionDropSlots([]);
|
|
13519
|
+
setActiveSectionDropIndex(null);
|
|
13520
|
+
setIsSectionDragging(false);
|
|
13521
|
+
stopAutoScroll();
|
|
13522
|
+
document.documentElement.removeAttribute("data-ohw-section-dragging-root");
|
|
13523
|
+
unlockItemDragInteraction();
|
|
13524
|
+
}, [stopAutoScroll]);
|
|
13525
|
+
const refreshSectionDragVisuals = (0, import_react15.useCallback)(
|
|
13526
|
+
(session, clientX, clientY) => {
|
|
13527
|
+
session.lastClientX = clientX;
|
|
13528
|
+
session.lastClientY = clientY;
|
|
13529
|
+
const slots = buildSectionDropSlots(session.instanceId);
|
|
13530
|
+
const activeSlot = hitTestSectionDropSlot(clientY, slots);
|
|
13531
|
+
session.activeSlot = activeSlot;
|
|
13532
|
+
setSectionDropSlots(slots);
|
|
13533
|
+
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
13534
|
+
setActiveSectionDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
13535
|
+
updateAutoScroll(clientY);
|
|
13536
|
+
},
|
|
13537
|
+
[updateAutoScroll]
|
|
13538
|
+
);
|
|
13539
|
+
const beginSectionDrag = (0, import_react15.useCallback)(
|
|
13540
|
+
(session) => {
|
|
13541
|
+
sectionDragRef.current = session;
|
|
13542
|
+
setIsSectionDragging(true);
|
|
13543
|
+
lockItemDuringDrag();
|
|
13544
|
+
document.documentElement.setAttribute("data-ohw-section-dragging-root", "");
|
|
13545
|
+
session.draggedEl.setAttribute("data-ohw-section-dragging", "");
|
|
13546
|
+
refreshSectionDragVisuals(session, session.lastClientX, session.lastClientY);
|
|
13547
|
+
},
|
|
13548
|
+
[refreshSectionDragVisuals]
|
|
13549
|
+
);
|
|
13550
|
+
const commitSectionDrag = (0, import_react15.useCallback)(() => {
|
|
13551
|
+
const session = sectionDragRef.current;
|
|
13552
|
+
if (!session) {
|
|
13553
|
+
clearSectionDragVisuals();
|
|
13554
|
+
return;
|
|
13555
|
+
}
|
|
13556
|
+
const slot = session.activeSlot ?? hitTestSectionDropSlot(session.lastClientY, buildSectionDropSlots(session.instanceId));
|
|
13557
|
+
const entries = slot ? planSectionMove(session.instanceId, slot.insertIndex, window.location.pathname) : null;
|
|
13558
|
+
if (!entries) {
|
|
13559
|
+
clearSectionDragVisuals();
|
|
13560
|
+
return;
|
|
13561
|
+
}
|
|
13562
|
+
const orderJson = JSON.stringify(entries);
|
|
13563
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
13564
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
13565
|
+
applyPersistedOrder(entries);
|
|
13566
|
+
clearSectionDragVisuals();
|
|
13567
|
+
requestAnimationFrame(() => {
|
|
13568
|
+
if (editContentRef.current[SECTION_ORDER_KEY] === orderJson) {
|
|
13569
|
+
applyPersistedOrder(entries);
|
|
13570
|
+
}
|
|
13571
|
+
requestAnimationFrame(() => {
|
|
13572
|
+
window.dispatchEvent(new Event("resize"));
|
|
13573
|
+
});
|
|
13574
|
+
});
|
|
13575
|
+
}, [clearSectionDragVisuals, editContentRef, postToParentRef]);
|
|
13576
|
+
const startSectionPressDrag = (0, import_react15.useCallback)(
|
|
13577
|
+
(el, clientX, clientY, pointerId) => {
|
|
13578
|
+
if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return false;
|
|
13579
|
+
const instanceId = instanceIdOf(el);
|
|
13580
|
+
if (!instanceId) return false;
|
|
13581
|
+
sectionPointerDragRef.current = {
|
|
13582
|
+
el,
|
|
13583
|
+
instanceId,
|
|
13584
|
+
startX: clientX,
|
|
13585
|
+
startY: clientY,
|
|
13586
|
+
pointerId,
|
|
13587
|
+
started: false
|
|
13588
|
+
};
|
|
13589
|
+
return true;
|
|
13590
|
+
},
|
|
13591
|
+
[footerDragRef, navDragRef]
|
|
13592
|
+
);
|
|
13593
|
+
(0, import_react15.useEffect)(() => {
|
|
13594
|
+
if (!isEditMode) return;
|
|
13595
|
+
const onPointerDown = (e) => {
|
|
13596
|
+
if (e.button !== 0) return;
|
|
13597
|
+
if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return;
|
|
13598
|
+
if (sectionPointerDragRef.current) return;
|
|
13599
|
+
const target = e.target;
|
|
13600
|
+
if (!(target instanceof HTMLElement)) return;
|
|
13601
|
+
if (target.closest(SECTION_DRAG_EXCLUDED_SELECTOR)) return;
|
|
13602
|
+
const sectionEl = target.closest("[data-ohw-section]");
|
|
13603
|
+
if (!sectionEl || isChromeSection(sectionEl) || sectionEl.dataset.ohwSection === "footer") return;
|
|
13604
|
+
if (!topLevelSections().includes(sectionEl)) return;
|
|
13605
|
+
startSectionPressDrag(sectionEl, e.clientX, e.clientY, e.pointerId);
|
|
13606
|
+
};
|
|
13607
|
+
const onPointerMove = (e) => {
|
|
13608
|
+
const pending = sectionPointerDragRef.current;
|
|
13609
|
+
if (!pending) return;
|
|
13610
|
+
if (pending.started) {
|
|
13611
|
+
e.preventDefault();
|
|
13612
|
+
clearTextSelection();
|
|
13613
|
+
const session = sectionDragRef.current;
|
|
13614
|
+
if (!session) return;
|
|
13615
|
+
refreshSectionDragVisuals(session, e.clientX, e.clientY);
|
|
13616
|
+
return;
|
|
13617
|
+
}
|
|
13618
|
+
const dx = e.clientX - pending.startX;
|
|
13619
|
+
const dy = e.clientY - pending.startY;
|
|
13620
|
+
if (dx * dx + dy * dy < PRESS_THRESHOLD * PRESS_THRESHOLD) return;
|
|
13621
|
+
e.preventDefault();
|
|
13622
|
+
pending.started = true;
|
|
13623
|
+
armItemPressDrag();
|
|
13624
|
+
clearTextSelection();
|
|
13625
|
+
try {
|
|
13626
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
13627
|
+
} catch {
|
|
13628
|
+
}
|
|
13629
|
+
beginSectionDrag({
|
|
13630
|
+
instanceId: pending.instanceId,
|
|
13631
|
+
draggedEl: pending.el,
|
|
13632
|
+
lastClientX: e.clientX,
|
|
13633
|
+
lastClientY: e.clientY,
|
|
13634
|
+
activeSlot: null
|
|
13635
|
+
});
|
|
13636
|
+
};
|
|
13637
|
+
const endPointerDrag = (e) => {
|
|
13638
|
+
const pending = sectionPointerDragRef.current;
|
|
13639
|
+
sectionPointerDragRef.current = null;
|
|
13640
|
+
try {
|
|
13641
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
13642
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
13643
|
+
}
|
|
13644
|
+
} catch {
|
|
13645
|
+
}
|
|
13646
|
+
if (!pending) return;
|
|
13647
|
+
if (!pending.started) {
|
|
13648
|
+
unlockItemDragInteraction();
|
|
13649
|
+
return;
|
|
13650
|
+
}
|
|
13651
|
+
suppressNextClickRef.current = true;
|
|
13652
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
13653
|
+
commitSectionDrag();
|
|
13654
|
+
};
|
|
13655
|
+
const onKeyDown = (e) => {
|
|
13656
|
+
if (e.key !== "Escape") return;
|
|
13657
|
+
if (!sectionDragRef.current && !sectionPointerDragRef.current) return;
|
|
13658
|
+
sectionPointerDragRef.current = null;
|
|
13659
|
+
clearSectionDragVisuals();
|
|
13660
|
+
};
|
|
13661
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
13662
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
13663
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
13664
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
13665
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
13666
|
+
return () => {
|
|
13667
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
13668
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
13669
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
13670
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
13671
|
+
document.removeEventListener("keydown", onKeyDown, true);
|
|
13672
|
+
unlockItemDragInteraction();
|
|
13673
|
+
stopAutoScroll();
|
|
13674
|
+
};
|
|
13675
|
+
}, [
|
|
13676
|
+
beginSectionDrag,
|
|
13677
|
+
clearSectionDragVisuals,
|
|
13678
|
+
commitSectionDrag,
|
|
13679
|
+
footerDragRef,
|
|
13680
|
+
isEditMode,
|
|
13681
|
+
navDragRef,
|
|
13682
|
+
refreshSectionDragVisuals,
|
|
13683
|
+
startSectionPressDrag,
|
|
13684
|
+
stopAutoScroll,
|
|
13685
|
+
suppressClickUntilRef,
|
|
13686
|
+
suppressNextClickRef
|
|
13687
|
+
]);
|
|
13688
|
+
return {
|
|
13689
|
+
sectionDragRef,
|
|
13690
|
+
sectionDropSlots,
|
|
13691
|
+
activeSectionDropIndex,
|
|
13692
|
+
isSectionDragging
|
|
13693
|
+
};
|
|
13694
|
+
}
|
|
13695
|
+
|
|
13696
|
+
// src/ui/footer-container-chrome.tsx
|
|
13697
|
+
var import_lucide_react15 = require("lucide-react");
|
|
13698
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
13699
|
+
function FooterContainerChrome({
|
|
13700
|
+
rect,
|
|
13701
|
+
onAdd,
|
|
13702
|
+
addDisabled = false
|
|
13703
|
+
}) {
|
|
13704
|
+
const chromeGap = 6;
|
|
13705
|
+
const buttonMargin = 7;
|
|
13706
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
13707
|
+
"div",
|
|
13708
|
+
{
|
|
13709
|
+
"data-ohw-footer-container-chrome": "",
|
|
13710
|
+
"data-ohw-bridge": "",
|
|
13711
|
+
className: "pointer-events-none fixed z-[2147483647]",
|
|
13712
|
+
style: {
|
|
13713
|
+
top: rect.top - chromeGap,
|
|
13714
|
+
left: rect.left - chromeGap,
|
|
13715
|
+
width: rect.width + chromeGap * 2,
|
|
13716
|
+
height: rect.height + chromeGap * 2
|
|
13717
|
+
},
|
|
13718
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(Tooltip, { children: [
|
|
13719
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
13720
|
+
"button",
|
|
13721
|
+
{
|
|
13722
|
+
type: "button",
|
|
13723
|
+
"data-ohw-footer-add-button": "",
|
|
13724
|
+
disabled: addDisabled,
|
|
13725
|
+
className: "pointer-events-auto absolute left-1/2 flex size-7 -translate-x-1/2 -translate-y-full items-center justify-center rounded-[10px] border border-border bg-background p-0.5 shadow-sm transition-colors hover:bg-muted/80 disabled:pointer-events-none disabled:opacity-40",
|
|
13726
|
+
style: { top: chromeGap - buttonMargin },
|
|
13727
|
+
"aria-label": "Add item",
|
|
13728
|
+
onMouseDown: (e) => {
|
|
13729
|
+
e.preventDefault();
|
|
13730
|
+
e.stopPropagation();
|
|
13731
|
+
},
|
|
13732
|
+
onClick: (e) => {
|
|
13733
|
+
e.preventDefault();
|
|
13734
|
+
e.stopPropagation();
|
|
13735
|
+
if (addDisabled) return;
|
|
13736
|
+
onAdd();
|
|
13737
|
+
},
|
|
13738
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
13739
|
+
}
|
|
13740
|
+
) }),
|
|
13741
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
13742
|
+
] })
|
|
13743
|
+
}
|
|
13744
|
+
) });
|
|
13745
|
+
}
|
|
13746
|
+
|
|
13747
|
+
// src/lib/carousel.ts
|
|
13748
|
+
var import_react16 = require("react");
|
|
13749
|
+
var CAROUSEL_ATTR = "data-ohw-carousel";
|
|
13750
|
+
var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
|
|
13751
|
+
var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
|
|
13752
|
+
var CAROUSEL_EVENT = "ohw:carousel-change";
|
|
13753
|
+
function listCarouselKeys() {
|
|
13754
|
+
const keys = /* @__PURE__ */ new Set();
|
|
13755
|
+
document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
|
|
13756
|
+
const key = el.getAttribute("data-ohw-key");
|
|
13757
|
+
if (key) keys.add(key);
|
|
13758
|
+
});
|
|
13759
|
+
return [...keys];
|
|
13760
|
+
}
|
|
13761
|
+
function containersForKey(key) {
|
|
13762
|
+
return Array.from(
|
|
13763
|
+
document.querySelectorAll(`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`)
|
|
13764
|
+
);
|
|
13765
|
+
}
|
|
13766
|
+
function isCarouselKey(key) {
|
|
13767
|
+
return containersForKey(key).length > 0;
|
|
13768
|
+
}
|
|
13769
|
+
function parseSlides(raw) {
|
|
13770
|
+
if (!raw) return [];
|
|
13771
|
+
try {
|
|
13772
|
+
const parsed = JSON.parse(raw);
|
|
13773
|
+
if (!Array.isArray(parsed)) return [];
|
|
13774
|
+
return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
|
|
13775
|
+
} catch {
|
|
13776
|
+
return [];
|
|
13777
|
+
}
|
|
13778
|
+
}
|
|
13779
|
+
function readCarouselValue(key) {
|
|
13780
|
+
const container = containersForKey(key)[0];
|
|
13781
|
+
if (!container) return [];
|
|
13782
|
+
const fromAttr = parseSlides(container.getAttribute(CAROUSEL_VALUE_ATTR));
|
|
13783
|
+
if (fromAttr.length > 0) return fromAttr;
|
|
13784
|
+
return Array.from(container.querySelectorAll(`[${CAROUSEL_SLIDE_ATTR}]`)).filter((slide) => slide.closest(`[${CAROUSEL_ATTR}]`) === container).sort((a, b) => slideIndex(a) - slideIndex(b)).map((slide) => {
|
|
13785
|
+
const img = slide instanceof HTMLImageElement ? slide : slide.querySelector("img");
|
|
13786
|
+
return { src: img?.src ?? "", alt: img?.alt ?? "" };
|
|
13787
|
+
});
|
|
12837
13788
|
}
|
|
12838
13789
|
function slideIndex(el) {
|
|
12839
13790
|
const raw = el.getAttribute(CAROUSEL_SLIDE_ATTR);
|
|
@@ -12856,8 +13807,8 @@ function applyCarouselNode(key, val) {
|
|
|
12856
13807
|
return true;
|
|
12857
13808
|
}
|
|
12858
13809
|
function useOhwCarousel(key, initial) {
|
|
12859
|
-
const [images, setImages] = (0,
|
|
12860
|
-
(0,
|
|
13810
|
+
const [images, setImages] = (0, import_react16.useState)(initial);
|
|
13811
|
+
(0, import_react16.useEffect)(() => {
|
|
12861
13812
|
const el = document.querySelector(
|
|
12862
13813
|
`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
|
|
12863
13814
|
);
|
|
@@ -12935,7 +13886,7 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
12935
13886
|
nodes.push({ key, type: "link", text: href });
|
|
12936
13887
|
}
|
|
12937
13888
|
if (extraContent) {
|
|
12938
|
-
for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
|
|
13889
|
+
for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY, SECTION_ORDER_KEY]) {
|
|
12939
13890
|
const text = extraContent[key];
|
|
12940
13891
|
if (typeof text === "string" && text.length > 0) {
|
|
12941
13892
|
nodes.push({ key, type: "meta", text });
|
|
@@ -12972,6 +13923,18 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
12972
13923
|
}
|
|
12973
13924
|
if (extraContent && !isScoped) {
|
|
12974
13925
|
applyNavFooterDeleteOverrides(byKey, extraContent);
|
|
13926
|
+
for (const key of LOGO_IMAGE_KEYS) {
|
|
13927
|
+
if (!(key in extraContent)) continue;
|
|
13928
|
+
byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
|
|
13929
|
+
}
|
|
13930
|
+
for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
|
|
13931
|
+
if (!(key in extraContent)) continue;
|
|
13932
|
+
byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
|
|
13933
|
+
}
|
|
13934
|
+
for (const key of LOGO_SIZE_KEYS) {
|
|
13935
|
+
if (!(key in extraContent)) continue;
|
|
13936
|
+
byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
|
|
13937
|
+
}
|
|
12975
13938
|
}
|
|
12976
13939
|
return Array.from(byKey.values());
|
|
12977
13940
|
}
|
|
@@ -13376,6 +14339,7 @@ function fadeInImageElement(img, onReady) {
|
|
|
13376
14339
|
function applyEditableImageSrc(img, url) {
|
|
13377
14340
|
img.removeAttribute("srcset");
|
|
13378
14341
|
img.removeAttribute("sizes");
|
|
14342
|
+
if (img.loading === "lazy") img.loading = "eager";
|
|
13379
14343
|
img.src = url;
|
|
13380
14344
|
}
|
|
13381
14345
|
function fadeInBgImage(el, url, onReady) {
|
|
@@ -13440,21 +14404,10 @@ function parseSchedulingInsertAfter(insertAfter) {
|
|
|
13440
14404
|
insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
|
|
13441
14405
|
};
|
|
13442
14406
|
}
|
|
13443
|
-
function
|
|
13444
|
-
|
|
13445
|
-
const
|
|
13446
|
-
|
|
13447
|
-
return { effectiveInsertAfter, insertBefore };
|
|
13448
|
-
}
|
|
13449
|
-
function getSchedulingMountPoint(insertAfter) {
|
|
13450
|
-
const { anchor } = parseSchedulingInsertAfter(insertAfter);
|
|
13451
|
-
let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
|
|
13452
|
-
if (!anchorEl && anchor === "scheduling") {
|
|
13453
|
-
const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
|
|
13454
|
-
anchorEl = widgets.at(-1) ?? null;
|
|
13455
|
-
}
|
|
13456
|
-
if (!anchorEl) return null;
|
|
13457
|
-
return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
14407
|
+
function resolveEntryAnchor(entry) {
|
|
14408
|
+
if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
|
|
14409
|
+
const parsed = parseSchedulingInsertAfter(entry.insertAfter);
|
|
14410
|
+
return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
|
|
13458
14411
|
}
|
|
13459
14412
|
function schedulingMountDepth(insertAfter) {
|
|
13460
14413
|
if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
|
|
@@ -13471,8 +14424,7 @@ function getPageSchedulingEntries(raw) {
|
|
|
13471
14424
|
}
|
|
13472
14425
|
}
|
|
13473
14426
|
function isSchedulingWidgetMissing(entry) {
|
|
13474
|
-
|
|
13475
|
-
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
|
|
14427
|
+
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
|
|
13476
14428
|
}
|
|
13477
14429
|
function hasMissingSchedulingWidgets(entries) {
|
|
13478
14430
|
return entries.some(isSchedulingWidgetMissing);
|
|
@@ -13502,16 +14454,17 @@ function initSectionsFromContent(content, removeExisting = false) {
|
|
|
13502
14454
|
} catch {
|
|
13503
14455
|
}
|
|
13504
14456
|
}
|
|
13505
|
-
function mountSchedulingWidget(
|
|
13506
|
-
const
|
|
13507
|
-
const sectionId = schedulingSectionId(
|
|
14457
|
+
function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
|
|
14458
|
+
const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
|
|
14459
|
+
const sectionId = schedulingSectionId(widgetId);
|
|
13508
14460
|
if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
|
|
13509
|
-
const
|
|
13510
|
-
if (!
|
|
14461
|
+
const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
|
|
14462
|
+
if (!anchorEl) return false;
|
|
14463
|
+
const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
13511
14464
|
const container = document.createElement("div");
|
|
13512
14465
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
13513
|
-
if (
|
|
13514
|
-
const beforeAnchor = document.querySelector(`[data-ohw-section="${
|
|
14466
|
+
if (beforeId) {
|
|
14467
|
+
const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
|
|
13515
14468
|
const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
|
|
13516
14469
|
if (!beforePoint) return false;
|
|
13517
14470
|
beforePoint.insertAdjacentElement("beforebegin", container);
|
|
@@ -13522,19 +14475,25 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
13522
14475
|
}
|
|
13523
14476
|
tail.insertAdjacentElement("afterend", container);
|
|
13524
14477
|
}
|
|
13525
|
-
|
|
13526
|
-
|
|
13527
|
-
|
|
13528
|
-
|
|
13529
|
-
|
|
13530
|
-
|
|
13531
|
-
|
|
13532
|
-
|
|
13533
|
-
|
|
13534
|
-
|
|
13535
|
-
|
|
13536
|
-
|
|
13537
|
-
|
|
14478
|
+
try {
|
|
14479
|
+
const root = (0, import_client2.createRoot)(container);
|
|
14480
|
+
(0, import_react_dom3.flushSync)(() => {
|
|
14481
|
+
root.render(
|
|
14482
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
14483
|
+
SchedulingWidget,
|
|
14484
|
+
{
|
|
14485
|
+
notifyOnConnect,
|
|
14486
|
+
initialScheduleId: scheduleId,
|
|
14487
|
+
insertAfter: widgetId
|
|
14488
|
+
}
|
|
14489
|
+
)
|
|
14490
|
+
);
|
|
14491
|
+
});
|
|
14492
|
+
} catch (err) {
|
|
14493
|
+
console.error("[ow:scheduling] render threw", err);
|
|
14494
|
+
container.remove();
|
|
14495
|
+
return false;
|
|
14496
|
+
}
|
|
13538
14497
|
const tracker = getSectionsTracker();
|
|
13539
14498
|
let sections = [];
|
|
13540
14499
|
try {
|
|
@@ -13542,10 +14501,12 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
13542
14501
|
} catch {
|
|
13543
14502
|
}
|
|
13544
14503
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
13545
|
-
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter ===
|
|
14504
|
+
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
|
|
13546
14505
|
sections.push({
|
|
13547
14506
|
type: "scheduling",
|
|
13548
|
-
insertAfter:
|
|
14507
|
+
insertAfter: widgetId,
|
|
14508
|
+
anchorId,
|
|
14509
|
+
beforeId: beforeId ?? null,
|
|
13549
14510
|
pagePath: window.location.pathname,
|
|
13550
14511
|
...scheduleId ? { scheduleId } : {}
|
|
13551
14512
|
});
|
|
@@ -13559,7 +14520,8 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
13559
14520
|
for (let i = pending.length - 1; i >= 0; i--) {
|
|
13560
14521
|
const entry = pending[i];
|
|
13561
14522
|
const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
|
|
13562
|
-
|
|
14523
|
+
const { anchorId, beforeId } = resolveEntryAnchor(entry);
|
|
14524
|
+
if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
|
|
13563
14525
|
pending.splice(i, 1);
|
|
13564
14526
|
}
|
|
13565
14527
|
}
|
|
@@ -13707,6 +14669,13 @@ function isInsideLinkEditor(target) {
|
|
|
13707
14669
|
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"]')
|
|
13708
14670
|
);
|
|
13709
14671
|
}
|
|
14672
|
+
function isInsideFloatingPanel(target) {
|
|
14673
|
+
return Boolean(target.closest("[data-ohw-floating-panel]"));
|
|
14674
|
+
}
|
|
14675
|
+
function isPointOverFloatingPanel(clientX, clientY) {
|
|
14676
|
+
const el = document.elementFromPoint(clientX, clientY);
|
|
14677
|
+
return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
|
|
14678
|
+
}
|
|
13710
14679
|
function getHrefKeyFromElement(el) {
|
|
13711
14680
|
if (!el) return null;
|
|
13712
14681
|
const anchor = el.closest("[data-ohw-href-key]");
|
|
@@ -13952,7 +14921,7 @@ function getNavigationSelectionParent(el) {
|
|
|
13952
14921
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
13953
14922
|
return getFooterLinksContainer();
|
|
13954
14923
|
}
|
|
13955
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
14924
|
+
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)) {
|
|
13956
14925
|
return getNavigationRoot(el);
|
|
13957
14926
|
}
|
|
13958
14927
|
return null;
|
|
@@ -14421,9 +15390,9 @@ function FloatingToolbar({
|
|
|
14421
15390
|
showEditLink,
|
|
14422
15391
|
onEditLink
|
|
14423
15392
|
}) {
|
|
14424
|
-
const localRef =
|
|
14425
|
-
const [measuredW, setMeasuredW] =
|
|
14426
|
-
const setRefs =
|
|
15393
|
+
const localRef = import_react17.default.useRef(null);
|
|
15394
|
+
const [measuredW, setMeasuredW] = import_react17.default.useState(330);
|
|
15395
|
+
const setRefs = import_react17.default.useCallback(
|
|
14427
15396
|
(node) => {
|
|
14428
15397
|
localRef.current = node;
|
|
14429
15398
|
if (typeof elRef === "function") elRef(node);
|
|
@@ -14435,7 +15404,7 @@ function FloatingToolbar({
|
|
|
14435
15404
|
},
|
|
14436
15405
|
[elRef]
|
|
14437
15406
|
);
|
|
14438
|
-
|
|
15407
|
+
import_react17.default.useLayoutEffect(() => {
|
|
14439
15408
|
const node = localRef.current;
|
|
14440
15409
|
if (!node) return;
|
|
14441
15410
|
const update = () => {
|
|
@@ -14461,7 +15430,7 @@ function FloatingToolbar({
|
|
|
14461
15430
|
pointerEvents: "auto"
|
|
14462
15431
|
},
|
|
14463
15432
|
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(CustomToolbar, { children: [
|
|
14464
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
15433
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react17.default.Fragment, { children: [
|
|
14465
15434
|
gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CustomToolbarDivider, {}),
|
|
14466
15435
|
btns.map((btn) => {
|
|
14467
15436
|
const isActive = activeCommands.has(btn.cmd);
|
|
@@ -14545,6 +15514,45 @@ function StateToggle({
|
|
|
14545
15514
|
);
|
|
14546
15515
|
}
|
|
14547
15516
|
var contentCache = /* @__PURE__ */ new Map();
|
|
15517
|
+
var fetchedContentPaths = /* @__PURE__ */ new Set();
|
|
15518
|
+
var OHW_LOADER_STYLE = {
|
|
15519
|
+
position: "fixed",
|
|
15520
|
+
inset: 0,
|
|
15521
|
+
background: "#fff",
|
|
15522
|
+
zIndex: 2147483646,
|
|
15523
|
+
display: "flex",
|
|
15524
|
+
alignItems: "center",
|
|
15525
|
+
justifyContent: "center"
|
|
15526
|
+
};
|
|
15527
|
+
function OhwLoaderSpinner() {
|
|
15528
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", "aria-hidden": true, children: [
|
|
15529
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("circle", { cx: "14", cy: "14", r: "11", stroke: "#E7E5E4", strokeWidth: "3" }),
|
|
15530
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
15531
|
+
"circle",
|
|
15532
|
+
{
|
|
15533
|
+
cx: "14",
|
|
15534
|
+
cy: "14",
|
|
15535
|
+
r: "11",
|
|
15536
|
+
stroke: "#1C1917",
|
|
15537
|
+
strokeWidth: "3",
|
|
15538
|
+
strokeDasharray: "17 52",
|
|
15539
|
+
strokeLinecap: "round",
|
|
15540
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
15541
|
+
"animateTransform",
|
|
15542
|
+
{
|
|
15543
|
+
attributeName: "transform",
|
|
15544
|
+
type: "rotate",
|
|
15545
|
+
from: "0 14 14",
|
|
15546
|
+
to: "360 14 14",
|
|
15547
|
+
dur: "0.7s",
|
|
15548
|
+
repeatCount: "indefinite"
|
|
15549
|
+
}
|
|
15550
|
+
)
|
|
15551
|
+
}
|
|
15552
|
+
)
|
|
15553
|
+
] });
|
|
15554
|
+
}
|
|
15555
|
+
var OHW_LOADER_PREHYDRATE_SCRIPT = `(function(){try{var p=location.hostname.split(".");var fromHost=p.length>=3&&p[0]!=="www"?p[0]:"";var fromQuery=new URLSearchParams(location.search).get("subdomain")||"";if(!fromHost&&!fromQuery)return;var e=document.getElementById("ohw-loader");if(e)e.style.display="flex"}catch(e){}})();`;
|
|
14548
15556
|
function resolveSubdomain(subdomainFromQuery) {
|
|
14549
15557
|
if (subdomainFromQuery) return subdomainFromQuery;
|
|
14550
15558
|
if (typeof window !== "undefined") {
|
|
@@ -14567,8 +15575,8 @@ function OhhwellsBridge() {
|
|
|
14567
15575
|
const router = (0, import_navigation3.useRouter)();
|
|
14568
15576
|
const searchParams = (0, import_navigation3.useSearchParams)();
|
|
14569
15577
|
const isEditMode = isEditSessionActive();
|
|
14570
|
-
const [bridgeRoot, setBridgeRoot] = (0,
|
|
14571
|
-
(0,
|
|
15578
|
+
const [bridgeRoot, setBridgeRoot] = (0, import_react17.useState)(null);
|
|
15579
|
+
(0, import_react17.useEffect)(() => {
|
|
14572
15580
|
const figtreeFontId = "ohw-figtree-font";
|
|
14573
15581
|
if (!document.getElementById(figtreeFontId)) {
|
|
14574
15582
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -14597,88 +15605,152 @@ function OhhwellsBridge() {
|
|
|
14597
15605
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
14598
15606
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
14599
15607
|
useSavedLinkNavigation(isEditMode);
|
|
14600
|
-
const postToParent2 = (0,
|
|
15608
|
+
const postToParent2 = (0, import_react17.useCallback)((data) => {
|
|
14601
15609
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
14602
15610
|
window.parent.postMessage(data, "*");
|
|
14603
15611
|
}
|
|
14604
15612
|
}, []);
|
|
14605
|
-
const [fetchState, setFetchState] = (0,
|
|
14606
|
-
const autoSaveTimers = (0,
|
|
14607
|
-
const activeElRef = (0,
|
|
14608
|
-
const pointerHeldRef = (0,
|
|
14609
|
-
const selectedElRef = (0,
|
|
14610
|
-
const selectedHrefKeyRef = (0,
|
|
14611
|
-
const selectedFooterColAttrRef = (0,
|
|
14612
|
-
const originalContentRef = (0,
|
|
14613
|
-
const activeStateElRef = (0,
|
|
14614
|
-
const parentScrollRef = (0,
|
|
14615
|
-
const visibleViewportRef = (0,
|
|
14616
|
-
const [dialogPortalContainer, setDialogPortalContainer] = (0,
|
|
14617
|
-
const attachVisibleViewport = (0,
|
|
15613
|
+
const [fetchState, setFetchState] = (0, import_react17.useState)("idle");
|
|
15614
|
+
const autoSaveTimers = (0, import_react17.useRef)(/* @__PURE__ */ new Map());
|
|
15615
|
+
const activeElRef = (0, import_react17.useRef)(null);
|
|
15616
|
+
const pointerHeldRef = (0, import_react17.useRef)(false);
|
|
15617
|
+
const selectedElRef = (0, import_react17.useRef)(null);
|
|
15618
|
+
const selectedHrefKeyRef = (0, import_react17.useRef)(null);
|
|
15619
|
+
const selectedFooterColAttrRef = (0, import_react17.useRef)(null);
|
|
15620
|
+
const originalContentRef = (0, import_react17.useRef)(null);
|
|
15621
|
+
const activeStateElRef = (0, import_react17.useRef)(null);
|
|
15622
|
+
const parentScrollRef = (0, import_react17.useRef)(null);
|
|
15623
|
+
const visibleViewportRef = (0, import_react17.useRef)(null);
|
|
15624
|
+
const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react17.useState)(null);
|
|
15625
|
+
const attachVisibleViewport = (0, import_react17.useCallback)((node) => {
|
|
14618
15626
|
visibleViewportRef.current = node;
|
|
14619
15627
|
setDialogPortalContainer(node);
|
|
14620
15628
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
14621
15629
|
}, []);
|
|
14622
|
-
const toolbarElRef = (0,
|
|
14623
|
-
const glowElRef = (0,
|
|
14624
|
-
const hoveredImageRef = (0,
|
|
14625
|
-
const hoveredImageHasTextOverlapRef = (0,
|
|
14626
|
-
const dragOverElRef = (0,
|
|
14627
|
-
const [mediaHover, setMediaHover] = (0,
|
|
14628
|
-
const [
|
|
14629
|
-
const
|
|
14630
|
-
const
|
|
14631
|
-
|
|
14632
|
-
|
|
14633
|
-
|
|
14634
|
-
|
|
14635
|
-
|
|
14636
|
-
|
|
14637
|
-
|
|
14638
|
-
|
|
14639
|
-
|
|
14640
|
-
|
|
14641
|
-
|
|
14642
|
-
|
|
14643
|
-
});
|
|
14644
|
-
const
|
|
14645
|
-
|
|
14646
|
-
const
|
|
14647
|
-
|
|
14648
|
-
|
|
14649
|
-
|
|
14650
|
-
|
|
14651
|
-
|
|
14652
|
-
|
|
14653
|
-
|
|
14654
|
-
|
|
14655
|
-
|
|
14656
|
-
|
|
14657
|
-
|
|
14658
|
-
|
|
14659
|
-
|
|
14660
|
-
|
|
14661
|
-
|
|
14662
|
-
|
|
14663
|
-
|
|
14664
|
-
|
|
14665
|
-
|
|
14666
|
-
|
|
14667
|
-
|
|
14668
|
-
|
|
14669
|
-
|
|
14670
|
-
const
|
|
14671
|
-
|
|
14672
|
-
|
|
14673
|
-
|
|
14674
|
-
|
|
14675
|
-
|
|
14676
|
-
|
|
14677
|
-
|
|
14678
|
-
|
|
14679
|
-
|
|
14680
|
-
|
|
14681
|
-
|
|
15630
|
+
const toolbarElRef = (0, import_react17.useRef)(null);
|
|
15631
|
+
const glowElRef = (0, import_react17.useRef)(null);
|
|
15632
|
+
const hoveredImageRef = (0, import_react17.useRef)(null);
|
|
15633
|
+
const hoveredImageHasTextOverlapRef = (0, import_react17.useRef)(false);
|
|
15634
|
+
const dragOverElRef = (0, import_react17.useRef)(null);
|
|
15635
|
+
const [mediaHover, setMediaHover] = (0, import_react17.useState)(null);
|
|
15636
|
+
const [selectedMedia, setSelectedMedia] = (0, import_react17.useState)(null);
|
|
15637
|
+
const selectedMediaElRef = (0, import_react17.useRef)(null);
|
|
15638
|
+
const clearMediaSelection = (0, import_react17.useCallback)(() => {
|
|
15639
|
+
const prev = selectedMediaElRef.current;
|
|
15640
|
+
selectedMediaElRef.current = null;
|
|
15641
|
+
setSelectedMedia(null);
|
|
15642
|
+
const sectionEl = prev?.closest("[data-ohw-section]") ?? null;
|
|
15643
|
+
if (sectionEl) {
|
|
15644
|
+
postToParentRef.current({
|
|
15645
|
+
type: "ow:section-selected",
|
|
15646
|
+
sectionId: sectionEl.dataset.ohwSection ?? null,
|
|
15647
|
+
sectionLabel: sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? ""),
|
|
15648
|
+
key: null
|
|
15649
|
+
});
|
|
15650
|
+
}
|
|
15651
|
+
}, []);
|
|
15652
|
+
const clearMediaSelectionRef = (0, import_react17.useRef)(clearMediaSelection);
|
|
15653
|
+
clearMediaSelectionRef.current = clearMediaSelection;
|
|
15654
|
+
const selectMediaElement = (0, import_react17.useCallback)((el) => {
|
|
15655
|
+
const r2 = el.getBoundingClientRect();
|
|
15656
|
+
const video = el.dataset.ohwEditable === "video" ? el.querySelector("video") : null;
|
|
15657
|
+
selectedMediaElRef.current = el;
|
|
15658
|
+
setSelectedMedia({
|
|
15659
|
+
key: el.dataset.ohwKey ?? "",
|
|
15660
|
+
rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
|
|
15661
|
+
elementType: el.dataset.ohwEditable ?? "image",
|
|
15662
|
+
hasTextOverlap: false,
|
|
15663
|
+
isDragOver: false,
|
|
15664
|
+
...video ? { videoAutoplay: video.autoplay, videoMuted: video.muted } : {}
|
|
15665
|
+
});
|
|
15666
|
+
const sectionEl = el.closest("[data-ohw-section]");
|
|
15667
|
+
aiSectionApiRef.current?.selectFromElement(el, { report: false });
|
|
15668
|
+
postToParentRef.current({
|
|
15669
|
+
type: "ow:section-selected",
|
|
15670
|
+
sectionId: sectionEl?.dataset.ohwSection ?? null,
|
|
15671
|
+
sectionLabel: sectionEl ? sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? "") : null,
|
|
15672
|
+
key: el.dataset.ohwKey ?? null,
|
|
15673
|
+
// Display name for the pill — the raw key prettifies into fragments ("Img"); the
|
|
15674
|
+
// bridge knows what the node IS, so it names it.
|
|
15675
|
+
keyLabel: el.dataset.ohwEditable === "video" ? "Video" : el.dataset.ohwEditable === "bg-image" ? "Background" : "Image"
|
|
15676
|
+
});
|
|
15677
|
+
}, []);
|
|
15678
|
+
const selectMediaElementRef = (0, import_react17.useRef)(selectMediaElement);
|
|
15679
|
+
selectMediaElementRef.current = selectMediaElement;
|
|
15680
|
+
(0, import_react17.useEffect)(() => {
|
|
15681
|
+
if (!selectedMedia) return;
|
|
15682
|
+
const update = () => {
|
|
15683
|
+
const el = selectedMediaElRef.current;
|
|
15684
|
+
if (!el || !el.isConnected) {
|
|
15685
|
+
clearMediaSelection();
|
|
15686
|
+
return;
|
|
15687
|
+
}
|
|
15688
|
+
const r2 = el.getBoundingClientRect();
|
|
15689
|
+
setSelectedMedia(
|
|
15690
|
+
(prev) => prev ? { ...prev, rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } } : prev
|
|
15691
|
+
);
|
|
15692
|
+
};
|
|
15693
|
+
window.addEventListener("scroll", update, true);
|
|
15694
|
+
window.addEventListener("resize", update);
|
|
15695
|
+
return () => {
|
|
15696
|
+
window.removeEventListener("scroll", update, true);
|
|
15697
|
+
window.removeEventListener("resize", update);
|
|
15698
|
+
};
|
|
15699
|
+
}, [selectedMedia !== null]);
|
|
15700
|
+
const [carouselHover, setCarouselHover] = (0, import_react17.useState)(null);
|
|
15701
|
+
const [uploadingRects, setUploadingRects] = (0, import_react17.useState)({});
|
|
15702
|
+
const hoveredGapRef = (0, import_react17.useRef)(null);
|
|
15703
|
+
const imageUnhoverTimerRef = (0, import_react17.useRef)(null);
|
|
15704
|
+
const imageShowTimerRef = (0, import_react17.useRef)(null);
|
|
15705
|
+
const editStylesRef = (0, import_react17.useRef)(null);
|
|
15706
|
+
const activateRef = (0, import_react17.useRef)(() => {
|
|
15707
|
+
});
|
|
15708
|
+
const deactivateRef = (0, import_react17.useRef)(() => {
|
|
15709
|
+
});
|
|
15710
|
+
const selectRef = (0, import_react17.useRef)(() => {
|
|
15711
|
+
});
|
|
15712
|
+
const selectFrameRef = (0, import_react17.useRef)(() => {
|
|
15713
|
+
});
|
|
15714
|
+
const selectLogoRef = (0, import_react17.useRef)(() => {
|
|
15715
|
+
});
|
|
15716
|
+
const openLogoSizePanelRef = (0, import_react17.useRef)(() => {
|
|
15717
|
+
});
|
|
15718
|
+
const deselectRef = (0, import_react17.useRef)(() => {
|
|
15719
|
+
});
|
|
15720
|
+
const closeFloatingPanelOnlyRef = (0, import_react17.useRef)(() => {
|
|
15721
|
+
});
|
|
15722
|
+
const reselectNavigationItemRef = (0, import_react17.useRef)(() => {
|
|
15723
|
+
});
|
|
15724
|
+
const commitNavigationTextEditRef = (0, import_react17.useRef)(() => {
|
|
15725
|
+
});
|
|
15726
|
+
const handleDeleteSelectedRef = (0, import_react17.useRef)(() => false);
|
|
15727
|
+
const runPendingDeleteUndoRef = (0, import_react17.useRef)(() => false);
|
|
15728
|
+
const isFooterFrameSelectionRef = (0, import_react17.useRef)(false);
|
|
15729
|
+
const refreshActiveCommandsRef = (0, import_react17.useRef)(() => {
|
|
15730
|
+
});
|
|
15731
|
+
const postToParentRef = (0, import_react17.useRef)(postToParent2);
|
|
15732
|
+
postToParentRef.current = postToParent2;
|
|
15733
|
+
const aiSectionApiRef = (0, import_react17.useRef)(null);
|
|
15734
|
+
const sectionsLoadedRef = (0, import_react17.useRef)(false);
|
|
15735
|
+
const pendingScheduleConfigRequests = (0, import_react17.useRef)([]);
|
|
15736
|
+
const [toolbarRect, setToolbarRect] = (0, import_react17.useState)(null);
|
|
15737
|
+
const [formPickRect, setFormPickRect] = (0, import_react17.useState)(null);
|
|
15738
|
+
const formPickElRef = (0, import_react17.useRef)(null);
|
|
15739
|
+
const [formViewState, setFormViewStateUi] = (0, import_react17.useState)("default");
|
|
15740
|
+
const [formPickCount, setFormPickCount] = (0, import_react17.useState)(null);
|
|
15741
|
+
const [formHoverRect, setFormHoverRect] = (0, import_react17.useState)(null);
|
|
15742
|
+
const formHoverElRef = (0, import_react17.useRef)(null);
|
|
15743
|
+
const [fieldPickRect, setFieldPickRect] = (0, import_react17.useState)(null);
|
|
15744
|
+
const fieldPickElRef = (0, import_react17.useRef)(null);
|
|
15745
|
+
const [fieldPickState, setFieldPickState] = (0, import_react17.useState)(null);
|
|
15746
|
+
const [fieldTypePickerOpen, setFieldTypePickerOpen] = (0, import_react17.useState)(false);
|
|
15747
|
+
const clearFormPick = (0, import_react17.useCallback)(() => {
|
|
15748
|
+
const form = formPickElRef.current;
|
|
15749
|
+
const editing = fieldPickElRef.current;
|
|
15750
|
+
if (commitPlaceholderEdit(editing) && editing) {
|
|
15751
|
+
const owner = editing.closest('[data-ohw-editable="form"]');
|
|
15752
|
+
if (owner) persistFieldsRef.current(owner);
|
|
15753
|
+
}
|
|
14682
15754
|
if (form) {
|
|
14683
15755
|
const key = formKeyOf(form);
|
|
14684
15756
|
if (key) setFormViewState(form, key, "default", successInitialFor(form, key, editContentRef.current));
|
|
@@ -14692,7 +15764,7 @@ function OhhwellsBridge() {
|
|
|
14692
15764
|
formPickElRef.current = null;
|
|
14693
15765
|
setFormPickRect(null);
|
|
14694
15766
|
}, []);
|
|
14695
|
-
const clearFieldPick = (0,
|
|
15767
|
+
const clearFieldPick = (0, import_react17.useCallback)(() => {
|
|
14696
15768
|
const wrapper = fieldPickElRef.current;
|
|
14697
15769
|
if (commitPlaceholderEdit(wrapper) && wrapper) {
|
|
14698
15770
|
const form = wrapper.closest('[data-ohw-editable="form"]');
|
|
@@ -14702,9 +15774,9 @@ function OhhwellsBridge() {
|
|
|
14702
15774
|
setFieldPickRect(null);
|
|
14703
15775
|
setFieldPickState(null);
|
|
14704
15776
|
}, []);
|
|
14705
|
-
const persistFieldsRef = (0,
|
|
15777
|
+
const persistFieldsRef = (0, import_react17.useRef)(() => {
|
|
14706
15778
|
});
|
|
14707
|
-
const persistFields = (0,
|
|
15779
|
+
const persistFields = (0, import_react17.useCallback)(
|
|
14708
15780
|
(form) => {
|
|
14709
15781
|
const key = formKeyOf(form);
|
|
14710
15782
|
if (!key) return;
|
|
@@ -14715,7 +15787,7 @@ function OhhwellsBridge() {
|
|
|
14715
15787
|
[]
|
|
14716
15788
|
);
|
|
14717
15789
|
persistFieldsRef.current = persistFields;
|
|
14718
|
-
const selectField = (0,
|
|
15790
|
+
const selectField = (0, import_react17.useCallback)((wrapper) => {
|
|
14719
15791
|
if (fieldPickElRef.current && fieldPickElRef.current !== wrapper) {
|
|
14720
15792
|
commitPlaceholderEdit(fieldPickElRef.current);
|
|
14721
15793
|
}
|
|
@@ -14728,7 +15800,7 @@ function OhhwellsBridge() {
|
|
|
14728
15800
|
setFieldPickState({ type: fieldTypeOf(wrapper), required: isFieldRequired(wrapper) });
|
|
14729
15801
|
setFieldTypePickerOpen(false);
|
|
14730
15802
|
}, []);
|
|
14731
|
-
const withSelectedField = (0,
|
|
15803
|
+
const withSelectedField = (0, import_react17.useCallback)(
|
|
14732
15804
|
(run) => {
|
|
14733
15805
|
const wrapper = fieldPickElRef.current;
|
|
14734
15806
|
const form = formPickElRef.current;
|
|
@@ -14741,28 +15813,28 @@ function OhhwellsBridge() {
|
|
|
14741
15813
|
},
|
|
14742
15814
|
[persistFields]
|
|
14743
15815
|
);
|
|
14744
|
-
const handleFieldTypeChange = (0,
|
|
15816
|
+
const handleFieldTypeChange = (0, import_react17.useCallback)(
|
|
14745
15817
|
(type) => withSelectedField((_form, wrapper) => {
|
|
14746
15818
|
applyFieldType(wrapper, type);
|
|
14747
15819
|
selectField(wrapper);
|
|
14748
15820
|
}),
|
|
14749
15821
|
[selectField, withSelectedField]
|
|
14750
15822
|
);
|
|
14751
|
-
const handleFieldRequiredToggle = (0,
|
|
15823
|
+
const handleFieldRequiredToggle = (0, import_react17.useCallback)(
|
|
14752
15824
|
() => withSelectedField((_form, wrapper) => {
|
|
14753
15825
|
setFieldRequired(wrapper, !isFieldRequired(wrapper));
|
|
14754
15826
|
selectField(wrapper);
|
|
14755
15827
|
}),
|
|
14756
15828
|
[selectField, withSelectedField]
|
|
14757
15829
|
);
|
|
14758
|
-
const handleFieldDuplicate = (0,
|
|
15830
|
+
const handleFieldDuplicate = (0, import_react17.useCallback)(
|
|
14759
15831
|
() => withSelectedField((form, wrapper) => {
|
|
14760
15832
|
const copy = duplicateField(form, wrapper);
|
|
14761
15833
|
selectField(copy);
|
|
14762
15834
|
}),
|
|
14763
15835
|
[selectField, withSelectedField]
|
|
14764
15836
|
);
|
|
14765
|
-
const handleFieldDelete = (0,
|
|
15837
|
+
const handleFieldDelete = (0, import_react17.useCallback)(
|
|
14766
15838
|
() => withSelectedField((_form, wrapper) => {
|
|
14767
15839
|
removeField(wrapper);
|
|
14768
15840
|
clearFieldPick();
|
|
@@ -14770,7 +15842,7 @@ function OhhwellsBridge() {
|
|
|
14770
15842
|
}),
|
|
14771
15843
|
[clearFieldPick, withSelectedField]
|
|
14772
15844
|
);
|
|
14773
|
-
const handleAddField = (0,
|
|
15845
|
+
const handleAddField = (0, import_react17.useCallback)(
|
|
14774
15846
|
(type) => {
|
|
14775
15847
|
const form = formPickElRef.current;
|
|
14776
15848
|
if (!form) return;
|
|
@@ -14786,8 +15858,8 @@ function OhhwellsBridge() {
|
|
|
14786
15858
|
},
|
|
14787
15859
|
[persistFields, selectField]
|
|
14788
15860
|
);
|
|
14789
|
-
const fieldDragRef = (0,
|
|
14790
|
-
const buildFieldDropSlots = (0,
|
|
15861
|
+
const fieldDragRef = (0, import_react17.useRef)(null);
|
|
15862
|
+
const buildFieldDropSlots = (0, import_react17.useCallback)((form, draggedKey) => {
|
|
14791
15863
|
const others = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== draggedKey);
|
|
14792
15864
|
const slots = others.map((el) => {
|
|
14793
15865
|
const rect = el.getBoundingClientRect();
|
|
@@ -14800,7 +15872,7 @@ function OhhwellsBridge() {
|
|
|
14800
15872
|
}
|
|
14801
15873
|
return slots;
|
|
14802
15874
|
}, []);
|
|
14803
|
-
const handleFieldDragStart = (0,
|
|
15875
|
+
const handleFieldDragStart = (0, import_react17.useCallback)(() => {
|
|
14804
15876
|
const wrapper = fieldPickElRef.current;
|
|
14805
15877
|
const form = formPickElRef.current;
|
|
14806
15878
|
if (!wrapper || !form) return;
|
|
@@ -14809,18 +15881,18 @@ function OhhwellsBridge() {
|
|
|
14809
15881
|
setFieldDragging(true);
|
|
14810
15882
|
setFieldDropSlots(buildFieldDropSlots(form, key));
|
|
14811
15883
|
}, [buildFieldDropSlots]);
|
|
14812
|
-
const handleFieldDragEnd = (0,
|
|
15884
|
+
const handleFieldDragEnd = (0, import_react17.useCallback)(() => {
|
|
14813
15885
|
fieldDragRef.current = null;
|
|
14814
15886
|
setFieldDropIndex(null);
|
|
14815
15887
|
setFieldDropSlots([]);
|
|
14816
15888
|
setFieldDragging(false);
|
|
14817
15889
|
}, []);
|
|
14818
|
-
const [fieldDropIndex, setFieldDropIndex] = (0,
|
|
14819
|
-
const [fieldDropSlots, setFieldDropSlots] = (0,
|
|
14820
|
-
const [fieldDragging, setFieldDragging] = (0,
|
|
14821
|
-
const clearFormPickRef = (0,
|
|
15890
|
+
const [fieldDropIndex, setFieldDropIndex] = (0, import_react17.useState)(null);
|
|
15891
|
+
const [fieldDropSlots, setFieldDropSlots] = (0, import_react17.useState)([]);
|
|
15892
|
+
const [fieldDragging, setFieldDragging] = (0, import_react17.useState)(false);
|
|
15893
|
+
const clearFormPickRef = (0, import_react17.useRef)(clearFormPick);
|
|
14822
15894
|
clearFormPickRef.current = clearFormPick;
|
|
14823
|
-
(0,
|
|
15895
|
+
(0, import_react17.useEffect)(() => {
|
|
14824
15896
|
const el = fieldPickElRef.current;
|
|
14825
15897
|
if (!el || fieldPickRect === null) return;
|
|
14826
15898
|
const observer = new ResizeObserver(() => {
|
|
@@ -14829,7 +15901,7 @@ function OhhwellsBridge() {
|
|
|
14829
15901
|
observer.observe(el);
|
|
14830
15902
|
return () => observer.disconnect();
|
|
14831
15903
|
}, [fieldPickRect !== null, fieldPickState]);
|
|
14832
|
-
(0,
|
|
15904
|
+
(0, import_react17.useEffect)(() => {
|
|
14833
15905
|
const el = formPickElRef.current;
|
|
14834
15906
|
if (!el || formPickRect === null) return;
|
|
14835
15907
|
const observer = new ResizeObserver(() => {
|
|
@@ -14838,25 +15910,25 @@ function OhhwellsBridge() {
|
|
|
14838
15910
|
observer.observe(el);
|
|
14839
15911
|
return () => observer.disconnect();
|
|
14840
15912
|
}, [formPickRect !== null, formViewState]);
|
|
14841
|
-
const [toolbarVariant, setToolbarVariant] = (0,
|
|
14842
|
-
const toolbarVariantRef = (0,
|
|
15913
|
+
const [toolbarVariant, setToolbarVariant] = (0, import_react17.useState)("none");
|
|
15914
|
+
const toolbarVariantRef = (0, import_react17.useRef)("none");
|
|
14843
15915
|
toolbarVariantRef.current = toolbarVariant;
|
|
14844
|
-
const [selectedIsCta, setSelectedIsCta] = (0,
|
|
14845
|
-
const [selectedIsSocial, setSelectedIsSocial] = (0,
|
|
14846
|
-
const [selectedIsSocialsRow, setSelectedIsSocialsRow] = (0,
|
|
14847
|
-
const [reorderHrefKey, setReorderHrefKey] = (0,
|
|
14848
|
-
const [reorderDragDisabled, setReorderDragDisabled] = (0,
|
|
14849
|
-
const [toggleState, setToggleState] = (0,
|
|
14850
|
-
const [maxBadge, setMaxBadge] = (0,
|
|
14851
|
-
const [activeCommands, setActiveCommands] = (0,
|
|
14852
|
-
const [sectionGap, setSectionGap] = (0,
|
|
14853
|
-
const [toolbarShowEditLink, setToolbarShowEditLink] = (0,
|
|
14854
|
-
const hoveredNavContainerRef = (0,
|
|
14855
|
-
const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0,
|
|
14856
|
-
const hoveredItemElRef = (0,
|
|
14857
|
-
const [hoveredItemRect, setHoveredItemRect] = (0,
|
|
14858
|
-
const [hoveredTextRect, setHoveredTextRect] = (0,
|
|
14859
|
-
(0,
|
|
15916
|
+
const [selectedIsCta, setSelectedIsCta] = (0, import_react17.useState)(false);
|
|
15917
|
+
const [selectedIsSocial, setSelectedIsSocial] = (0, import_react17.useState)(false);
|
|
15918
|
+
const [selectedIsSocialsRow, setSelectedIsSocialsRow] = (0, import_react17.useState)(false);
|
|
15919
|
+
const [reorderHrefKey, setReorderHrefKey] = (0, import_react17.useState)(null);
|
|
15920
|
+
const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react17.useState)(false);
|
|
15921
|
+
const [toggleState, setToggleState] = (0, import_react17.useState)(null);
|
|
15922
|
+
const [maxBadge, setMaxBadge] = (0, import_react17.useState)(null);
|
|
15923
|
+
const [activeCommands, setActiveCommands] = (0, import_react17.useState)(/* @__PURE__ */ new Set());
|
|
15924
|
+
const [sectionGap, setSectionGap] = (0, import_react17.useState)(null);
|
|
15925
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react17.useState)(false);
|
|
15926
|
+
const hoveredNavContainerRef = (0, import_react17.useRef)(null);
|
|
15927
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react17.useState)(null);
|
|
15928
|
+
const hoveredItemElRef = (0, import_react17.useRef)(null);
|
|
15929
|
+
const [hoveredItemRect, setHoveredItemRect] = (0, import_react17.useState)(null);
|
|
15930
|
+
const [hoveredTextRect, setHoveredTextRect] = (0, import_react17.useState)(null);
|
|
15931
|
+
(0, import_react17.useEffect)(() => {
|
|
14860
15932
|
const sync = () => {
|
|
14861
15933
|
const el = document.querySelector(
|
|
14862
15934
|
'[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]):not([data-ohw-editable="form"] *)'
|
|
@@ -14877,43 +15949,56 @@ function OhhwellsBridge() {
|
|
|
14877
15949
|
});
|
|
14878
15950
|
return () => observer.disconnect();
|
|
14879
15951
|
}, []);
|
|
14880
|
-
const siblingHintElRef = (0,
|
|
14881
|
-
const [siblingHintRect, setSiblingHintRect] = (0,
|
|
14882
|
-
const [siblingHintRects, setSiblingHintRects] = (0,
|
|
14883
|
-
const [isItemDragging, setIsItemDragging] = (0,
|
|
14884
|
-
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0,
|
|
15952
|
+
const siblingHintElRef = (0, import_react17.useRef)(null);
|
|
15953
|
+
const [siblingHintRect, setSiblingHintRect] = (0, import_react17.useState)(null);
|
|
15954
|
+
const [siblingHintRects, setSiblingHintRects] = (0, import_react17.useState)([]);
|
|
15955
|
+
const [isItemDragging, setIsItemDragging] = (0, import_react17.useState)(false);
|
|
15956
|
+
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react17.useState)(false);
|
|
14885
15957
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
14886
|
-
const [
|
|
14887
|
-
const
|
|
14888
|
-
|
|
14889
|
-
const [
|
|
14890
|
-
const [
|
|
14891
|
-
const [
|
|
14892
|
-
const
|
|
14893
|
-
const
|
|
14894
|
-
const
|
|
14895
|
-
const
|
|
14896
|
-
const
|
|
14897
|
-
const
|
|
14898
|
-
const
|
|
14899
|
-
const
|
|
14900
|
-
const
|
|
14901
|
-
const
|
|
14902
|
-
const
|
|
14903
|
-
const
|
|
14904
|
-
const
|
|
14905
|
-
const
|
|
14906
|
-
const
|
|
14907
|
-
const
|
|
14908
|
-
const [
|
|
14909
|
-
const [
|
|
14910
|
-
const
|
|
14911
|
-
const
|
|
14912
|
-
const
|
|
14913
|
-
const
|
|
14914
|
-
const
|
|
15958
|
+
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react17.useState)(null);
|
|
15959
|
+
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react17.useState)(null);
|
|
15960
|
+
const footerDragRef = (0, import_react17.useRef)(null);
|
|
15961
|
+
const [footerDropSlots, setFooterDropSlots] = (0, import_react17.useState)([]);
|
|
15962
|
+
const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react17.useState)(null);
|
|
15963
|
+
const [draggedItemRect, setDraggedItemRect] = (0, import_react17.useState)(null);
|
|
15964
|
+
const footerPointerDragRef = (0, import_react17.useRef)(null);
|
|
15965
|
+
const suppressNextClickRef = (0, import_react17.useRef)(false);
|
|
15966
|
+
const suppressClickUntilRef = (0, import_react17.useRef)(0);
|
|
15967
|
+
const [linkPopover, setLinkPopover] = (0, import_react17.useState)(null);
|
|
15968
|
+
const linkPopoverSessionRef = (0, import_react17.useRef)(null);
|
|
15969
|
+
const addNavAfterAnchorRef = (0, import_react17.useRef)(null);
|
|
15970
|
+
const editContentRef = (0, import_react17.useRef)({});
|
|
15971
|
+
const aiSectionsRef = (0, import_react17.useRef)("");
|
|
15972
|
+
const brandKitRef = (0, import_react17.useRef)("");
|
|
15973
|
+
const stylesRef = (0, import_react17.useRef)("");
|
|
15974
|
+
const pendingDeleteUndoRef = (0, import_react17.useRef)(null);
|
|
15975
|
+
const [floatingPanel, setFloatingPanel] = (0, import_react17.useState)(null);
|
|
15976
|
+
const floatingPanelOpenRef = (0, import_react17.useRef)(false);
|
|
15977
|
+
const setFloatingPanelRef = (0, import_react17.useRef)(setFloatingPanel);
|
|
15978
|
+
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react17.useState)(null);
|
|
15979
|
+
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react17.useState)(null);
|
|
15980
|
+
const [editorViewport, setEditorViewport] = (0, import_react17.useState)("desktop");
|
|
15981
|
+
const [parentScrollSnap, setParentScrollSnap] = (0, import_react17.useState)(null);
|
|
15982
|
+
const [sitePages, setSitePages] = (0, import_react17.useState)([]);
|
|
15983
|
+
const [sectionsByPath, setSectionsByPath] = (0, import_react17.useState)({});
|
|
15984
|
+
const sectionsPrefetchGenRef = (0, import_react17.useRef)(0);
|
|
15985
|
+
const setLinkPopoverRef = (0, import_react17.useRef)(setLinkPopover);
|
|
15986
|
+
const linkPopoverPanelRef = (0, import_react17.useRef)(null);
|
|
15987
|
+
const linkPopoverOpenRef = (0, import_react17.useRef)(false);
|
|
15988
|
+
const linkPopoverGraceUntilRef = (0, import_react17.useRef)(0);
|
|
14915
15989
|
setLinkPopoverRef.current = setLinkPopover;
|
|
15990
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
14916
15991
|
linkPopoverSessionRef.current = linkPopover;
|
|
15992
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
15993
|
+
(0, import_react17.useEffect)(() => {
|
|
15994
|
+
const syncViewport = () => {
|
|
15995
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
15996
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
15997
|
+
};
|
|
15998
|
+
syncViewport();
|
|
15999
|
+
window.addEventListener("resize", syncViewport);
|
|
16000
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
16001
|
+
}, []);
|
|
14917
16002
|
const {
|
|
14918
16003
|
navDragRef,
|
|
14919
16004
|
navDropSlots,
|
|
@@ -14946,10 +16031,20 @@ function OhhwellsBridge() {
|
|
|
14946
16031
|
getNavigationItemAnchor,
|
|
14947
16032
|
isDragHandleDisabled
|
|
14948
16033
|
});
|
|
16034
|
+
const { sectionDropSlots, activeSectionDropIndex, isSectionDragging } = useSectionDrag({
|
|
16035
|
+
isEditMode,
|
|
16036
|
+
editContentRef,
|
|
16037
|
+
postToParentRef,
|
|
16038
|
+
parentScrollRef,
|
|
16039
|
+
navDragRef,
|
|
16040
|
+
footerDragRef,
|
|
16041
|
+
suppressNextClickRef,
|
|
16042
|
+
suppressClickUntilRef
|
|
16043
|
+
});
|
|
14949
16044
|
const bumpLinkPopoverGrace = () => {
|
|
14950
16045
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
14951
16046
|
};
|
|
14952
|
-
const runSectionsPrefetch = (0,
|
|
16047
|
+
const runSectionsPrefetch = (0, import_react17.useCallback)((pages) => {
|
|
14953
16048
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
14954
16049
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
14955
16050
|
const paths = pages.map((p) => p.path);
|
|
@@ -14968,9 +16063,9 @@ function OhhwellsBridge() {
|
|
|
14968
16063
|
);
|
|
14969
16064
|
});
|
|
14970
16065
|
}, [isEditMode, pathname]);
|
|
14971
|
-
const runSectionsPrefetchRef = (0,
|
|
16066
|
+
const runSectionsPrefetchRef = (0, import_react17.useRef)(runSectionsPrefetch);
|
|
14972
16067
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
14973
|
-
(0,
|
|
16068
|
+
(0, import_react17.useEffect)(() => {
|
|
14974
16069
|
if (!linkPopover) {
|
|
14975
16070
|
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
14976
16071
|
return;
|
|
@@ -14998,7 +16093,7 @@ function OhhwellsBridge() {
|
|
|
14998
16093
|
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
14999
16094
|
};
|
|
15000
16095
|
}, [linkPopover, postToParent2]);
|
|
15001
|
-
(0,
|
|
16096
|
+
(0, import_react17.useEffect)(() => {
|
|
15002
16097
|
if (!isEditMode) return;
|
|
15003
16098
|
const useFixtures = shouldUseDevFixtures();
|
|
15004
16099
|
if (useFixtures) {
|
|
@@ -15022,14 +16117,14 @@ function OhhwellsBridge() {
|
|
|
15022
16117
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
15023
16118
|
return () => window.removeEventListener("message", onSitePages);
|
|
15024
16119
|
}, [isEditMode, postToParent2]);
|
|
15025
|
-
(0,
|
|
16120
|
+
(0, import_react17.useEffect)(() => {
|
|
15026
16121
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
15027
16122
|
void loadAllSectionsManifest().then((manifest) => {
|
|
15028
16123
|
if (Object.keys(manifest).length === 0) return;
|
|
15029
16124
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
15030
16125
|
});
|
|
15031
16126
|
}, [isEditMode]);
|
|
15032
|
-
(0,
|
|
16127
|
+
(0, import_react17.useEffect)(() => {
|
|
15033
16128
|
const update = () => {
|
|
15034
16129
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
15035
16130
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -15053,10 +16148,10 @@ function OhhwellsBridge() {
|
|
|
15053
16148
|
vvp.removeEventListener("resize", update);
|
|
15054
16149
|
};
|
|
15055
16150
|
}, []);
|
|
15056
|
-
const refreshStateRules = (0,
|
|
16151
|
+
const refreshStateRules = (0, import_react17.useCallback)(() => {
|
|
15057
16152
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
15058
16153
|
}, []);
|
|
15059
|
-
const processConfigRequest = (0,
|
|
16154
|
+
const processConfigRequest = (0, import_react17.useCallback)((insertAfterVal) => {
|
|
15060
16155
|
const tracker = getSectionsTracker();
|
|
15061
16156
|
let entries = [];
|
|
15062
16157
|
try {
|
|
@@ -15079,7 +16174,7 @@ function OhhwellsBridge() {
|
|
|
15079
16174
|
}
|
|
15080
16175
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
15081
16176
|
}, [isEditMode]);
|
|
15082
|
-
const deactivate = (0,
|
|
16177
|
+
const deactivate = (0, import_react17.useCallback)(() => {
|
|
15083
16178
|
const el = activeElRef.current;
|
|
15084
16179
|
if (!el) return;
|
|
15085
16180
|
const isFormBlock = el.dataset.ohwEditable === "form";
|
|
@@ -15120,12 +16215,12 @@ function OhhwellsBridge() {
|
|
|
15120
16215
|
setToolbarShowEditLink(false);
|
|
15121
16216
|
postToParent2({ type: "ow:exit-edit" });
|
|
15122
16217
|
}, [postToParent2]);
|
|
15123
|
-
const clearSelectedAttr = (0,
|
|
16218
|
+
const clearSelectedAttr = (0, import_react17.useCallback)(() => {
|
|
15124
16219
|
document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
|
|
15125
16220
|
el.removeAttribute("data-ohw-selected");
|
|
15126
16221
|
});
|
|
15127
16222
|
}, []);
|
|
15128
|
-
const deselect = (0,
|
|
16223
|
+
const deselect = (0, import_react17.useCallback)(() => {
|
|
15129
16224
|
clearSelectedAttr();
|
|
15130
16225
|
selectedElRef.current = null;
|
|
15131
16226
|
selectedHrefKeyRef.current = null;
|
|
@@ -15154,11 +16249,12 @@ function OhhwellsBridge() {
|
|
|
15154
16249
|
setToolbarVariant("none");
|
|
15155
16250
|
}
|
|
15156
16251
|
}, [clearSelectedAttr]);
|
|
15157
|
-
const markSelected = (0,
|
|
16252
|
+
const markSelected = (0, import_react17.useCallback)((el) => {
|
|
15158
16253
|
clearSelectedAttr();
|
|
16254
|
+
el.removeAttribute("data-ohw-hovered");
|
|
15159
16255
|
el.setAttribute("data-ohw-selected", "");
|
|
15160
16256
|
}, [clearSelectedAttr]);
|
|
15161
|
-
const resolveHrefKeyElement = (0,
|
|
16257
|
+
const resolveHrefKeyElement = (0, import_react17.useCallback)((hrefKey) => {
|
|
15162
16258
|
if (isFooterHrefKey(hrefKey)) {
|
|
15163
16259
|
return document.querySelector(
|
|
15164
16260
|
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
@@ -15173,7 +16269,7 @@ function OhhwellsBridge() {
|
|
|
15173
16269
|
`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
15174
16270
|
);
|
|
15175
16271
|
}, []);
|
|
15176
|
-
const resyncSelectedNavigationItem = (0,
|
|
16272
|
+
const resyncSelectedNavigationItem = (0, import_react17.useCallback)(() => {
|
|
15177
16273
|
const hrefKey = selectedHrefKeyRef.current;
|
|
15178
16274
|
if (hrefKey) {
|
|
15179
16275
|
const link = resolveHrefKeyElement(hrefKey);
|
|
@@ -15211,7 +16307,7 @@ function OhhwellsBridge() {
|
|
|
15211
16307
|
);
|
|
15212
16308
|
}
|
|
15213
16309
|
}, [resolveHrefKeyElement]);
|
|
15214
|
-
const reselectNavigationItem = (0,
|
|
16310
|
+
const reselectNavigationItem = (0, import_react17.useCallback)((navAnchor) => {
|
|
15215
16311
|
selectedElRef.current = navAnchor;
|
|
15216
16312
|
selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
|
|
15217
16313
|
selectedFooterColAttrRef.current = null;
|
|
@@ -15242,7 +16338,7 @@ function OhhwellsBridge() {
|
|
|
15242
16338
|
setToolbarShowEditLink(false);
|
|
15243
16339
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
15244
16340
|
}, [markSelected]);
|
|
15245
|
-
const commitNavigationTextEdit = (0,
|
|
16341
|
+
const commitNavigationTextEdit = (0, import_react17.useCallback)((navAnchor) => {
|
|
15246
16342
|
const el = activeElRef.current;
|
|
15247
16343
|
if (!el) return;
|
|
15248
16344
|
const key = el.dataset.ohwKey;
|
|
@@ -15275,7 +16371,7 @@ function OhhwellsBridge() {
|
|
|
15275
16371
|
postToParent2({ type: "ow:exit-edit" });
|
|
15276
16372
|
reselectNavigationItem(navAnchor);
|
|
15277
16373
|
}, [postToParent2, reselectNavigationItem]);
|
|
15278
|
-
const handleAddTopLevelNavItem = (0,
|
|
16374
|
+
const handleAddTopLevelNavItem = (0, import_react17.useCallback)(() => {
|
|
15279
16375
|
const items = listNavbarRootItems();
|
|
15280
16376
|
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
15281
16377
|
deselectRef.current();
|
|
@@ -15287,7 +16383,7 @@ function OhhwellsBridge() {
|
|
|
15287
16383
|
intent: "add-nav"
|
|
15288
16384
|
});
|
|
15289
16385
|
}, []);
|
|
15290
|
-
const maybeWarnNavLinkDropdownConflict = (0,
|
|
16386
|
+
const maybeWarnNavLinkDropdownConflict = (0, import_react17.useCallback)(
|
|
15291
16387
|
(anchor) => {
|
|
15292
16388
|
if (!isNavbarHrefKey(anchor.getAttribute("data-ohw-href-key"))) return;
|
|
15293
16389
|
if (!navDropdownsOpenOnClick()) return;
|
|
@@ -15300,7 +16396,7 @@ function OhhwellsBridge() {
|
|
|
15300
16396
|
},
|
|
15301
16397
|
[postToParent2]
|
|
15302
16398
|
);
|
|
15303
|
-
const handleNavDropdownOpenChange = (0,
|
|
16399
|
+
const handleNavDropdownOpenChange = (0, import_react17.useCallback)((open) => {
|
|
15304
16400
|
const selected = selectedElRef.current;
|
|
15305
16401
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
15306
16402
|
setNavGroupForceOpen(selected, open);
|
|
@@ -15312,7 +16408,7 @@ function OhhwellsBridge() {
|
|
|
15312
16408
|
}
|
|
15313
16409
|
});
|
|
15314
16410
|
}, []);
|
|
15315
|
-
const handleFooterHeadingVisibleChange = (0,
|
|
16411
|
+
const handleFooterHeadingVisibleChange = (0, import_react17.useCallback)(
|
|
15316
16412
|
(visible) => {
|
|
15317
16413
|
const selected = selectedElRef.current;
|
|
15318
16414
|
if (!selected || !isFooterFrameSelectionRef.current) return;
|
|
@@ -15336,7 +16432,7 @@ function OhhwellsBridge() {
|
|
|
15336
16432
|
},
|
|
15337
16433
|
[postToParent2]
|
|
15338
16434
|
);
|
|
15339
|
-
const enterEditOnNewItem = (0,
|
|
16435
|
+
const enterEditOnNewItem = (0, import_react17.useCallback)((anchor) => {
|
|
15340
16436
|
const label = anchor.querySelector('[data-ohw-editable="text"]');
|
|
15341
16437
|
if (!label) {
|
|
15342
16438
|
selectRef.current(anchor);
|
|
@@ -15345,7 +16441,7 @@ function OhhwellsBridge() {
|
|
|
15345
16441
|
setNavGroupForceOpen(anchor, true);
|
|
15346
16442
|
activateRef.current(label);
|
|
15347
16443
|
}, []);
|
|
15348
|
-
const handleAddChildItem = (0,
|
|
16444
|
+
const handleAddChildItem = (0, import_react17.useCallback)(() => {
|
|
15349
16445
|
const selected = selectedElRef.current;
|
|
15350
16446
|
if (!selected) return;
|
|
15351
16447
|
const socialsRow = isSocialsRow(selected) ? selected : findSocialsRow(selected);
|
|
@@ -15457,7 +16553,7 @@ function OhhwellsBridge() {
|
|
|
15457
16553
|
enterEditOnNewItem(result.anchor);
|
|
15458
16554
|
});
|
|
15459
16555
|
}, [enterEditOnNewItem, isFooterFrameSelection, maybeWarnNavLinkDropdownConflict, postToParent2]);
|
|
15460
|
-
const handleAddFooterColumn = (0,
|
|
16556
|
+
const handleAddFooterColumn = (0, import_react17.useCallback)(() => {
|
|
15461
16557
|
if (!canAddFooterColumn()) {
|
|
15462
16558
|
postToParent2({
|
|
15463
16559
|
type: "ow:toast",
|
|
@@ -15478,7 +16574,7 @@ function OhhwellsBridge() {
|
|
|
15478
16574
|
selectRef.current(result.firstLink);
|
|
15479
16575
|
});
|
|
15480
16576
|
}, [postToParent2]);
|
|
15481
|
-
const clearFooterDragVisuals = (0,
|
|
16577
|
+
const clearFooterDragVisuals = (0, import_react17.useCallback)(() => {
|
|
15482
16578
|
footerDragRef.current = null;
|
|
15483
16579
|
setSiblingHintRects([]);
|
|
15484
16580
|
setFooterDropSlots([]);
|
|
@@ -15487,7 +16583,7 @@ function OhhwellsBridge() {
|
|
|
15487
16583
|
setIsItemDragging(false);
|
|
15488
16584
|
unlockFooterDragInteraction();
|
|
15489
16585
|
}, []);
|
|
15490
|
-
const refreshFooterDragVisuals = (0,
|
|
16586
|
+
const refreshFooterDragVisuals = (0, import_react17.useCallback)((session, activeSlot, clientX, clientY) => {
|
|
15491
16587
|
const dragged = session.draggedEl;
|
|
15492
16588
|
setDraggedItemRect(dragged.getBoundingClientRect());
|
|
15493
16589
|
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
@@ -15519,13 +16615,13 @@ function OhhwellsBridge() {
|
|
|
15519
16615
|
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
15520
16616
|
setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
15521
16617
|
}, []);
|
|
15522
|
-
const refreshFooterDragVisualsRef = (0,
|
|
16618
|
+
const refreshFooterDragVisualsRef = (0, import_react17.useRef)(refreshFooterDragVisuals);
|
|
15523
16619
|
refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
|
|
15524
|
-
const commitFooterDragRef = (0,
|
|
16620
|
+
const commitFooterDragRef = (0, import_react17.useRef)(() => {
|
|
15525
16621
|
});
|
|
15526
|
-
const beginFooterDragRef = (0,
|
|
16622
|
+
const beginFooterDragRef = (0, import_react17.useRef)(() => {
|
|
15527
16623
|
});
|
|
15528
|
-
const beginFooterDrag = (0,
|
|
16624
|
+
const beginFooterDrag = (0, import_react17.useCallback)(
|
|
15529
16625
|
(session) => {
|
|
15530
16626
|
const rect = session.draggedEl.getBoundingClientRect();
|
|
15531
16627
|
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
@@ -15545,7 +16641,7 @@ function OhhwellsBridge() {
|
|
|
15545
16641
|
[refreshFooterDragVisuals]
|
|
15546
16642
|
);
|
|
15547
16643
|
beginFooterDragRef.current = beginFooterDrag;
|
|
15548
|
-
const commitFooterDrag = (0,
|
|
16644
|
+
const commitFooterDrag = (0, import_react17.useCallback)(
|
|
15549
16645
|
(clientX, clientY) => {
|
|
15550
16646
|
const session = footerDragRef.current;
|
|
15551
16647
|
if (!session) {
|
|
@@ -15673,7 +16769,7 @@ function OhhwellsBridge() {
|
|
|
15673
16769
|
[clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
|
|
15674
16770
|
);
|
|
15675
16771
|
commitFooterDragRef.current = commitFooterDrag;
|
|
15676
|
-
const startFooterLinkDrag = (0,
|
|
16772
|
+
const startFooterLinkDrag = (0, import_react17.useCallback)(
|
|
15677
16773
|
(anchor, clientX, clientY, wasSelected) => {
|
|
15678
16774
|
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
15679
16775
|
if (!hrefKey) return false;
|
|
@@ -15709,7 +16805,7 @@ function OhhwellsBridge() {
|
|
|
15709
16805
|
},
|
|
15710
16806
|
[beginFooterDrag]
|
|
15711
16807
|
);
|
|
15712
|
-
const startFooterColumnDrag = (0,
|
|
16808
|
+
const startFooterColumnDrag = (0, import_react17.useCallback)(
|
|
15713
16809
|
(columnEl, clientX, clientY, wasSelected) => {
|
|
15714
16810
|
const columns = listFooterColumns();
|
|
15715
16811
|
const idx = columns.indexOf(columnEl);
|
|
@@ -15729,7 +16825,7 @@ function OhhwellsBridge() {
|
|
|
15729
16825
|
},
|
|
15730
16826
|
[beginFooterDrag]
|
|
15731
16827
|
);
|
|
15732
|
-
const handleItemDragStart = (0,
|
|
16828
|
+
const handleItemDragStart = (0, import_react17.useCallback)(
|
|
15733
16829
|
(e) => {
|
|
15734
16830
|
const selected = selectedElRef.current;
|
|
15735
16831
|
if (!selected) {
|
|
@@ -15749,7 +16845,7 @@ function OhhwellsBridge() {
|
|
|
15749
16845
|
},
|
|
15750
16846
|
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
|
|
15751
16847
|
);
|
|
15752
|
-
const handleItemDragEnd = (0,
|
|
16848
|
+
const handleItemDragEnd = (0, import_react17.useCallback)(
|
|
15753
16849
|
(e) => {
|
|
15754
16850
|
if (footerDragRef.current) {
|
|
15755
16851
|
const x = e?.clientX;
|
|
@@ -15775,7 +16871,7 @@ function OhhwellsBridge() {
|
|
|
15775
16871
|
},
|
|
15776
16872
|
[commitFooterDrag, commitNavDrag, navDragRef]
|
|
15777
16873
|
);
|
|
15778
|
-
const handleItemChromePointerDown = (0,
|
|
16874
|
+
const handleItemChromePointerDown = (0, import_react17.useCallback)((e) => {
|
|
15779
16875
|
if (e.button !== 0) return;
|
|
15780
16876
|
const selected = selectedElRef.current;
|
|
15781
16877
|
if (!selected) return;
|
|
@@ -15806,7 +16902,7 @@ function OhhwellsBridge() {
|
|
|
15806
16902
|
}
|
|
15807
16903
|
if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
|
|
15808
16904
|
}, [armNavPressFromChrome]);
|
|
15809
|
-
const handleItemChromeClick = (0,
|
|
16905
|
+
const handleItemChromeClick = (0, import_react17.useCallback)((clientX, clientY) => {
|
|
15810
16906
|
if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
|
|
15811
16907
|
suppressNextClickRef.current = false;
|
|
15812
16908
|
return;
|
|
@@ -15819,7 +16915,7 @@ function OhhwellsBridge() {
|
|
|
15819
16915
|
}, []);
|
|
15820
16916
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
15821
16917
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
15822
|
-
const select = (0,
|
|
16918
|
+
const select = (0, import_react17.useCallback)((anchor) => {
|
|
15823
16919
|
if (!isNavigationItem2(anchor)) return;
|
|
15824
16920
|
if (activeElRef.current) deactivate();
|
|
15825
16921
|
aiSectionApiRef.current?.selectFromElement(anchor);
|
|
@@ -15862,7 +16958,7 @@ function OhhwellsBridge() {
|
|
|
15862
16958
|
setFloatingPanel(null);
|
|
15863
16959
|
setLogoSizeDraft(null);
|
|
15864
16960
|
}, [deactivate, markSelected]);
|
|
15865
|
-
const selectFrame = (0,
|
|
16961
|
+
const selectFrame = (0, import_react17.useCallback)((el) => {
|
|
15866
16962
|
if (!isNavigationContainer(el)) return;
|
|
15867
16963
|
if (activeElRef.current) deactivate();
|
|
15868
16964
|
aiSectionApiRef.current?.selectFromElement(el);
|
|
@@ -15913,7 +17009,7 @@ function OhhwellsBridge() {
|
|
|
15913
17009
|
setFloatingPanel(null);
|
|
15914
17010
|
setLogoSizeDraft(null);
|
|
15915
17011
|
}, [deactivate, markSelected, postToParent2]);
|
|
15916
|
-
const selectLogo = (0,
|
|
17012
|
+
const selectLogo = (0, import_react17.useCallback)(
|
|
15917
17013
|
(logoEl) => {
|
|
15918
17014
|
if (activeElRef.current) deactivate();
|
|
15919
17015
|
selectedElRef.current = logoEl;
|
|
@@ -15942,7 +17038,7 @@ function OhhwellsBridge() {
|
|
|
15942
17038
|
},
|
|
15943
17039
|
[deactivate, markSelected]
|
|
15944
17040
|
);
|
|
15945
|
-
const openLogoSizePanel = (0,
|
|
17041
|
+
const openLogoSizePanel = (0, import_react17.useCallback)((logoEl) => {
|
|
15946
17042
|
const placement = getLogoPlacement(logoEl);
|
|
15947
17043
|
const draft = readLogoSizeState(editContentRef.current, placement);
|
|
15948
17044
|
setLogoSizeDraft(draft);
|
|
@@ -15955,7 +17051,7 @@ function OhhwellsBridge() {
|
|
|
15955
17051
|
placement
|
|
15956
17052
|
});
|
|
15957
17053
|
}, []);
|
|
15958
|
-
const openSocialsDisplayPanel = (0,
|
|
17054
|
+
const openSocialsDisplayPanel = (0, import_react17.useCallback)((row) => {
|
|
15959
17055
|
setParentScrollSnap(parentScrollRef.current);
|
|
15960
17056
|
setFloatingPanel({
|
|
15961
17057
|
key: "socials-display",
|
|
@@ -15965,7 +17061,7 @@ function OhhwellsBridge() {
|
|
|
15965
17061
|
row
|
|
15966
17062
|
});
|
|
15967
17063
|
}, []);
|
|
15968
|
-
const changeSocialsDisplay = (0,
|
|
17064
|
+
const changeSocialsDisplay = (0, import_react17.useCallback)(
|
|
15969
17065
|
(row, next) => {
|
|
15970
17066
|
if (next.icon) {
|
|
15971
17067
|
const missing = socialsMissingIcons(row);
|
|
@@ -15988,17 +17084,17 @@ function OhhwellsBridge() {
|
|
|
15988
17084
|
},
|
|
15989
17085
|
[]
|
|
15990
17086
|
);
|
|
15991
|
-
const closeFloatingPanelOnly = (0,
|
|
17087
|
+
const closeFloatingPanelOnly = (0, import_react17.useCallback)(() => {
|
|
15992
17088
|
setFloatingPanel(null);
|
|
15993
17089
|
setLogoSizeDraft(null);
|
|
15994
17090
|
}, []);
|
|
15995
17091
|
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
15996
|
-
const closeFloatingPanelAndDeselect = (0,
|
|
17092
|
+
const closeFloatingPanelAndDeselect = (0, import_react17.useCallback)(() => {
|
|
15997
17093
|
setFloatingPanel(null);
|
|
15998
17094
|
setLogoSizeDraft(null);
|
|
15999
17095
|
deselectRef.current();
|
|
16000
17096
|
}, []);
|
|
16001
|
-
(0,
|
|
17097
|
+
(0, import_react17.useEffect)(() => {
|
|
16002
17098
|
const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
|
|
16003
17099
|
if (!session || !logoSizeDraft) {
|
|
16004
17100
|
postToParentRef.current({ type: "ow:logo-size-panel", open: false });
|
|
@@ -16017,7 +17113,7 @@ function OhhwellsBridge() {
|
|
|
16017
17113
|
max: LOGO_SIZE_MAX
|
|
16018
17114
|
});
|
|
16019
17115
|
}, [floatingPanel, logoSizeDraft, editorViewport]);
|
|
16020
|
-
const persistLogoSizeDraft = (0,
|
|
17116
|
+
const persistLogoSizeDraft = (0, import_react17.useCallback)(
|
|
16021
17117
|
(placement, draft) => {
|
|
16022
17118
|
const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
|
|
16023
17119
|
const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
|
|
@@ -16057,7 +17153,7 @@ function OhhwellsBridge() {
|
|
|
16057
17153
|
},
|
|
16058
17154
|
[postToParent2]
|
|
16059
17155
|
);
|
|
16060
|
-
const activate = (0,
|
|
17156
|
+
const activate = (0, import_react17.useCallback)((el, options) => {
|
|
16061
17157
|
if (activeElRef.current === el) return;
|
|
16062
17158
|
if (isIconEditable(el)) return;
|
|
16063
17159
|
if (el.hasAttribute("data-ohw-social-label")) return;
|
|
@@ -16141,8 +17237,8 @@ function OhhwellsBridge() {
|
|
|
16141
17237
|
openLogoSizePanelRef.current = openLogoSizePanel;
|
|
16142
17238
|
deselectRef.current = deselect;
|
|
16143
17239
|
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
16144
|
-
const lastSiteWideScopeRef = (0,
|
|
16145
|
-
(0,
|
|
17240
|
+
const lastSiteWideScopeRef = (0, import_react17.useRef)(null);
|
|
17241
|
+
(0, import_react17.useEffect)(() => {
|
|
16146
17242
|
if (!isEditMode) {
|
|
16147
17243
|
if (lastSiteWideScopeRef.current !== false) {
|
|
16148
17244
|
lastSiteWideScopeRef.current = false;
|
|
@@ -16168,22 +17264,34 @@ function OhhwellsBridge() {
|
|
|
16168
17264
|
isFooterFrameSelection,
|
|
16169
17265
|
postToParent2
|
|
16170
17266
|
]);
|
|
16171
|
-
(0,
|
|
17267
|
+
(0, import_react17.useLayoutEffect)(() => {
|
|
16172
17268
|
if (!subdomain || isEditMode) {
|
|
16173
17269
|
setFetchState("done");
|
|
16174
17270
|
return;
|
|
16175
17271
|
}
|
|
16176
17272
|
const applyContent = (content) => {
|
|
16177
17273
|
const imageLoads = [];
|
|
17274
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
17275
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
17276
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
17277
|
+
}
|
|
16178
17278
|
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
16179
17279
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
16180
17280
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
16181
17281
|
}
|
|
17282
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
17283
|
+
stylesRef.current = content[STYLE_STORE_KEY];
|
|
17284
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
17285
|
+
}
|
|
17286
|
+
applyBrandChrome(content);
|
|
16182
17287
|
for (const [key, val] of Object.entries(content)) {
|
|
16183
17288
|
if (key === "__ohw_sections") continue;
|
|
16184
17289
|
if (key === AI_SECTIONS_KEY) continue;
|
|
16185
17290
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
16186
17291
|
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
17292
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
17293
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17294
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
16187
17295
|
if (applyVideoSettingNode(key, val)) continue;
|
|
16188
17296
|
if (applyCarouselNode(key, val)) continue;
|
|
16189
17297
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -16241,7 +17349,9 @@ function OhhwellsBridge() {
|
|
|
16241
17349
|
let cancelled = false;
|
|
16242
17350
|
setFetchState("loading");
|
|
16243
17351
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
16244
|
-
|
|
17352
|
+
const initialPath = pathname;
|
|
17353
|
+
fetchedContentPaths.add(`${subdomain}::${initialPath}`);
|
|
17354
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
16245
17355
|
if (cancelled) return;
|
|
16246
17356
|
const content = data?.content ?? {};
|
|
16247
17357
|
contentCache.set(subdomain, content);
|
|
@@ -16254,7 +17364,7 @@ function OhhwellsBridge() {
|
|
|
16254
17364
|
cancelled = true;
|
|
16255
17365
|
};
|
|
16256
17366
|
}, [subdomain, isEditMode]);
|
|
16257
|
-
(0,
|
|
17367
|
+
(0, import_react17.useEffect)(() => {
|
|
16258
17368
|
if (!isEditMode) return;
|
|
16259
17369
|
const resolveIndex = (form, clientY) => {
|
|
16260
17370
|
const wrappers = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== fieldDragRef.current?.key);
|
|
@@ -16295,7 +17405,7 @@ function OhhwellsBridge() {
|
|
|
16295
17405
|
window.removeEventListener("drop", onDrop, true);
|
|
16296
17406
|
};
|
|
16297
17407
|
}, [buildFieldDropSlots, isEditMode, persistFields, selectField]);
|
|
16298
|
-
(0,
|
|
17408
|
+
(0, import_react17.useEffect)(() => {
|
|
16299
17409
|
if (!isEditMode) return;
|
|
16300
17410
|
const mark = () => document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
16301
17411
|
markFormFields(form);
|
|
@@ -16307,7 +17417,7 @@ function OhhwellsBridge() {
|
|
|
16307
17417
|
});
|
|
16308
17418
|
return () => observer.disconnect();
|
|
16309
17419
|
}, [isEditMode, fetchState, pathname]);
|
|
16310
|
-
(0,
|
|
17420
|
+
(0, import_react17.useEffect)(() => {
|
|
16311
17421
|
if (!isEditMode) return;
|
|
16312
17422
|
let saveTimer = null;
|
|
16313
17423
|
const onInput = (e) => {
|
|
@@ -16329,14 +17439,14 @@ function OhhwellsBridge() {
|
|
|
16329
17439
|
document.addEventListener("input", onInput, true);
|
|
16330
17440
|
return () => document.removeEventListener("input", onInput, true);
|
|
16331
17441
|
}, [isEditMode, persistFields]);
|
|
16332
|
-
(0,
|
|
17442
|
+
(0, import_react17.useEffect)(() => {
|
|
16333
17443
|
if (isEditMode || fetchState !== "done") return;
|
|
16334
17444
|
const content = contentCache.get(subdomain) ?? {};
|
|
16335
17445
|
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
16336
17446
|
reconcileFieldsFromContent(form, content);
|
|
16337
17447
|
});
|
|
16338
17448
|
}, [isEditMode, fetchState, subdomain]);
|
|
16339
|
-
(0,
|
|
17449
|
+
(0, import_react17.useEffect)(() => {
|
|
16340
17450
|
if (!isEditMode) return;
|
|
16341
17451
|
const swallow = (e) => {
|
|
16342
17452
|
const target = e.target;
|
|
@@ -16345,12 +17455,12 @@ function OhhwellsBridge() {
|
|
|
16345
17455
|
document.addEventListener("submit", swallow, true);
|
|
16346
17456
|
return () => document.removeEventListener("submit", swallow, true);
|
|
16347
17457
|
}, [isEditMode]);
|
|
16348
|
-
(0,
|
|
17458
|
+
(0, import_react17.useEffect)(() => {
|
|
16349
17459
|
if (isEditMode || fetchState !== "done") return;
|
|
16350
17460
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
16351
17461
|
bindPublishedForms(apiUrl, subdomain, contentCache.get(subdomain) ?? {});
|
|
16352
17462
|
}, [isEditMode, fetchState, subdomain]);
|
|
16353
|
-
(0,
|
|
17463
|
+
(0, import_react17.useEffect)(() => {
|
|
16354
17464
|
if (!subdomain || isEditMode) return;
|
|
16355
17465
|
let debounceTimer = null;
|
|
16356
17466
|
let observer = null;
|
|
@@ -16361,10 +17471,21 @@ function OhhwellsBridge() {
|
|
|
16361
17471
|
initSectionInstancesFromContent(content, window.location.pathname);
|
|
16362
17472
|
observer?.disconnect();
|
|
16363
17473
|
try {
|
|
17474
|
+
applyBrandChrome(content);
|
|
17475
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
17476
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
17477
|
+
}
|
|
17478
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
17479
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
17480
|
+
}
|
|
16364
17481
|
for (const [key, val] of Object.entries(content)) {
|
|
16365
17482
|
if (key === "__ohw_sections") continue;
|
|
16366
17483
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
16367
17484
|
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
17485
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
17486
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17487
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17488
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
16368
17489
|
if (applyVideoSettingNode(key, val)) continue;
|
|
16369
17490
|
if (applyCarouselNode(key, val)) continue;
|
|
16370
17491
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -16407,6 +17528,17 @@ function OhhwellsBridge() {
|
|
|
16407
17528
|
debounceTimer = setTimeout(applyFromCache, 150);
|
|
16408
17529
|
};
|
|
16409
17530
|
applyFromCache();
|
|
17531
|
+
const pathCacheKey = `${subdomain}::${pathname}`;
|
|
17532
|
+
if (!fetchedContentPaths.has(pathCacheKey)) {
|
|
17533
|
+
fetchedContentPaths.add(pathCacheKey);
|
|
17534
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
17535
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
17536
|
+
if (!data?.content) return;
|
|
17537
|
+
contentCache.set(subdomain, data.content);
|
|
17538
|
+
applyFromCache();
|
|
17539
|
+
}).catch(() => {
|
|
17540
|
+
});
|
|
17541
|
+
}
|
|
16410
17542
|
observer = new MutationObserver(scheduleApply);
|
|
16411
17543
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
16412
17544
|
return () => {
|
|
@@ -16414,16 +17546,16 @@ function OhhwellsBridge() {
|
|
|
16414
17546
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
16415
17547
|
};
|
|
16416
17548
|
}, [subdomain, isEditMode, pathname]);
|
|
16417
|
-
(0,
|
|
17549
|
+
(0, import_react17.useLayoutEffect)(() => {
|
|
16418
17550
|
const el = document.getElementById("ohw-loader");
|
|
16419
17551
|
if (!el) return;
|
|
16420
17552
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
16421
17553
|
el.style.display = visible ? "flex" : "none";
|
|
16422
17554
|
}, [subdomain, fetchState]);
|
|
16423
|
-
(0,
|
|
17555
|
+
(0, import_react17.useEffect)(() => {
|
|
16424
17556
|
postToParent2({ type: "ow:navigation", path: pathname });
|
|
16425
17557
|
}, [pathname, postToParent2]);
|
|
16426
|
-
(0,
|
|
17558
|
+
(0, import_react17.useEffect)(() => {
|
|
16427
17559
|
if (!isEditMode) return;
|
|
16428
17560
|
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
16429
17561
|
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
@@ -16431,7 +17563,7 @@ function OhhwellsBridge() {
|
|
|
16431
17563
|
deselectRef.current();
|
|
16432
17564
|
deactivateRef.current();
|
|
16433
17565
|
}, [pathname, isEditMode]);
|
|
16434
|
-
(0,
|
|
17566
|
+
(0, import_react17.useEffect)(() => {
|
|
16435
17567
|
const contentForNav = () => {
|
|
16436
17568
|
if (isEditMode) return editContentRef.current;
|
|
16437
17569
|
if (!subdomain) return {};
|
|
@@ -16498,31 +17630,36 @@ function OhhwellsBridge() {
|
|
|
16498
17630
|
observer?.disconnect();
|
|
16499
17631
|
};
|
|
16500
17632
|
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
16501
|
-
(0,
|
|
17633
|
+
(0, import_react17.useEffect)(() => {
|
|
16502
17634
|
if (!isEditMode) return;
|
|
17635
|
+
let lastPosted = 0;
|
|
16503
17636
|
const measure = () => {
|
|
16504
17637
|
const h = document.body.scrollHeight;
|
|
16505
|
-
if (h > 50
|
|
17638
|
+
if (h > 50 && Math.abs(h - lastPosted) > 1) {
|
|
17639
|
+
lastPosted = h;
|
|
17640
|
+
postToParent2({ type: "ow:height", height: h });
|
|
17641
|
+
}
|
|
17642
|
+
};
|
|
17643
|
+
let raf = null;
|
|
17644
|
+
const schedule = () => {
|
|
17645
|
+
if (raf != null) return;
|
|
17646
|
+
raf = requestAnimationFrame(() => {
|
|
17647
|
+
raf = null;
|
|
17648
|
+
measure();
|
|
17649
|
+
});
|
|
16506
17650
|
};
|
|
16507
17651
|
const t1 = setTimeout(measure, 50);
|
|
16508
17652
|
const t2 = setTimeout(measure, 500);
|
|
16509
|
-
|
|
16510
|
-
|
|
16511
|
-
const handleResize = () => {
|
|
16512
|
-
if (window.innerWidth === lastWidth) return;
|
|
16513
|
-
lastWidth = window.innerWidth;
|
|
16514
|
-
if (resizeTimer) clearTimeout(resizeTimer);
|
|
16515
|
-
resizeTimer = setTimeout(measure, 150);
|
|
16516
|
-
};
|
|
16517
|
-
window.addEventListener("resize", handleResize);
|
|
17653
|
+
const ro = new ResizeObserver(schedule);
|
|
17654
|
+
ro.observe(document.body);
|
|
16518
17655
|
return () => {
|
|
16519
17656
|
clearTimeout(t1);
|
|
16520
17657
|
clearTimeout(t2);
|
|
16521
|
-
if (
|
|
16522
|
-
|
|
17658
|
+
if (raf != null) cancelAnimationFrame(raf);
|
|
17659
|
+
ro.disconnect();
|
|
16523
17660
|
};
|
|
16524
17661
|
}, [pathname, isEditMode, postToParent2]);
|
|
16525
|
-
(0,
|
|
17662
|
+
(0, import_react17.useEffect)(() => {
|
|
16526
17663
|
if (!subdomainFromQuery || isEditMode) return;
|
|
16527
17664
|
const handleClick = (e) => {
|
|
16528
17665
|
const anchor = e.target.closest("a");
|
|
@@ -16538,7 +17675,7 @@ function OhhwellsBridge() {
|
|
|
16538
17675
|
document.addEventListener("click", handleClick, true);
|
|
16539
17676
|
return () => document.removeEventListener("click", handleClick, true);
|
|
16540
17677
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
16541
|
-
(0,
|
|
17678
|
+
(0, import_react17.useEffect)(() => {
|
|
16542
17679
|
if (!isEditMode) {
|
|
16543
17680
|
editStylesRef.current?.base.remove();
|
|
16544
17681
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -16700,16 +17837,21 @@ function OhhwellsBridge() {
|
|
|
16700
17837
|
return;
|
|
16701
17838
|
}
|
|
16702
17839
|
const target = e.target;
|
|
17840
|
+
if (target.closest("[data-ohw-ai-review]")) return;
|
|
16703
17841
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
16704
17842
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
16705
17843
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
16706
17844
|
if (isInsideLinkEditor(target)) return;
|
|
17845
|
+
if (isInsideFloatingPanel(target)) return;
|
|
16707
17846
|
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
16708
17847
|
if (target.closest(
|
|
16709
17848
|
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
16710
17849
|
)) {
|
|
16711
17850
|
return;
|
|
16712
17851
|
}
|
|
17852
|
+
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
17853
|
+
clearMediaSelectionRef.current();
|
|
17854
|
+
}
|
|
16713
17855
|
{
|
|
16714
17856
|
const formEl = getFormElement(target);
|
|
16715
17857
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -16857,8 +17999,11 @@ function OhhwellsBridge() {
|
|
|
16857
17999
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
16858
18000
|
e.preventDefault();
|
|
16859
18001
|
e.stopPropagation();
|
|
16860
|
-
|
|
16861
|
-
|
|
18002
|
+
if (selectedMediaElRef.current === editable) {
|
|
18003
|
+
postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
|
|
18004
|
+
} else {
|
|
18005
|
+
selectMediaElementRef.current(editable);
|
|
18006
|
+
}
|
|
16862
18007
|
return;
|
|
16863
18008
|
}
|
|
16864
18009
|
const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
|
|
@@ -16977,10 +18122,12 @@ function OhhwellsBridge() {
|
|
|
16977
18122
|
};
|
|
16978
18123
|
const handleDblClick = (e) => {
|
|
16979
18124
|
const target = e.target;
|
|
18125
|
+
if (target.closest("[data-ohw-ai-review]")) return;
|
|
16980
18126
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
16981
18127
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
16982
18128
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
16983
18129
|
if (isInsideLinkEditor(target)) return;
|
|
18130
|
+
if (isInsideFloatingPanel(target)) return;
|
|
16984
18131
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
16985
18132
|
return;
|
|
16986
18133
|
}
|
|
@@ -17021,11 +18168,14 @@ function OhhwellsBridge() {
|
|
|
17021
18168
|
setSiblingHintRects([]);
|
|
17022
18169
|
return;
|
|
17023
18170
|
}
|
|
17024
|
-
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || target.
|
|
18171
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
|
|
17025
18172
|
hoveredItemElRef.current = null;
|
|
17026
18173
|
setHoveredItemRect(null);
|
|
17027
18174
|
hoveredNavContainerRef.current = null;
|
|
17028
18175
|
setHoveredNavContainerRect(null);
|
|
18176
|
+
siblingHintElRef.current = null;
|
|
18177
|
+
setSiblingHintRect(null);
|
|
18178
|
+
setSiblingHintRects([]);
|
|
17029
18179
|
return;
|
|
17030
18180
|
}
|
|
17031
18181
|
{
|
|
@@ -17043,6 +18193,16 @@ function OhhwellsBridge() {
|
|
|
17043
18193
|
return;
|
|
17044
18194
|
}
|
|
17045
18195
|
}
|
|
18196
|
+
if (allowNavContainerHover) {
|
|
18197
|
+
const socialsRow = isSocialsRow(target) ? target : null;
|
|
18198
|
+
if (socialsRow && !getSocialItem(target) && selected2 !== socialsRow) {
|
|
18199
|
+
hoveredNavContainerRef.current = socialsRow;
|
|
18200
|
+
setHoveredNavContainerRect(socialsRow.getBoundingClientRect());
|
|
18201
|
+
hoveredItemElRef.current = null;
|
|
18202
|
+
setHoveredItemRect(null);
|
|
18203
|
+
return;
|
|
18204
|
+
}
|
|
18205
|
+
}
|
|
17046
18206
|
if (allowFooterLinksHover) {
|
|
17047
18207
|
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
17048
18208
|
if (!navContainer) {
|
|
@@ -17128,13 +18288,12 @@ function OhhwellsBridge() {
|
|
|
17128
18288
|
clearHrefKeyHover(hoverTarget);
|
|
17129
18289
|
hoveredItemElRef.current = hoverTarget;
|
|
17130
18290
|
setHoveredItemRect(hoverTarget.getBoundingClientRect());
|
|
17131
|
-
} else if (!isInsideNavigationItem(editable)) {
|
|
18291
|
+
} else if (!isInsideNavigationItem(editable) && hoverTarget !== selectedElRef.current) {
|
|
17132
18292
|
hoverTarget.setAttribute("data-ohw-hovered", "");
|
|
17133
18293
|
if (editable.closest("footer") || editable.closest('[data-ohw-section="footer"]')) {
|
|
17134
18294
|
hoveredNavContainerRef.current = null;
|
|
17135
18295
|
setHoveredNavContainerRect(null);
|
|
17136
18296
|
hoveredItemElRef.current = editable;
|
|
17137
|
-
setHoveredItemRect(editable.getBoundingClientRect());
|
|
17138
18297
|
}
|
|
17139
18298
|
}
|
|
17140
18299
|
}
|
|
@@ -17431,7 +18590,7 @@ function OhhwellsBridge() {
|
|
|
17431
18590
|
}
|
|
17432
18591
|
};
|
|
17433
18592
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
17434
|
-
if (linkPopoverOpenRef.current) {
|
|
18593
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
17435
18594
|
if (hoveredImageRef.current) {
|
|
17436
18595
|
hoveredImageRef.current = null;
|
|
17437
18596
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -17690,7 +18849,7 @@ function OhhwellsBridge() {
|
|
|
17690
18849
|
}
|
|
17691
18850
|
};
|
|
17692
18851
|
const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
|
|
17693
|
-
if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
18852
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
17694
18853
|
if (activeStateElRef.current) {
|
|
17695
18854
|
activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
|
|
17696
18855
|
activeStateElRef.current = null;
|
|
@@ -17727,6 +18886,35 @@ function OhhwellsBridge() {
|
|
|
17727
18886
|
}
|
|
17728
18887
|
}
|
|
17729
18888
|
};
|
|
18889
|
+
const probeSocialsRowAt = (clientX, clientY, fromParentViewport = false) => {
|
|
18890
|
+
const wasSocialsRow = Boolean(hoveredNavContainerRef.current?.hasAttribute(SOCIALS_ROW_ATTR));
|
|
18891
|
+
const clear = () => {
|
|
18892
|
+
if (!wasSocialsRow) return false;
|
|
18893
|
+
hoveredNavContainerRef.current = null;
|
|
18894
|
+
setHoveredNavContainerRect(null);
|
|
18895
|
+
return false;
|
|
18896
|
+
};
|
|
18897
|
+
if (linkPopoverOpenRef.current || toolbarVariantRef.current === "select-frame") return clear();
|
|
18898
|
+
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
18899
|
+
const SLACK = 6;
|
|
18900
|
+
for (const row of Array.from(document.querySelectorAll(`[${SOCIALS_ROW_ATTR}]`))) {
|
|
18901
|
+
const rect = row.getBoundingClientRect();
|
|
18902
|
+
const inside = x >= rect.left - SLACK && x <= rect.right + SLACK && y >= rect.top - SLACK && y <= rect.bottom + SLACK;
|
|
18903
|
+
if (!inside) continue;
|
|
18904
|
+
if (selectedElRef.current === row) return clear();
|
|
18905
|
+
const overItem = listSocialItems(row).some((item) => {
|
|
18906
|
+
const box = item.getBoundingClientRect();
|
|
18907
|
+
return x >= box.left && x <= box.right && y >= box.top && y <= box.bottom;
|
|
18908
|
+
});
|
|
18909
|
+
if (overItem) return clear();
|
|
18910
|
+
hoveredNavContainerRef.current = row;
|
|
18911
|
+
setHoveredNavContainerRect(rect);
|
|
18912
|
+
hoveredItemElRef.current = null;
|
|
18913
|
+
setHoveredItemRect(null);
|
|
18914
|
+
return true;
|
|
18915
|
+
}
|
|
18916
|
+
return clear();
|
|
18917
|
+
};
|
|
17730
18918
|
const probeSectionGapAt = (clientX, clientY, fromParentViewport = false) => {
|
|
17731
18919
|
if (linkPopoverOpenRef.current) {
|
|
17732
18920
|
if (hoveredGapRef.current) {
|
|
@@ -17736,7 +18924,9 @@ function OhhwellsBridge() {
|
|
|
17736
18924
|
return;
|
|
17737
18925
|
}
|
|
17738
18926
|
const { y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
17739
|
-
const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).
|
|
18927
|
+
const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
18928
|
+
(el) => !el.hasAttribute("data-ohw-ai-template-hidden") && !el.hasAttribute("data-ohw-ai-removed") && !el.hasAttribute("data-ohw-ai-replaced-by") && el.getBoundingClientRect().height > 0
|
|
18929
|
+
).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
|
|
17740
18930
|
const ZONE = 20;
|
|
17741
18931
|
for (let i = 0; i < sections.length; i++) {
|
|
17742
18932
|
const a = sections[i];
|
|
@@ -17765,8 +18955,7 @@ function OhhwellsBridge() {
|
|
|
17765
18955
|
};
|
|
17766
18956
|
const handleMouseMove = (e) => {
|
|
17767
18957
|
const { clientX, clientY } = e;
|
|
17768
|
-
if (
|
|
17769
|
-
if (isOverEditorChrome(clientX, clientY)) {
|
|
18958
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
|
|
17770
18959
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
17771
18960
|
formHoverElRef.current = null;
|
|
17772
18961
|
setFormHoverRect(null);
|
|
@@ -17774,8 +18963,15 @@ function OhhwellsBridge() {
|
|
|
17774
18963
|
setHoveredItemRect(null);
|
|
17775
18964
|
hoveredNavContainerRef.current = null;
|
|
17776
18965
|
setHoveredNavContainerRect(null);
|
|
18966
|
+
siblingHintElRef.current = null;
|
|
18967
|
+
setSiblingHintRect(null);
|
|
18968
|
+
setSiblingHintRects([]);
|
|
18969
|
+
dismissImageHover();
|
|
18970
|
+
clearImageHover();
|
|
18971
|
+
setSectionGap(null);
|
|
17777
18972
|
return;
|
|
17778
18973
|
}
|
|
18974
|
+
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
17779
18975
|
probeSectionGapAt(clientX, clientY);
|
|
17780
18976
|
probeImageAt(clientX, clientY);
|
|
17781
18977
|
probeHoverCardsAt(clientX, clientY);
|
|
@@ -17784,7 +18980,12 @@ function OhhwellsBridge() {
|
|
|
17784
18980
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
17785
18981
|
const { clientX, clientY } = e.data;
|
|
17786
18982
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
17787
|
-
if (
|
|
18983
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
18984
|
+
dismissImageHover();
|
|
18985
|
+
clearImageHover();
|
|
18986
|
+
return;
|
|
18987
|
+
}
|
|
18988
|
+
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
17788
18989
|
probeSectionGapAt(clientX, clientY);
|
|
17789
18990
|
probeImageAt(clientX, clientY);
|
|
17790
18991
|
probeHoverCardsAt(clientX, clientY);
|
|
@@ -18030,10 +19231,19 @@ function OhhwellsBridge() {
|
|
|
18030
19231
|
if (e.data?.type !== "ow:hydrate") return;
|
|
18031
19232
|
const content = e.data.content;
|
|
18032
19233
|
if (!content) return;
|
|
19234
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
19235
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
19236
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
19237
|
+
}
|
|
18033
19238
|
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
18034
19239
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
18035
19240
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
18036
19241
|
}
|
|
19242
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
19243
|
+
stylesRef.current = content[STYLE_STORE_KEY];
|
|
19244
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
19245
|
+
}
|
|
19246
|
+
applyBrandChrome(content);
|
|
18037
19247
|
let sectionsJson = null;
|
|
18038
19248
|
for (const [key, val] of Object.entries(content)) {
|
|
18039
19249
|
if (key === "__ohw_sections") {
|
|
@@ -18043,6 +19253,9 @@ function OhhwellsBridge() {
|
|
|
18043
19253
|
if (key === AI_SECTIONS_KEY) continue;
|
|
18044
19254
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
18045
19255
|
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
19256
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
19257
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
19258
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
18046
19259
|
if (applyVideoSettingNode(key, val)) continue;
|
|
18047
19260
|
if (applyCarouselNode(key, val)) continue;
|
|
18048
19261
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -18056,6 +19269,8 @@ function OhhwellsBridge() {
|
|
|
18056
19269
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
18057
19270
|
} else if (el.dataset.ohwEditable === "link") {
|
|
18058
19271
|
applyLinkHref(el, val);
|
|
19272
|
+
} else if (el.dataset.ohwEditable === "icon") {
|
|
19273
|
+
applyIconMarkup(el, val);
|
|
18059
19274
|
} else {
|
|
18060
19275
|
el.innerHTML = val;
|
|
18061
19276
|
}
|
|
@@ -18139,12 +19354,21 @@ function OhhwellsBridge() {
|
|
|
18139
19354
|
nodes: collectEditableNodes(editContentRef.current)
|
|
18140
19355
|
});
|
|
18141
19356
|
};
|
|
19357
|
+
const clearInteractionChrome = () => {
|
|
19358
|
+
deactivateRef.current();
|
|
19359
|
+
deselectRef.current();
|
|
19360
|
+
clearMediaSelectionRef.current();
|
|
19361
|
+
};
|
|
18142
19362
|
const handleAiApplyTree = (e) => {
|
|
18143
19363
|
if (e.data?.type !== "ow:ai-apply-tree") return;
|
|
18144
19364
|
const payload = e.data.payload;
|
|
18145
19365
|
if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
|
|
19366
|
+
clearInteractionChrome();
|
|
18146
19367
|
const previous = aiSectionsRef.current;
|
|
18147
|
-
const nextState = applyTreeToState(parseAiSectionsState(previous),
|
|
19368
|
+
const nextState = applyTreeToState(parseAiSectionsState(previous), {
|
|
19369
|
+
...payload,
|
|
19370
|
+
path: payload.path ?? window.location.pathname
|
|
19371
|
+
});
|
|
18148
19372
|
const nextValue = serializeAiSectionsState(nextState);
|
|
18149
19373
|
aiSectionsRef.current = nextValue;
|
|
18150
19374
|
applyAiSectionsToDom(nextState);
|
|
@@ -18164,6 +19388,7 @@ function OhhwellsBridge() {
|
|
|
18164
19388
|
if (!sectionId || sectionId === "navbar" || sectionId === "footer") return;
|
|
18165
19389
|
const exists = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
|
|
18166
19390
|
if (!exists) return;
|
|
19391
|
+
clearInteractionChrome();
|
|
18167
19392
|
const previous = aiSectionsRef.current;
|
|
18168
19393
|
const nextState = deleteSectionFromState(parseAiSectionsState(previous), sectionId);
|
|
18169
19394
|
const nextValue = serializeAiSectionsState(nextState);
|
|
@@ -18179,14 +19404,58 @@ function OhhwellsBridge() {
|
|
|
18179
19404
|
const handleAiSetSections = (e) => {
|
|
18180
19405
|
if (e.data?.type !== "ow:ai-set-sections") return;
|
|
18181
19406
|
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
19407
|
+
clearInteractionChrome();
|
|
18182
19408
|
aiSectionsRef.current = value;
|
|
18183
19409
|
applyAiSectionsToDom(parseAiSectionsState(value));
|
|
19410
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
18184
19411
|
const restoredHeight = document.documentElement.scrollHeight;
|
|
18185
19412
|
if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
|
|
18186
19413
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
|
|
18187
19414
|
postAiSectionsChanged();
|
|
18188
19415
|
};
|
|
18189
19416
|
window.addEventListener("message", handleAiSetSections);
|
|
19417
|
+
const handleMoveSection = (e) => {
|
|
19418
|
+
if (e.data?.type !== "ow:move-section") return;
|
|
19419
|
+
const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
|
|
19420
|
+
const direction = e.data.direction === "up" || e.data.direction === "down" ? e.data.direction : null;
|
|
19421
|
+
if (!instanceId || !direction) return;
|
|
19422
|
+
const entries = moveSectionInstance(instanceId, direction, window.location.pathname);
|
|
19423
|
+
if (!entries) return;
|
|
19424
|
+
const orderJson = JSON.stringify(entries);
|
|
19425
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
19426
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
19427
|
+
window.dispatchEvent(new Event("resize"));
|
|
19428
|
+
};
|
|
19429
|
+
window.addEventListener("message", handleMoveSection);
|
|
19430
|
+
const handleAiSetBrand = (e) => {
|
|
19431
|
+
if (e.data?.type !== "ow:ai-set-brand") return;
|
|
19432
|
+
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
19433
|
+
const previous = brandKitRef.current;
|
|
19434
|
+
brandKitRef.current = value;
|
|
19435
|
+
applyBrandToDom(parseBrandKit(value));
|
|
19436
|
+
if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
|
|
19437
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
19438
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
|
|
19439
|
+
postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
|
|
19440
|
+
};
|
|
19441
|
+
window.addEventListener("message", handleAiSetBrand);
|
|
19442
|
+
const handleAiSetStyles = (e) => {
|
|
19443
|
+
if (e.data?.type !== "ow:ai-set-styles") return;
|
|
19444
|
+
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
19445
|
+
const previous = stylesRef.current;
|
|
19446
|
+
stylesRef.current = value;
|
|
19447
|
+
applyStylesToDom(parseStyleStore(value));
|
|
19448
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
|
|
19449
|
+
postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
|
|
19450
|
+
};
|
|
19451
|
+
window.addEventListener("message", handleAiSetStyles);
|
|
19452
|
+
const handleGetBrand = (e) => {
|
|
19453
|
+
if (e.data?.type !== "ow:get-brand") return;
|
|
19454
|
+
const template = deriveTemplateBrand();
|
|
19455
|
+
const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
|
|
19456
|
+
postToParentRef.current({ type: "ow:brand-value", value });
|
|
19457
|
+
};
|
|
19458
|
+
window.addEventListener("message", handleGetBrand);
|
|
18190
19459
|
const handlePanelDragging = (e) => {
|
|
18191
19460
|
if (e.data?.type !== "ow:panel-dragging") return;
|
|
18192
19461
|
if (e.data.dragging) document.documentElement.setAttribute("data-ohw-panel-dragging", "");
|
|
@@ -18202,8 +19471,15 @@ function OhhwellsBridge() {
|
|
|
18202
19471
|
closeLinkPopoverRef.current();
|
|
18203
19472
|
return;
|
|
18204
19473
|
}
|
|
19474
|
+
if (floatingPanelOpenRef.current) {
|
|
19475
|
+
setFloatingPanelRef.current(null);
|
|
19476
|
+
deselectRef.current();
|
|
19477
|
+
deactivateRef.current();
|
|
19478
|
+
return;
|
|
19479
|
+
}
|
|
18205
19480
|
deselectRef.current();
|
|
18206
19481
|
deactivateRef.current();
|
|
19482
|
+
clearMediaSelectionRef.current();
|
|
18207
19483
|
};
|
|
18208
19484
|
window.addEventListener("message", handleDeactivate);
|
|
18209
19485
|
const handleToastAction = (e) => {
|
|
@@ -18289,6 +19565,10 @@ function OhhwellsBridge() {
|
|
|
18289
19565
|
const handleKeyDown = (e) => {
|
|
18290
19566
|
if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
|
|
18291
19567
|
if (e.key === "Escape" && document.querySelector("[data-ohw-more-menu]")) return;
|
|
19568
|
+
if (e.key === "Escape" && selectedMediaElRef.current) {
|
|
19569
|
+
clearMediaSelectionRef.current();
|
|
19570
|
+
return;
|
|
19571
|
+
}
|
|
18292
19572
|
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
|
|
18293
19573
|
e.preventDefault();
|
|
18294
19574
|
selectAllTextInEditable(activeElRef.current);
|
|
@@ -18448,6 +19728,12 @@ function OhhwellsBridge() {
|
|
|
18448
19728
|
if (aiSectionsRef.current) {
|
|
18449
19729
|
nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
|
|
18450
19730
|
}
|
|
19731
|
+
if (stylesRef.current) {
|
|
19732
|
+
nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
|
|
19733
|
+
}
|
|
19734
|
+
if (brandKitRef.current) {
|
|
19735
|
+
nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
|
|
19736
|
+
}
|
|
18451
19737
|
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
18452
19738
|
const formKey = formKeyOf(form);
|
|
18453
19739
|
if (!formKey) return;
|
|
@@ -18465,8 +19751,12 @@ function OhhwellsBridge() {
|
|
|
18465
19751
|
if (inserted) {
|
|
18466
19752
|
const tracker = getSectionsTracker();
|
|
18467
19753
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
18468
|
-
const
|
|
18469
|
-
|
|
19754
|
+
const reportHeight = () => {
|
|
19755
|
+
const h = document.body.scrollHeight;
|
|
19756
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
19757
|
+
};
|
|
19758
|
+
reportHeight();
|
|
19759
|
+
setTimeout(reportHeight, 500);
|
|
18470
19760
|
}
|
|
18471
19761
|
};
|
|
18472
19762
|
const handleSwitchSchedule = (e) => {
|
|
@@ -18853,19 +20143,23 @@ function OhhwellsBridge() {
|
|
|
18853
20143
|
window.removeEventListener("message", handleAiApplyTree);
|
|
18854
20144
|
window.removeEventListener("message", handleAiDeleteSection);
|
|
18855
20145
|
window.removeEventListener("message", handleAiSetSections);
|
|
20146
|
+
window.removeEventListener("message", handleMoveSection);
|
|
20147
|
+
window.removeEventListener("message", handleAiSetBrand);
|
|
20148
|
+
window.removeEventListener("message", handleAiSetStyles);
|
|
20149
|
+
window.removeEventListener("message", handleGetBrand);
|
|
18856
20150
|
window.removeEventListener("message", handlePanelDragging);
|
|
18857
20151
|
window.removeEventListener("message", handleDeactivate);
|
|
18858
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
18859
20152
|
window.removeEventListener("message", handleToastAction);
|
|
18860
20153
|
window.removeEventListener("message", handleFormCount);
|
|
18861
20154
|
window.removeEventListener("message", handleUiEscape);
|
|
20155
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
18862
20156
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
18863
20157
|
autoSaveTimers.current.clear();
|
|
18864
20158
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
18865
20159
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
18866
20160
|
};
|
|
18867
20161
|
}, [isEditMode, refreshStateRules]);
|
|
18868
|
-
(0,
|
|
20162
|
+
(0, import_react17.useEffect)(() => {
|
|
18869
20163
|
if (!isEditMode) return;
|
|
18870
20164
|
const THRESHOLD = 10;
|
|
18871
20165
|
const resolveWasSelected = (el) => {
|
|
@@ -19021,7 +20315,7 @@ function OhhwellsBridge() {
|
|
|
19021
20315
|
unlockFooterDragInteraction();
|
|
19022
20316
|
};
|
|
19023
20317
|
}, [isEditMode]);
|
|
19024
|
-
(0,
|
|
20318
|
+
(0, import_react17.useEffect)(() => {
|
|
19025
20319
|
const handler = (e) => {
|
|
19026
20320
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
19027
20321
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -19037,7 +20331,7 @@ function OhhwellsBridge() {
|
|
|
19037
20331
|
window.addEventListener("message", handler);
|
|
19038
20332
|
return () => window.removeEventListener("message", handler);
|
|
19039
20333
|
}, [processConfigRequest]);
|
|
19040
|
-
(0,
|
|
20334
|
+
(0, import_react17.useEffect)(() => {
|
|
19041
20335
|
if (!isEditMode) return;
|
|
19042
20336
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
19043
20337
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -19061,7 +20355,7 @@ function OhhwellsBridge() {
|
|
|
19061
20355
|
postToParent2({
|
|
19062
20356
|
type: "ow:ready",
|
|
19063
20357
|
version: "1",
|
|
19064
|
-
bridgeVersion: "0.1.
|
|
20358
|
+
bridgeVersion: "0.1.69",
|
|
19065
20359
|
path: pathname,
|
|
19066
20360
|
nodes: collectEditableNodes(editContentRef.current),
|
|
19067
20361
|
sections
|
|
@@ -19073,13 +20367,13 @@ function OhhwellsBridge() {
|
|
|
19073
20367
|
clearTimeout(timer);
|
|
19074
20368
|
};
|
|
19075
20369
|
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
19076
|
-
(0,
|
|
20370
|
+
(0, import_react17.useEffect)(() => {
|
|
19077
20371
|
scrollToHashSectionWhenReady();
|
|
19078
20372
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
19079
20373
|
window.addEventListener("hashchange", onHashChange);
|
|
19080
20374
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
19081
20375
|
}, [pathname]);
|
|
19082
|
-
const handleCommand = (0,
|
|
20376
|
+
const handleCommand = (0, import_react17.useCallback)((cmd) => {
|
|
19083
20377
|
const el = activeElRef.current;
|
|
19084
20378
|
const selBefore = window.getSelection();
|
|
19085
20379
|
let savedOffsets = null;
|
|
@@ -19115,7 +20409,7 @@ function OhhwellsBridge() {
|
|
|
19115
20409
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
19116
20410
|
refreshActiveCommandsRef.current();
|
|
19117
20411
|
}, []);
|
|
19118
|
-
(0,
|
|
20412
|
+
(0, import_react17.useEffect)(() => {
|
|
19119
20413
|
const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
|
|
19120
20414
|
if (!session || !logoSizeDraft) return;
|
|
19121
20415
|
const onPanelAction = (e) => {
|
|
@@ -19153,7 +20447,7 @@ function OhhwellsBridge() {
|
|
|
19153
20447
|
window.addEventListener("message", onPanelAction);
|
|
19154
20448
|
return () => window.removeEventListener("message", onPanelAction);
|
|
19155
20449
|
}, [floatingPanel, logoSizeDraft, editorViewport, persistLogoSizeDraft, closeFloatingPanelAndDeselect]);
|
|
19156
|
-
const handleStateChange = (0,
|
|
20450
|
+
const handleStateChange = (0, import_react17.useCallback)((state) => {
|
|
19157
20451
|
if (!activeStateElRef.current) return;
|
|
19158
20452
|
const el = activeStateElRef.current;
|
|
19159
20453
|
if (state === "Default") {
|
|
@@ -19166,7 +20460,7 @@ function OhhwellsBridge() {
|
|
|
19166
20460
|
}
|
|
19167
20461
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
19168
20462
|
}, [deactivate]);
|
|
19169
|
-
const reselectAfterLinkPopover = (0,
|
|
20463
|
+
const reselectAfterLinkPopover = (0, import_react17.useCallback)(
|
|
19170
20464
|
(hrefKey) => {
|
|
19171
20465
|
requestAnimationFrame(() => {
|
|
19172
20466
|
const el = resolveHrefKeyElement(hrefKey);
|
|
@@ -19175,7 +20469,7 @@ function OhhwellsBridge() {
|
|
|
19175
20469
|
},
|
|
19176
20470
|
[resolveHrefKeyElement]
|
|
19177
20471
|
);
|
|
19178
|
-
const closeLinkPopover = (0,
|
|
20472
|
+
const closeLinkPopover = (0, import_react17.useCallback)(() => {
|
|
19179
20473
|
const session = linkPopoverSessionRef.current;
|
|
19180
20474
|
addNavAfterAnchorRef.current = null;
|
|
19181
20475
|
setLinkPopover(null);
|
|
@@ -19183,9 +20477,9 @@ function OhhwellsBridge() {
|
|
|
19183
20477
|
reselectAfterLinkPopover(session.key);
|
|
19184
20478
|
}
|
|
19185
20479
|
}, [reselectAfterLinkPopover]);
|
|
19186
|
-
const closeLinkPopoverRef = (0,
|
|
20480
|
+
const closeLinkPopoverRef = (0, import_react17.useRef)(closeLinkPopover);
|
|
19187
20481
|
closeLinkPopoverRef.current = closeLinkPopover;
|
|
19188
|
-
const openLinkPopoverForActive = (0,
|
|
20482
|
+
const openLinkPopoverForActive = (0, import_react17.useCallback)(() => {
|
|
19189
20483
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
19190
20484
|
if (!hrefCtx) return;
|
|
19191
20485
|
bumpLinkPopoverGrace();
|
|
@@ -19196,7 +20490,7 @@ function OhhwellsBridge() {
|
|
|
19196
20490
|
});
|
|
19197
20491
|
deactivate();
|
|
19198
20492
|
}, [deactivate]);
|
|
19199
|
-
const openLinkPopoverForSelected = (0,
|
|
20493
|
+
const openLinkPopoverForSelected = (0, import_react17.useCallback)(() => {
|
|
19200
20494
|
const anchor = selectedElRef.current;
|
|
19201
20495
|
if (!anchor) return;
|
|
19202
20496
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -19213,7 +20507,7 @@ function OhhwellsBridge() {
|
|
|
19213
20507
|
});
|
|
19214
20508
|
deselect();
|
|
19215
20509
|
}, [deselect]);
|
|
19216
|
-
const handleSelectParent = (0,
|
|
20510
|
+
const handleSelectParent = (0, import_react17.useCallback)(() => {
|
|
19217
20511
|
const selected = selectedElRef.current;
|
|
19218
20512
|
if (!selected) return;
|
|
19219
20513
|
if (toolbarVariantRef.current === "select-frame") {
|
|
@@ -19240,7 +20534,7 @@ function OhhwellsBridge() {
|
|
|
19240
20534
|
}
|
|
19241
20535
|
deselectRef.current();
|
|
19242
20536
|
}, []);
|
|
19243
|
-
const handleDuplicateSelected = (0,
|
|
20537
|
+
const handleDuplicateSelected = (0, import_react17.useCallback)(() => {
|
|
19244
20538
|
const selected = selectedElRef.current;
|
|
19245
20539
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
19246
20540
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
@@ -19356,7 +20650,7 @@ function OhhwellsBridge() {
|
|
|
19356
20650
|
});
|
|
19357
20651
|
}
|
|
19358
20652
|
}, [postToParent2]);
|
|
19359
|
-
const runPendingDeleteUndo = (0,
|
|
20653
|
+
const runPendingDeleteUndo = (0, import_react17.useCallback)(() => {
|
|
19360
20654
|
const pending = pendingDeleteUndoRef.current;
|
|
19361
20655
|
if (!pending) return false;
|
|
19362
20656
|
pendingDeleteUndoRef.current = null;
|
|
@@ -19364,7 +20658,7 @@ function OhhwellsBridge() {
|
|
|
19364
20658
|
enforceLinkHrefs();
|
|
19365
20659
|
return true;
|
|
19366
20660
|
}, []);
|
|
19367
|
-
const handleDeleteSelected = (0,
|
|
20661
|
+
const handleDeleteSelected = (0, import_react17.useCallback)(() => {
|
|
19368
20662
|
const selected = selectedElRef.current;
|
|
19369
20663
|
if (!selected) return false;
|
|
19370
20664
|
return deleteSelectedNavFooterItem({
|
|
@@ -19385,7 +20679,7 @@ function OhhwellsBridge() {
|
|
|
19385
20679
|
}, [postToParent2]);
|
|
19386
20680
|
handleDeleteSelectedRef.current = handleDeleteSelected;
|
|
19387
20681
|
runPendingDeleteUndoRef.current = runPendingDeleteUndo;
|
|
19388
|
-
const handleLinkPopoverSubmit = (0,
|
|
20682
|
+
const handleLinkPopoverSubmit = (0, import_react17.useCallback)(
|
|
19389
20683
|
(target) => {
|
|
19390
20684
|
const session = linkPopoverSessionRef.current;
|
|
19391
20685
|
if (!session) return;
|
|
@@ -19451,19 +20745,30 @@ function OhhwellsBridge() {
|
|
|
19451
20745
|
const showEditLink = toolbarShowEditLink;
|
|
19452
20746
|
const currentSections = sectionsByPath[pathname] ?? [];
|
|
19453
20747
|
linkPopoverOpenRef.current = linkPopover !== null;
|
|
19454
|
-
const
|
|
20748
|
+
const handleMediaSelect = (0, import_react17.useCallback)((key) => {
|
|
20749
|
+
const el = hoveredImageRef.current?.dataset.ohwKey === key ? hoveredImageRef.current : Array.from(document.querySelectorAll(MEDIA_SELECTOR)).find(
|
|
20750
|
+
(m) => (m.dataset.ohwKey ?? "") === key
|
|
20751
|
+
) ?? null;
|
|
20752
|
+
if (!el) return;
|
|
20753
|
+
selectMediaElementRef.current(el);
|
|
20754
|
+
}, []);
|
|
20755
|
+
const handleMediaReplace = (0, import_react17.useCallback)(
|
|
19455
20756
|
(key) => {
|
|
19456
|
-
postToParent2({
|
|
20757
|
+
postToParent2({
|
|
20758
|
+
type: "ow:image-pick",
|
|
20759
|
+
key,
|
|
20760
|
+
elementType: mediaHover?.elementType ?? selectedMedia?.elementType ?? "image"
|
|
20761
|
+
});
|
|
19457
20762
|
},
|
|
19458
|
-
[postToParent2, mediaHover?.elementType]
|
|
20763
|
+
[postToParent2, mediaHover?.elementType, selectedMedia?.elementType]
|
|
19459
20764
|
);
|
|
19460
|
-
const handleEditCarousel = (0,
|
|
20765
|
+
const handleEditCarousel = (0, import_react17.useCallback)(
|
|
19461
20766
|
(key) => {
|
|
19462
20767
|
postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
|
|
19463
20768
|
},
|
|
19464
20769
|
[postToParent2]
|
|
19465
20770
|
);
|
|
19466
|
-
const handleMediaFadeOutComplete = (0,
|
|
20771
|
+
const handleMediaFadeOutComplete = (0, import_react17.useCallback)((key) => {
|
|
19467
20772
|
setUploadingRects((prev) => {
|
|
19468
20773
|
if (!(key in prev)) return prev;
|
|
19469
20774
|
const next = { ...prev };
|
|
@@ -19471,7 +20776,7 @@ function OhhwellsBridge() {
|
|
|
19471
20776
|
return next;
|
|
19472
20777
|
});
|
|
19473
20778
|
}, []);
|
|
19474
|
-
const handleVideoSettingsChange = (0,
|
|
20779
|
+
const handleVideoSettingsChange = (0, import_react17.useCallback)(
|
|
19475
20780
|
(key, settings) => {
|
|
19476
20781
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
19477
20782
|
const video = getVideoEl2(el);
|
|
@@ -19493,420 +20798,506 @@ function OhhwellsBridge() {
|
|
|
19493
20798
|
},
|
|
19494
20799
|
[postToParent2]
|
|
19495
20800
|
);
|
|
19496
|
-
return
|
|
19497
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.
|
|
19498
|
-
|
|
19499
|
-
|
|
19500
|
-
|
|
19501
|
-
|
|
19502
|
-
{
|
|
19503
|
-
|
|
19504
|
-
|
|
19505
|
-
|
|
19506
|
-
|
|
19507
|
-
|
|
19508
|
-
|
|
19509
|
-
|
|
19510
|
-
|
|
19511
|
-
|
|
19512
|
-
|
|
19513
|
-
|
|
19514
|
-
|
|
19515
|
-
|
|
19516
|
-
onReplace: handleMediaReplace,
|
|
19517
|
-
onVideoSettingsChange: handleVideoSettingsChange
|
|
19518
|
-
}
|
|
19519
|
-
),
|
|
19520
|
-
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
|
|
19521
|
-
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
19522
|
-
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
19523
|
-
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
19524
|
-
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
19525
|
-
"div",
|
|
19526
|
-
{
|
|
19527
|
-
className: "pointer-events-none fixed z-2147483646",
|
|
19528
|
-
style: {
|
|
19529
|
-
left: slot.left,
|
|
19530
|
-
top: slot.top,
|
|
19531
|
-
width: slot.width,
|
|
19532
|
-
height: slot.height
|
|
20801
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
20802
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { id: "ohw-loader", suppressHydrationWarning: true, style: { ...OHW_LOADER_STYLE, display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(OhwLoaderSpinner, {}) }),
|
|
20803
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: OHW_LOADER_PREHYDRATE_SCRIPT } }),
|
|
20804
|
+
bridgeRoot ? (0, import_react_dom4.createPortal)(
|
|
20805
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
20806
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
20807
|
+
isEditMode && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
|
|
20808
|
+
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
20809
|
+
"div",
|
|
20810
|
+
{
|
|
20811
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
20812
|
+
style: { left: slot.left, top: slot.y, width: slot.width, height: 3, transform: "translateY(-50%)" },
|
|
20813
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
20814
|
+
DropIndicator,
|
|
20815
|
+
{
|
|
20816
|
+
direction: "horizontal",
|
|
20817
|
+
state: activeSectionDropIndex === i ? "dragActive" : "dragIdle",
|
|
20818
|
+
className: "!h-full !w-full"
|
|
20819
|
+
}
|
|
20820
|
+
)
|
|
19533
20821
|
},
|
|
19534
|
-
|
|
19535
|
-
|
|
19536
|
-
|
|
19537
|
-
|
|
19538
|
-
|
|
19539
|
-
|
|
19540
|
-
|
|
19541
|
-
|
|
19542
|
-
|
|
19543
|
-
|
|
19544
|
-
)),
|
|
19545
|
-
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
19546
|
-
"div",
|
|
19547
|
-
{
|
|
19548
|
-
className: "pointer-events-none fixed z-2147483646",
|
|
19549
|
-
style: {
|
|
19550
|
-
left: slot.left,
|
|
19551
|
-
top: slot.top,
|
|
19552
|
-
width: slot.width,
|
|
19553
|
-
height: slot.height
|
|
20822
|
+
`section-drop-${slot.insertIndex}-${i}`
|
|
20823
|
+
)),
|
|
20824
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
20825
|
+
MediaOverlay,
|
|
20826
|
+
{
|
|
20827
|
+
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
20828
|
+
isUploading: true,
|
|
20829
|
+
fadingOut,
|
|
20830
|
+
onFadeOutComplete: handleMediaFadeOutComplete,
|
|
20831
|
+
onReplace: handleMediaReplace
|
|
19554
20832
|
},
|
|
19555
|
-
|
|
19556
|
-
|
|
19557
|
-
|
|
19558
|
-
|
|
19559
|
-
|
|
19560
|
-
|
|
19561
|
-
|
|
19562
|
-
|
|
19563
|
-
|
|
19564
|
-
|
|
19565
|
-
|
|
19566
|
-
|
|
19567
|
-
|
|
19568
|
-
|
|
19569
|
-
|
|
19570
|
-
|
|
19571
|
-
|
|
19572
|
-
|
|
19573
|
-
|
|
19574
|
-
|
|
19575
|
-
|
|
19576
|
-
|
|
19577
|
-
|
|
20833
|
+
`uploading-${key}`
|
|
20834
|
+
)),
|
|
20835
|
+
mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
20836
|
+
MediaOverlay,
|
|
20837
|
+
{
|
|
20838
|
+
hover: mediaHover,
|
|
20839
|
+
isUploading: false,
|
|
20840
|
+
onReplace: handleMediaReplace,
|
|
20841
|
+
onSelect: handleMediaSelect,
|
|
20842
|
+
onVideoSettingsChange: handleVideoSettingsChange
|
|
20843
|
+
}
|
|
20844
|
+
),
|
|
20845
|
+
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
20846
|
+
MediaOverlay,
|
|
20847
|
+
{
|
|
20848
|
+
hover: selectedMedia,
|
|
20849
|
+
selected: true,
|
|
20850
|
+
hovered: mediaHover?.key === selectedMedia.key,
|
|
20851
|
+
isUploading: false,
|
|
20852
|
+
onReplace: handleMediaReplace,
|
|
20853
|
+
onSelect: handleMediaSelect,
|
|
20854
|
+
onVideoSettingsChange: handleVideoSettingsChange
|
|
20855
|
+
}
|
|
20856
|
+
),
|
|
20857
|
+
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
|
|
20858
|
+
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
20859
|
+
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
20860
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
20861
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
20862
|
+
"div",
|
|
20863
|
+
{
|
|
20864
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
20865
|
+
style: {
|
|
20866
|
+
left: slot.left,
|
|
20867
|
+
top: slot.top,
|
|
20868
|
+
width: slot.width,
|
|
20869
|
+
height: slot.height
|
|
20870
|
+
},
|
|
20871
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
20872
|
+
DropIndicator,
|
|
20873
|
+
{
|
|
20874
|
+
direction: slot.direction,
|
|
20875
|
+
state: activeFooterDropIndex === i ? "dragActive" : "dragIdle",
|
|
20876
|
+
className: "!h-full !w-full"
|
|
20877
|
+
}
|
|
20878
|
+
)
|
|
20879
|
+
},
|
|
20880
|
+
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
20881
|
+
)),
|
|
20882
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
20883
|
+
"div",
|
|
20884
|
+
{
|
|
20885
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
20886
|
+
style: {
|
|
20887
|
+
left: slot.left,
|
|
20888
|
+
top: slot.top,
|
|
20889
|
+
width: slot.width,
|
|
20890
|
+
height: slot.height
|
|
20891
|
+
},
|
|
20892
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
20893
|
+
DropIndicator,
|
|
20894
|
+
{
|
|
20895
|
+
direction: slot.direction,
|
|
20896
|
+
state: activeNavDropIndex === i ? "dragActive" : "dragIdle",
|
|
20897
|
+
className: "!h-full !w-full"
|
|
20898
|
+
}
|
|
20899
|
+
)
|
|
20900
|
+
},
|
|
20901
|
+
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
20902
|
+
)),
|
|
20903
|
+
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
20904
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
20905
|
+
hoveredTextRect && !hoveredNavContainerRect && !hoveredItemRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
|
|
20906
|
+
formPickRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
20907
|
+
ItemInteractionLayer,
|
|
20908
|
+
{
|
|
20909
|
+
rect: formPickRect,
|
|
20910
|
+
state: "active-top",
|
|
20911
|
+
itemDragSurface: false,
|
|
20912
|
+
toolbarAlign: "left",
|
|
20913
|
+
chromeGap: 24,
|
|
20914
|
+
toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
20915
|
+
"div",
|
|
20916
|
+
{
|
|
20917
|
+
"data-ohw-form-toolbar": "",
|
|
20918
|
+
className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
|
|
20919
|
+
children: [
|
|
20920
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
20921
|
+
"button",
|
|
20922
|
+
{
|
|
20923
|
+
type: "button",
|
|
20924
|
+
"aria-label": "Add field",
|
|
20925
|
+
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
20926
|
+
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
20927
|
+
"data-ohw-add-field": "",
|
|
20928
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Plus, { size: 15, "aria-hidden": true })
|
|
20929
|
+
}
|
|
20930
|
+
),
|
|
20931
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
20932
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
20933
|
+
"button",
|
|
20934
|
+
{
|
|
20935
|
+
type: "button",
|
|
20936
|
+
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",
|
|
20937
|
+
onClick: () => {
|
|
20938
|
+
const form = formPickElRef.current;
|
|
20939
|
+
if (!form) return;
|
|
20940
|
+
postToParent2({
|
|
20941
|
+
type: "ow:form-pick",
|
|
20942
|
+
formKey: formKeyOf(form),
|
|
20943
|
+
hasLongText: formHasLongText(form)
|
|
20944
|
+
});
|
|
20945
|
+
},
|
|
20946
|
+
children: [
|
|
20947
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Settings, { size: 14, "aria-hidden": true }),
|
|
20948
|
+
"Form settings",
|
|
20949
|
+
formPickCount ? (
|
|
20950
|
+
// Counter pill, per the design — not a text suffix.
|
|
20951
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
20952
|
+
"span",
|
|
20953
|
+
{
|
|
20954
|
+
"data-ohw-form-count": "",
|
|
20955
|
+
className: "ml-0.5 inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-full bg-primary px-1.5 text-[11px] font-semibold text-primary-foreground",
|
|
20956
|
+
children: formPickCount
|
|
20957
|
+
}
|
|
20958
|
+
)
|
|
20959
|
+
) : null
|
|
20960
|
+
]
|
|
20961
|
+
}
|
|
20962
|
+
),
|
|
20963
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
20964
|
+
/* @__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)(
|
|
20965
|
+
"button",
|
|
20966
|
+
{
|
|
20967
|
+
type: "button",
|
|
20968
|
+
"aria-pressed": formViewState === state,
|
|
20969
|
+
className: "rounded-md px-2.5 py-1 text-[13px] font-semibold capitalize transition-colors " + (formViewState === state ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"),
|
|
20970
|
+
onClick: () => {
|
|
20971
|
+
const form = formPickElRef.current;
|
|
20972
|
+
const key = form ? formKeyOf(form) : null;
|
|
20973
|
+
if (!form || !key) return;
|
|
20974
|
+
const initial = successInitialFor(form, key, editContentRef.current);
|
|
20975
|
+
setFormViewState(form, key, state, initial);
|
|
20976
|
+
setFormViewStateUi(state);
|
|
20977
|
+
setFormPickRect(form.getBoundingClientRect());
|
|
20978
|
+
if (state === "success") {
|
|
20979
|
+
const successEl = form.querySelector(`[${SUCCESS_TEXT_ATTR}]`);
|
|
20980
|
+
if (successEl) requestAnimationFrame(() => activateRef.current(successEl));
|
|
20981
|
+
} else {
|
|
20982
|
+
deactivateRef.current();
|
|
20983
|
+
}
|
|
20984
|
+
},
|
|
20985
|
+
children: state
|
|
20986
|
+
},
|
|
20987
|
+
state
|
|
20988
|
+
)) })
|
|
20989
|
+
]
|
|
20990
|
+
}
|
|
20991
|
+
)
|
|
20992
|
+
}
|
|
20993
|
+
),
|
|
20994
|
+
formHoverRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
20995
|
+
ItemInteractionLayer,
|
|
20996
|
+
{
|
|
20997
|
+
rect: formHoverRect,
|
|
20998
|
+
state: "hover",
|
|
20999
|
+
chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
|
|
21000
|
+
}
|
|
21001
|
+
),
|
|
21002
|
+
fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21003
|
+
ItemInteractionLayer,
|
|
21004
|
+
{
|
|
21005
|
+
rect: fieldPickRect,
|
|
21006
|
+
state: fieldDragging ? "dragging" : "active-top",
|
|
21007
|
+
itemDragSurface: false,
|
|
21008
|
+
toolbarAlign: "left",
|
|
21009
|
+
chromeGap: 10,
|
|
21010
|
+
showHandle: true,
|
|
21011
|
+
dragHandleLabel: "Reorder field",
|
|
21012
|
+
onDragHandleDragStart: handleFieldDragStart,
|
|
21013
|
+
onDragHandleDragEnd: handleFieldDragEnd,
|
|
21014
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21015
|
+
FormFieldToolbar,
|
|
21016
|
+
{
|
|
21017
|
+
type: fieldPickState.type,
|
|
21018
|
+
required: fieldPickState.required,
|
|
21019
|
+
onTypeChange: handleFieldTypeChange,
|
|
21020
|
+
onRequiredToggle: handleFieldRequiredToggle,
|
|
21021
|
+
onDuplicate: handleFieldDuplicate,
|
|
21022
|
+
onDelete: handleFieldDelete
|
|
21023
|
+
}
|
|
21024
|
+
)
|
|
21025
|
+
}
|
|
21026
|
+
),
|
|
21027
|
+
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21028
|
+
"div",
|
|
21029
|
+
{
|
|
21030
|
+
className: "pointer-events-none fixed z-[2147483644]",
|
|
21031
|
+
style: { top: slot.top, left: slot.left, width: slot.width },
|
|
21032
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21033
|
+
DropIndicator,
|
|
21034
|
+
{
|
|
21035
|
+
direction: "horizontal",
|
|
21036
|
+
state: fieldDropIndex === i ? "dragActive" : "dragIdle",
|
|
21037
|
+
className: "!w-full"
|
|
21038
|
+
}
|
|
21039
|
+
)
|
|
21040
|
+
},
|
|
21041
|
+
`field-drop-${i}`
|
|
21042
|
+
)) : null,
|
|
21043
|
+
fieldTypePickerOpen && formPickRect ? (() => {
|
|
21044
|
+
const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
|
|
21045
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
19578
21046
|
"div",
|
|
19579
21047
|
{
|
|
19580
|
-
"
|
|
19581
|
-
|
|
19582
|
-
|
|
19583
|
-
|
|
19584
|
-
|
|
19585
|
-
|
|
19586
|
-
type: "button",
|
|
19587
|
-
"aria-label": "Add field",
|
|
19588
|
-
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
19589
|
-
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
19590
|
-
"data-ohw-add-field": "",
|
|
19591
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Plus, { size: 15, "aria-hidden": true })
|
|
19592
|
-
}
|
|
19593
|
-
),
|
|
19594
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
19595
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
19596
|
-
"button",
|
|
19597
|
-
{
|
|
19598
|
-
type: "button",
|
|
19599
|
-
className: "flex h-7 items-center gap-1.5 whitespace-nowrap rounded-md px-2 text-[13px] font-semibold text-foreground transition-colors hover:bg-muted/80",
|
|
19600
|
-
onClick: () => {
|
|
19601
|
-
const form = formPickElRef.current;
|
|
19602
|
-
if (!form) return;
|
|
19603
|
-
postToParent2({
|
|
19604
|
-
type: "ow:form-pick",
|
|
19605
|
-
formKey: formKeyOf(form),
|
|
19606
|
-
hasLongText: formHasLongText(form)
|
|
19607
|
-
});
|
|
19608
|
-
},
|
|
19609
|
-
children: [
|
|
19610
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.Settings, { size: 14, "aria-hidden": true }),
|
|
19611
|
-
"Form settings",
|
|
19612
|
-
formPickCount ? (
|
|
19613
|
-
// Counter pill, per the design — not a text suffix.
|
|
19614
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
19615
|
-
"span",
|
|
19616
|
-
{
|
|
19617
|
-
"data-ohw-form-count": "",
|
|
19618
|
-
className: "ml-0.5 inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-full bg-primary px-1.5 text-[11px] font-semibold text-primary-foreground",
|
|
19619
|
-
children: formPickCount
|
|
19620
|
-
}
|
|
19621
|
-
)
|
|
19622
|
-
) : null
|
|
19623
|
-
]
|
|
19624
|
-
}
|
|
19625
|
-
),
|
|
19626
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
19627
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
19628
|
-
"button",
|
|
19629
|
-
{
|
|
19630
|
-
type: "button",
|
|
19631
|
-
"aria-pressed": formViewState === state,
|
|
19632
|
-
className: "rounded-md px-2.5 py-1 text-[13px] font-semibold capitalize transition-colors " + (formViewState === state ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"),
|
|
19633
|
-
onClick: () => {
|
|
19634
|
-
const form = formPickElRef.current;
|
|
19635
|
-
const key = form ? formKeyOf(form) : null;
|
|
19636
|
-
if (!form || !key) return;
|
|
19637
|
-
const initial = successInitialFor(form, key, editContentRef.current);
|
|
19638
|
-
setFormViewState(form, key, state, initial);
|
|
19639
|
-
setFormViewStateUi(state);
|
|
19640
|
-
setFormPickRect(form.getBoundingClientRect());
|
|
19641
|
-
if (state === "success") {
|
|
19642
|
-
const successEl = form.querySelector(`[${SUCCESS_TEXT_ATTR}]`);
|
|
19643
|
-
if (successEl) requestAnimationFrame(() => activateRef.current(successEl));
|
|
19644
|
-
} else {
|
|
19645
|
-
deactivateRef.current();
|
|
19646
|
-
}
|
|
19647
|
-
},
|
|
19648
|
-
children: state
|
|
19649
|
-
},
|
|
19650
|
-
state
|
|
19651
|
-
)) })
|
|
19652
|
-
]
|
|
21048
|
+
className: "pointer-events-none fixed z-[2147483645]",
|
|
21049
|
+
style: {
|
|
21050
|
+
top: toolbar ? toolbar.bottom + 6 : formPickRect.top + 16,
|
|
21051
|
+
left: toolbar ? toolbar.left : formPickRect.left + 24
|
|
21052
|
+
},
|
|
21053
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FieldTypePicker, { onPick: handleAddField })
|
|
19653
21054
|
}
|
|
19654
|
-
)
|
|
19655
|
-
}
|
|
19656
|
-
|
|
19657
|
-
|
|
19658
|
-
|
|
19659
|
-
|
|
19660
|
-
|
|
19661
|
-
|
|
19662
|
-
|
|
19663
|
-
|
|
19664
|
-
|
|
19665
|
-
|
|
19666
|
-
|
|
19667
|
-
|
|
19668
|
-
|
|
19669
|
-
|
|
19670
|
-
|
|
19671
|
-
|
|
19672
|
-
|
|
19673
|
-
|
|
19674
|
-
|
|
19675
|
-
|
|
19676
|
-
|
|
19677
|
-
|
|
19678
|
-
|
|
21055
|
+
);
|
|
21056
|
+
})() : null,
|
|
21057
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
21058
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21059
|
+
FooterContainerChrome,
|
|
21060
|
+
{
|
|
21061
|
+
rect: toolbarRect,
|
|
21062
|
+
onAdd: handleAddFooterColumn,
|
|
21063
|
+
addDisabled: !canAddFooterColumn()
|
|
21064
|
+
}
|
|
21065
|
+
),
|
|
21066
|
+
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21067
|
+
ItemInteractionLayer,
|
|
21068
|
+
{
|
|
21069
|
+
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
21070
|
+
toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
|
|
21071
|
+
elRef: glowElRef,
|
|
21072
|
+
state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanelRect(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
21073
|
+
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
21074
|
+
dragDisabled: reorderDragDisabled,
|
|
21075
|
+
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
21076
|
+
onDragHandleDragStart: handleItemDragStart,
|
|
21077
|
+
onDragHandleDragEnd: handleItemDragEnd,
|
|
21078
|
+
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
21079
|
+
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
21080
|
+
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
|
|
21081
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21082
|
+
ItemActionToolbar,
|
|
21083
|
+
{
|
|
21084
|
+
onEditLink: openLinkPopoverForSelected,
|
|
21085
|
+
onStyle: () => {
|
|
21086
|
+
const row = selectedElRef.current;
|
|
21087
|
+
if (!row) return;
|
|
21088
|
+
if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
|
|
21089
|
+
else openSocialsDisplayPanel(row);
|
|
21090
|
+
},
|
|
21091
|
+
showStyle: selectedIsSocialsRow,
|
|
21092
|
+
styleActive: floatingPanel?.kind === "socials-display",
|
|
21093
|
+
onAddItem: handleAddChildItem,
|
|
21094
|
+
onSelectParent: handleSelectParent,
|
|
21095
|
+
onDuplicate: handleDuplicateSelected,
|
|
21096
|
+
onDelete: handleDeleteSelected,
|
|
21097
|
+
addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
21098
|
+
const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
|
|
21099
|
+
return row ? !canAddSocialItem(row) : false;
|
|
21100
|
+
})(),
|
|
21101
|
+
editLinkDisabled: false,
|
|
21102
|
+
moreDisabled: false,
|
|
21103
|
+
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
|
|
21104
|
+
showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
|
|
21105
|
+
showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
|
|
21106
|
+
selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
|
|
21107
|
+
),
|
|
21108
|
+
showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
|
|
21109
|
+
dropdownOpen: navDropdownPreviewOpen,
|
|
21110
|
+
onDropdownOpenChange: handleNavDropdownOpenChange,
|
|
21111
|
+
headingVisible: footerHeadingVisible,
|
|
21112
|
+
onHeadingVisibleChange: handleFooterHeadingVisibleChange
|
|
21113
|
+
}
|
|
21114
|
+
) : void 0
|
|
21115
|
+
}
|
|
21116
|
+
),
|
|
21117
|
+
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
21118
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21119
|
+
EditGlowChrome,
|
|
19679
21120
|
{
|
|
19680
|
-
|
|
19681
|
-
|
|
19682
|
-
|
|
19683
|
-
|
|
19684
|
-
|
|
19685
|
-
onDelete: handleFieldDelete
|
|
21121
|
+
rect: toolbarRect,
|
|
21122
|
+
elRef: glowElRef,
|
|
21123
|
+
reorderHrefKey,
|
|
21124
|
+
dragDisabled: reorderDragDisabled,
|
|
21125
|
+
hideHandle: isItemDragging
|
|
19686
21126
|
}
|
|
19687
|
-
)
|
|
19688
|
-
|
|
19689
|
-
|
|
19690
|
-
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
19691
|
-
"div",
|
|
19692
|
-
{
|
|
19693
|
-
className: "pointer-events-none fixed z-[2147483644]",
|
|
19694
|
-
style: { top: slot.top, left: slot.left, width: slot.width },
|
|
19695
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
19696
|
-
DropIndicator,
|
|
21127
|
+
),
|
|
21128
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21129
|
+
FloatingToolbar,
|
|
19697
21130
|
{
|
|
19698
|
-
|
|
19699
|
-
|
|
19700
|
-
|
|
21131
|
+
rect: toolbarRect,
|
|
21132
|
+
parentScroll: parentScrollRef.current,
|
|
21133
|
+
elRef: toolbarElRef,
|
|
21134
|
+
onCommand: handleCommand,
|
|
21135
|
+
activeCommands,
|
|
21136
|
+
showEditLink,
|
|
21137
|
+
onEditLink: openLinkPopoverForActive
|
|
19701
21138
|
}
|
|
19702
21139
|
)
|
|
19703
|
-
},
|
|
19704
|
-
|
|
19705
|
-
)) : null,
|
|
19706
|
-
fieldTypePickerOpen && formPickRect ? (() => {
|
|
19707
|
-
const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
|
|
19708
|
-
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21140
|
+
] }),
|
|
21141
|
+
maxBadge && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
19709
21142
|
"div",
|
|
19710
21143
|
{
|
|
19711
|
-
|
|
21144
|
+
"data-ohw-max-badge": "",
|
|
19712
21145
|
style: {
|
|
19713
|
-
|
|
19714
|
-
|
|
21146
|
+
position: "fixed",
|
|
21147
|
+
top: maxBadge.rect.bottom + 4,
|
|
21148
|
+
left: maxBadge.rect.right,
|
|
21149
|
+
transform: "translateX(-100%)",
|
|
21150
|
+
zIndex: 2147483647,
|
|
21151
|
+
background: maxBadge.current > maxBadge.max ? "#FEF2F2" : "#F5F5F4",
|
|
21152
|
+
color: maxBadge.current > maxBadge.max ? "#DC2626" : "#78716C",
|
|
21153
|
+
border: `1px solid ${maxBadge.current > maxBadge.max ? "#FECACA" : "#E7E5E4"}`,
|
|
21154
|
+
borderRadius: 4,
|
|
21155
|
+
padding: "2px 6px",
|
|
21156
|
+
fontSize: 11,
|
|
21157
|
+
fontWeight: 500,
|
|
21158
|
+
pointerEvents: "none"
|
|
19715
21159
|
},
|
|
19716
|
-
children:
|
|
21160
|
+
children: [
|
|
21161
|
+
maxBadge.current,
|
|
21162
|
+
"/",
|
|
21163
|
+
maxBadge.max
|
|
21164
|
+
]
|
|
19717
21165
|
}
|
|
19718
|
-
)
|
|
19719
|
-
|
|
19720
|
-
|
|
19721
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
19722
|
-
FooterContainerChrome,
|
|
19723
|
-
{
|
|
19724
|
-
rect: toolbarRect,
|
|
19725
|
-
onAdd: handleAddFooterColumn,
|
|
19726
|
-
addDisabled: !canAddFooterColumn()
|
|
19727
|
-
}
|
|
19728
|
-
),
|
|
19729
|
-
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
19730
|
-
ItemInteractionLayer,
|
|
19731
|
-
{
|
|
19732
|
-
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
19733
|
-
toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
|
|
19734
|
-
elRef: glowElRef,
|
|
19735
|
-
state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanelRect(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
19736
|
-
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
19737
|
-
dragDisabled: reorderDragDisabled,
|
|
19738
|
-
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
19739
|
-
onDragHandleDragStart: handleItemDragStart,
|
|
19740
|
-
onDragHandleDragEnd: handleItemDragEnd,
|
|
19741
|
-
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
19742
|
-
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
19743
|
-
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
|
|
19744
|
-
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
19745
|
-
ItemActionToolbar,
|
|
19746
|
-
{
|
|
19747
|
-
onEditLink: openLinkPopoverForSelected,
|
|
19748
|
-
onStyle: () => {
|
|
19749
|
-
const row = selectedElRef.current;
|
|
19750
|
-
if (!row) return;
|
|
19751
|
-
if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
|
|
19752
|
-
else openSocialsDisplayPanel(row);
|
|
19753
|
-
},
|
|
19754
|
-
showStyle: selectedIsSocialsRow,
|
|
19755
|
-
styleActive: floatingPanel?.kind === "socials-display",
|
|
19756
|
-
onAddItem: handleAddChildItem,
|
|
19757
|
-
onSelectParent: handleSelectParent,
|
|
19758
|
-
onDuplicate: handleDuplicateSelected,
|
|
19759
|
-
onDelete: handleDeleteSelected,
|
|
19760
|
-
addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
19761
|
-
const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
|
|
19762
|
-
return row ? !canAddSocialItem(row) : false;
|
|
19763
|
-
})(),
|
|
19764
|
-
editLinkDisabled: false,
|
|
19765
|
-
moreDisabled: false,
|
|
19766
|
-
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
|
|
19767
|
-
showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
|
|
19768
|
-
showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
|
|
19769
|
-
selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
|
|
19770
|
-
),
|
|
19771
|
-
showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
|
|
19772
|
-
dropdownOpen: navDropdownPreviewOpen,
|
|
19773
|
-
onDropdownOpenChange: handleNavDropdownOpenChange,
|
|
19774
|
-
headingVisible: footerHeadingVisible,
|
|
19775
|
-
onHeadingVisibleChange: handleFooterHeadingVisibleChange
|
|
19776
|
-
}
|
|
19777
|
-
) : void 0
|
|
19778
|
-
}
|
|
19779
|
-
),
|
|
19780
|
-
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
19781
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
19782
|
-
EditGlowChrome,
|
|
21166
|
+
),
|
|
21167
|
+
toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21168
|
+
StateToggle,
|
|
19783
21169
|
{
|
|
19784
|
-
rect:
|
|
19785
|
-
|
|
19786
|
-
|
|
19787
|
-
|
|
19788
|
-
hideHandle: isItemDragging
|
|
21170
|
+
rect: toggleState.rect,
|
|
21171
|
+
activeState: toggleState.activeState,
|
|
21172
|
+
states: toggleState.states,
|
|
21173
|
+
onStateChange: handleStateChange
|
|
19789
21174
|
}
|
|
19790
21175
|
),
|
|
19791
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.
|
|
19792
|
-
|
|
21176
|
+
sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
21177
|
+
"div",
|
|
19793
21178
|
{
|
|
19794
|
-
|
|
19795
|
-
|
|
19796
|
-
|
|
19797
|
-
|
|
19798
|
-
|
|
19799
|
-
|
|
19800
|
-
|
|
21179
|
+
"data-ohw-section-insert-line": "",
|
|
21180
|
+
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
21181
|
+
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
21182
|
+
children: [
|
|
21183
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
21184
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21185
|
+
Badge,
|
|
21186
|
+
{
|
|
21187
|
+
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",
|
|
21188
|
+
onClick: () => {
|
|
21189
|
+
window.parent.postMessage(
|
|
21190
|
+
{
|
|
21191
|
+
type: "ow:add-section",
|
|
21192
|
+
insertAfter: sectionGap.insertAfter,
|
|
21193
|
+
insertBefore: sectionGap.insertBefore
|
|
21194
|
+
},
|
|
21195
|
+
"*"
|
|
21196
|
+
);
|
|
21197
|
+
},
|
|
21198
|
+
children: "Add Section"
|
|
21199
|
+
}
|
|
21200
|
+
),
|
|
21201
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
21202
|
+
]
|
|
19801
21203
|
}
|
|
19802
|
-
)
|
|
19803
|
-
|
|
19804
|
-
|
|
19805
|
-
|
|
19806
|
-
|
|
19807
|
-
|
|
19808
|
-
|
|
19809
|
-
|
|
19810
|
-
|
|
19811
|
-
|
|
19812
|
-
|
|
19813
|
-
|
|
19814
|
-
|
|
19815
|
-
|
|
19816
|
-
|
|
19817
|
-
borderRadius: 4,
|
|
19818
|
-
padding: "2px 6px",
|
|
19819
|
-
fontSize: 11,
|
|
19820
|
-
fontWeight: 500,
|
|
19821
|
-
pointerEvents: "none"
|
|
21204
|
+
),
|
|
21205
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21206
|
+
LinkPopover,
|
|
21207
|
+
{
|
|
21208
|
+
panelRef: linkPopoverPanelRef,
|
|
21209
|
+
portalContainer: dialogPortalContainer,
|
|
21210
|
+
open: true,
|
|
21211
|
+
mode: linkPopover.mode ?? "edit",
|
|
21212
|
+
pages: sitePages,
|
|
21213
|
+
sections: currentSections,
|
|
21214
|
+
sectionsByPath,
|
|
21215
|
+
initialTarget: linkPopover.target,
|
|
21216
|
+
existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
|
|
21217
|
+
onClose: closeLinkPopover,
|
|
21218
|
+
onSubmit: handleLinkPopoverSubmit
|
|
19822
21219
|
},
|
|
19823
|
-
|
|
19824
|
-
|
|
19825
|
-
|
|
19826
|
-
|
|
19827
|
-
|
|
19828
|
-
|
|
19829
|
-
|
|
19830
|
-
|
|
19831
|
-
|
|
19832
|
-
|
|
19833
|
-
|
|
19834
|
-
|
|
19835
|
-
|
|
19836
|
-
|
|
19837
|
-
}
|
|
19838
|
-
),
|
|
19839
|
-
sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
19840
|
-
"div",
|
|
19841
|
-
{
|
|
19842
|
-
"data-ohw-section-insert-line": "",
|
|
19843
|
-
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
19844
|
-
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
19845
|
-
children: [
|
|
19846
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
19847
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
19848
|
-
Badge,
|
|
21220
|
+
linkPopover.key
|
|
21221
|
+
) : null,
|
|
21222
|
+
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21223
|
+
FloatingPanel,
|
|
21224
|
+
{
|
|
21225
|
+
open: true,
|
|
21226
|
+
title: floatingPanel.title,
|
|
21227
|
+
context: floatingPanel.context,
|
|
21228
|
+
position: floatingPanelPos,
|
|
21229
|
+
onPositionChange: setFloatingPanelPos,
|
|
21230
|
+
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
21231
|
+
onClose: closeFloatingPanelOnly,
|
|
21232
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
21233
|
+
SocialsDisplayPanel,
|
|
19849
21234
|
{
|
|
19850
|
-
|
|
19851
|
-
|
|
19852
|
-
|
|
19853
|
-
|
|
19854
|
-
|
|
19855
|
-
insertAfter: sectionGap.insertAfter,
|
|
19856
|
-
insertBefore: sectionGap.insertBefore
|
|
19857
|
-
},
|
|
19858
|
-
"*"
|
|
19859
|
-
);
|
|
19860
|
-
},
|
|
19861
|
-
children: "Add Section"
|
|
21235
|
+
display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
|
|
21236
|
+
onChange: (next) => {
|
|
21237
|
+
changeSocialsDisplay(floatingPanel.row, next);
|
|
21238
|
+
setFloatingPanel({ ...floatingPanel });
|
|
21239
|
+
}
|
|
19862
21240
|
}
|
|
19863
|
-
)
|
|
19864
|
-
|
|
19865
|
-
|
|
19866
|
-
|
|
19867
|
-
|
|
19868
|
-
|
|
19869
|
-
|
|
19870
|
-
|
|
19871
|
-
|
|
19872
|
-
|
|
19873
|
-
|
|
19874
|
-
|
|
19875
|
-
|
|
19876
|
-
|
|
19877
|
-
|
|
19878
|
-
|
|
19879
|
-
|
|
19880
|
-
|
|
19881
|
-
|
|
21241
|
+
)
|
|
21242
|
+
}
|
|
21243
|
+
) : null
|
|
21244
|
+
] }),
|
|
21245
|
+
bridgeRoot
|
|
21246
|
+
) : null
|
|
21247
|
+
] });
|
|
21248
|
+
}
|
|
21249
|
+
|
|
21250
|
+
// src/ui/EmptySection.tsx
|
|
21251
|
+
var import_link = __toESM(require("next/link"), 1);
|
|
21252
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
21253
|
+
function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
|
|
21254
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
|
|
21255
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
21256
|
+
"p",
|
|
21257
|
+
{
|
|
21258
|
+
style: {
|
|
21259
|
+
fontFamily: "var(--brand-font-body)",
|
|
21260
|
+
fontSize: "0.75rem",
|
|
21261
|
+
fontWeight: 500,
|
|
21262
|
+
letterSpacing: "0.15em",
|
|
21263
|
+
textTransform: "uppercase",
|
|
21264
|
+
color: "var(--brand-accent)",
|
|
21265
|
+
marginBottom: "1.5rem"
|
|
19882
21266
|
},
|
|
19883
|
-
|
|
19884
|
-
|
|
19885
|
-
|
|
19886
|
-
|
|
19887
|
-
|
|
19888
|
-
|
|
19889
|
-
|
|
19890
|
-
|
|
19891
|
-
|
|
19892
|
-
|
|
19893
|
-
|
|
19894
|
-
|
|
19895
|
-
|
|
19896
|
-
|
|
19897
|
-
|
|
19898
|
-
|
|
19899
|
-
|
|
19900
|
-
|
|
19901
|
-
|
|
19902
|
-
|
|
19903
|
-
|
|
19904
|
-
|
|
19905
|
-
|
|
19906
|
-
|
|
19907
|
-
|
|
19908
|
-
|
|
19909
|
-
|
|
21267
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_link.default, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
|
|
21268
|
+
}
|
|
21269
|
+
),
|
|
21270
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
21271
|
+
"h1",
|
|
21272
|
+
{
|
|
21273
|
+
style: {
|
|
21274
|
+
fontFamily: "var(--brand-font-heading)",
|
|
21275
|
+
fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
|
|
21276
|
+
lineHeight: 1.1,
|
|
21277
|
+
letterSpacing: "-0.025em",
|
|
21278
|
+
color: "var(--brand-text)",
|
|
21279
|
+
marginBottom: "1rem"
|
|
21280
|
+
},
|
|
21281
|
+
...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
|
|
21282
|
+
children: title
|
|
21283
|
+
}
|
|
21284
|
+
),
|
|
21285
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
21286
|
+
"p",
|
|
21287
|
+
{
|
|
21288
|
+
style: {
|
|
21289
|
+
fontFamily: "var(--brand-font-body)",
|
|
21290
|
+
fontSize: "1rem",
|
|
21291
|
+
lineHeight: 1.7,
|
|
21292
|
+
fontWeight: 300,
|
|
21293
|
+
color: "var(--brand-text-muted)",
|
|
21294
|
+
maxWidth: "340px"
|
|
21295
|
+
},
|
|
21296
|
+
...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
|
|
21297
|
+
children: "This page doesn't have any content yet."
|
|
21298
|
+
}
|
|
21299
|
+
)
|
|
21300
|
+
] });
|
|
19910
21301
|
}
|
|
19911
21302
|
// Annotate the CommonJS export names for ESM import in node:
|
|
19912
21303
|
0 && (module.exports = {
|
|
@@ -19925,6 +21316,7 @@ function OhhwellsBridge() {
|
|
|
19925
21316
|
DropdownMenuItem,
|
|
19926
21317
|
DropdownMenuSeparator,
|
|
19927
21318
|
DropdownMenuTrigger,
|
|
21319
|
+
EmptySection,
|
|
19928
21320
|
ItemActionToolbar,
|
|
19929
21321
|
ItemInteractionLayer,
|
|
19930
21322
|
LinkEditorPanel,
|