@ohhwells/bridge 0.1.72 → 0.1.73-next.227
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 +2489 -884
- 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 +2481 -877
- 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 +63 -0
- package/package.json +8 -3
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/OhhwellsBridge.tsx
|
|
4
|
-
import React12, { useCallback as
|
|
4
|
+
import React12, { useCallback as useCallback8, useEffect as useEffect13, useLayoutEffect as useLayoutEffect5, useRef as useRef10, useState as useState13 } from "react";
|
|
5
5
|
import { createRoot as createRoot2 } from "react-dom/client";
|
|
6
6
|
import { flushSync as flushSync2 } from "react-dom";
|
|
7
7
|
|
|
@@ -83,7 +83,12 @@ function parseAiSectionsState(raw) {
|
|
|
83
83
|
media: entry.media && typeof entry.media === "object" ? entry.media : {}
|
|
84
84
|
}));
|
|
85
85
|
const removed = Array.isArray(parsed.removed) ? parsed.removed.filter((id) => typeof id === "string" && id.length > 0) : [];
|
|
86
|
-
return {
|
|
86
|
+
return {
|
|
87
|
+
v: 1,
|
|
88
|
+
sections,
|
|
89
|
+
...removed.length ? { removed } : {},
|
|
90
|
+
...parsed.hideTemplate === true ? { hideTemplate: true } : {}
|
|
91
|
+
};
|
|
87
92
|
} catch {
|
|
88
93
|
return EMPTY_AI_SECTIONS;
|
|
89
94
|
}
|
|
@@ -96,6 +101,7 @@ function applyTreeToState(state, payload) {
|
|
|
96
101
|
const entry = {
|
|
97
102
|
id: payload.id,
|
|
98
103
|
label: payload.label ?? "Generated section",
|
|
104
|
+
...typeof payload.path === "string" && payload.path ? { path: payload.path } : {},
|
|
99
105
|
afterSection: payload.mode === "insert" && !insertBefore ? payload.targetSectionId ?? null : null,
|
|
100
106
|
...insertBefore && payload.targetSectionId ? { beforeSection: payload.targetSectionId } : {},
|
|
101
107
|
...payload.mode === "replace" && payload.targetSectionId ? { replaces: payload.targetSectionId } : {},
|
|
@@ -118,6 +124,317 @@ function deleteSectionFromState(state, sectionId) {
|
|
|
118
124
|
return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
|
|
119
125
|
}
|
|
120
126
|
|
|
127
|
+
// src/lib/brand-chrome.ts
|
|
128
|
+
var BRAND_NAME_KEY = "__ohw_brand_name";
|
|
129
|
+
var BRAND_TITLE_KEY = "__ohw_site_title";
|
|
130
|
+
var BRAND_FAVICON_LETTER_KEY = "__ohw_favicon_letter";
|
|
131
|
+
var BRAND_CHROME_KEYS = /* @__PURE__ */ new Set([
|
|
132
|
+
BRAND_NAME_KEY,
|
|
133
|
+
BRAND_TITLE_KEY,
|
|
134
|
+
BRAND_FAVICON_LETTER_KEY
|
|
135
|
+
]);
|
|
136
|
+
function upsertMeta(selector, attr, token, value) {
|
|
137
|
+
let el = document.head.querySelector(selector);
|
|
138
|
+
if (!el) {
|
|
139
|
+
el = document.createElement("meta");
|
|
140
|
+
el.setAttribute(attr, token);
|
|
141
|
+
document.head.appendChild(el);
|
|
142
|
+
}
|
|
143
|
+
if (el.getAttribute("content") !== value) el.setAttribute("content", value);
|
|
144
|
+
}
|
|
145
|
+
function escapeXml(value) {
|
|
146
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
147
|
+
}
|
|
148
|
+
function applyLetterFavicon(letter) {
|
|
149
|
+
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>`;
|
|
150
|
+
const href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
151
|
+
let link = document.head.querySelector('link[rel="icon"]');
|
|
152
|
+
if (!link) {
|
|
153
|
+
link = document.createElement("link");
|
|
154
|
+
link.rel = "icon";
|
|
155
|
+
document.head.appendChild(link);
|
|
156
|
+
}
|
|
157
|
+
link.type = "image/svg+xml";
|
|
158
|
+
if (link.href !== href) link.href = href;
|
|
159
|
+
}
|
|
160
|
+
function applyBrandChrome(content) {
|
|
161
|
+
const name = content[BRAND_NAME_KEY];
|
|
162
|
+
if (typeof name === "string" && name.length > 0) {
|
|
163
|
+
document.querySelectorAll("[data-ohw-wordmark]").forEach((el) => {
|
|
164
|
+
if (el.textContent !== name) el.textContent = name;
|
|
165
|
+
if (el.getAttribute("title") !== name) el.setAttribute("title", name);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
const title = content[BRAND_TITLE_KEY];
|
|
169
|
+
if (typeof title === "string" && title.length > 0) {
|
|
170
|
+
if (document.title !== title) document.title = title;
|
|
171
|
+
upsertMeta('meta[property="og:title"]', "property", "og:title", title);
|
|
172
|
+
upsertMeta('meta[name="twitter:title"]', "name", "twitter:title", title);
|
|
173
|
+
}
|
|
174
|
+
const letter = content[BRAND_FAVICON_LETTER_KEY];
|
|
175
|
+
if (typeof letter === "string" && letter.length > 0) {
|
|
176
|
+
applyLetterFavicon(letter);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/lib/brand-kit.ts
|
|
181
|
+
var BRAND_KIT_KEY = "__ohw_brand";
|
|
182
|
+
var BRAND_VAR_PREFIX = "--ohw-brand-";
|
|
183
|
+
var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
|
|
184
|
+
(role) => `${BRAND_VAR_PREFIX}${role}`
|
|
185
|
+
);
|
|
186
|
+
var FONT_VARS = {
|
|
187
|
+
heading: ["--font-heading", "--font-display", "--brand-font-heading"],
|
|
188
|
+
body: ["--font-body", "--brand-font-body"]
|
|
189
|
+
};
|
|
190
|
+
var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
|
|
191
|
+
function brandColorVars(kit) {
|
|
192
|
+
const { dark, primary, accent, light } = kit.palette;
|
|
193
|
+
const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
|
|
194
|
+
return {
|
|
195
|
+
[`${BRAND_VAR_PREFIX}primary`]: primary,
|
|
196
|
+
[`${BRAND_VAR_PREFIX}accent`]: accent,
|
|
197
|
+
[`${BRAND_VAR_PREFIX}light`]: light,
|
|
198
|
+
[`${BRAND_VAR_PREFIX}dark`]: dark,
|
|
199
|
+
[`${BRAND_VAR_PREFIX}surface`]: mix(light, 95, dark),
|
|
200
|
+
[`${BRAND_VAR_PREFIX}border`]: mix(light, 85, dark),
|
|
201
|
+
[`${BRAND_VAR_PREFIX}muted`]: mix(dark, 62, light)
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function parseBrandKit(raw) {
|
|
205
|
+
if (!raw) return null;
|
|
206
|
+
try {
|
|
207
|
+
const parsed = JSON.parse(raw);
|
|
208
|
+
const p = parsed?.palette;
|
|
209
|
+
const f = parsed?.fonts;
|
|
210
|
+
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") {
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
palette: { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light },
|
|
215
|
+
fonts: { heading: f.heading, body: f.body }
|
|
216
|
+
};
|
|
217
|
+
} catch {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function familyOf(stack) {
|
|
222
|
+
const first = stack.split(",")[0]?.trim() ?? "";
|
|
223
|
+
return first.replace(/^['"]|['"]$/g, "");
|
|
224
|
+
}
|
|
225
|
+
function loadBrandFonts(families) {
|
|
226
|
+
const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
|
|
227
|
+
if (unique.length === 0) return;
|
|
228
|
+
const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
|
|
229
|
+
const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
|
|
230
|
+
let link = document.getElementById(BRAND_FONT_LINK_ID);
|
|
231
|
+
if (!link) {
|
|
232
|
+
link = document.createElement("link");
|
|
233
|
+
link.id = BRAND_FONT_LINK_ID;
|
|
234
|
+
link.rel = "stylesheet";
|
|
235
|
+
document.head.appendChild(link);
|
|
236
|
+
}
|
|
237
|
+
if (link.href !== href) link.href = href;
|
|
238
|
+
}
|
|
239
|
+
function applyBrandToDom(kit) {
|
|
240
|
+
const root = document.documentElement;
|
|
241
|
+
if (!kit) {
|
|
242
|
+
for (const name of BRAND_VAR_NAMES) root.style.removeProperty(name);
|
|
243
|
+
for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
|
|
244
|
+
document.getElementById(BRAND_FONT_LINK_ID)?.remove();
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
for (const [name, value] of Object.entries(brandColorVars(kit))) root.style.setProperty(name, value);
|
|
248
|
+
for (const name of FONT_VARS.heading) root.style.setProperty(name, kit.fonts.heading);
|
|
249
|
+
for (const name of FONT_VARS.body) root.style.setProperty(name, kit.fonts.body);
|
|
250
|
+
loadBrandFonts([familyOf(kit.fonts.heading), familyOf(kit.fonts.body)]);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// src/lib/section-styles.ts
|
|
254
|
+
var STYLE_STORE_KEY = "__ohw_styles";
|
|
255
|
+
var STYLE_SHEET_ID = "ohw-section-styles";
|
|
256
|
+
function parseStyleStore(raw) {
|
|
257
|
+
if (!raw) return null;
|
|
258
|
+
try {
|
|
259
|
+
const parsed = JSON.parse(raw);
|
|
260
|
+
if (parsed?.v !== 1) return null;
|
|
261
|
+
return {
|
|
262
|
+
v: 1,
|
|
263
|
+
sections: typeof parsed.sections === "object" && parsed.sections ? parsed.sections : {},
|
|
264
|
+
nodes: typeof parsed.nodes === "object" && parsed.nodes ? parsed.nodes : {}
|
|
265
|
+
};
|
|
266
|
+
} catch {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
var BG_VALUES = {
|
|
271
|
+
surface: "color-mix(in srgb, var(--ohw-brand-light, var(--color-light, #ECECEB)) 94%, var(--ohw-brand-dark, var(--color-dark, #0C0A09)))",
|
|
272
|
+
accent: "var(--ohw-brand-primary, var(--color-primary, #0078E5))",
|
|
273
|
+
"accent-soft": "color-mix(in srgb, var(--ohw-brand-primary, var(--color-primary, #0078E5)) 12%, var(--ohw-brand-light, var(--color-light, #FFFFFF)))"
|
|
274
|
+
};
|
|
275
|
+
var HEADLINE_SIZES = { md: 24, lg: 32, xl: 40, display: 56 };
|
|
276
|
+
function styleSheetCss() {
|
|
277
|
+
const rules = [];
|
|
278
|
+
for (const [tone, value] of Object.entries(BG_VALUES)) {
|
|
279
|
+
rules.push(`[data-ohw-style-bg="${tone}"] { background: ${value} !important; }`);
|
|
280
|
+
}
|
|
281
|
+
rules.push(
|
|
282
|
+
`[data-ohw-style-bg="accent"] { color: var(--ohw-brand-light, var(--color-light, #FFFFFF)) !important; }`
|
|
283
|
+
);
|
|
284
|
+
rules.push(
|
|
285
|
+
`[data-ohw-style-distribution="space-between"] { display: flex !important; flex-direction: column; justify-content: space-between; }`,
|
|
286
|
+
`[data-ohw-style-distribution="center"] { display: flex !important; flex-direction: column; justify-content: center; }`
|
|
287
|
+
);
|
|
288
|
+
for (const [scale, size] of Object.entries(HEADLINE_SIZES)) {
|
|
289
|
+
rules.push(
|
|
290
|
+
`[data-ohw-style-headline="${scale}"] :is(h1, h2, h3) { font-size: ${size}px !important; line-height: 1.15 !important; }`
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
rules.push(
|
|
294
|
+
`[data-ohw-style-aspect="fill-height"] img { height: 100% !important; aspect-ratio: auto !important; object-fit: cover; }`
|
|
295
|
+
);
|
|
296
|
+
for (const aspect of ["1:1", "4:5", "3:4", "3:2", "16:9", "2:1", "3:1"]) {
|
|
297
|
+
rules.push(
|
|
298
|
+
`[data-ohw-style-aspect="${aspect.replace(":", "-")}"] img { aspect-ratio: ${aspect.replace(":", " / ")} !important; height: auto !important; object-fit: cover; }`
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
const pad = { tight: 40, balanced: 64, airy: 96 };
|
|
302
|
+
for (const [spacing, px] of Object.entries(pad)) {
|
|
303
|
+
rules.push(
|
|
304
|
+
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
return rules.join("\n");
|
|
308
|
+
}
|
|
309
|
+
var STYLE_FONT_LINK_ID = "ohw-style-fonts";
|
|
310
|
+
function loadStyleFonts(families) {
|
|
311
|
+
const unique = [...new Set(families.map((f) => f.trim()).filter(Boolean))];
|
|
312
|
+
const existing = document.getElementById(STYLE_FONT_LINK_ID);
|
|
313
|
+
if (unique.length === 0) {
|
|
314
|
+
existing?.remove();
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
const spec = unique.map((f) => `${f.replace(/ /g, "+")}:400,500,600,700`).join("|");
|
|
318
|
+
const href = `https://fonts.googleapis.com/css?family=${spec}&display=swap`;
|
|
319
|
+
let link = existing;
|
|
320
|
+
if (!link) {
|
|
321
|
+
link = document.createElement("link");
|
|
322
|
+
link.id = STYLE_FONT_LINK_ID;
|
|
323
|
+
link.rel = "stylesheet";
|
|
324
|
+
document.head.appendChild(link);
|
|
325
|
+
}
|
|
326
|
+
if (link.href !== href) link.href = href;
|
|
327
|
+
}
|
|
328
|
+
var SECTION_ATTRS = {
|
|
329
|
+
sectionBackground: "data-ohw-style-bg",
|
|
330
|
+
textDistribution: "data-ohw-style-distribution",
|
|
331
|
+
headlineScale: "data-ohw-style-headline",
|
|
332
|
+
imageAspect: "data-ohw-style-aspect",
|
|
333
|
+
spacing: "data-ohw-style-spacing"
|
|
334
|
+
};
|
|
335
|
+
var NODE_WROTE_ATTR = "data-ohw-style-node";
|
|
336
|
+
var NODE_PROPS = ["color", "font-family", "font-size", "background"];
|
|
337
|
+
function saveInline(el, prop) {
|
|
338
|
+
const attr = `data-ohw-style-prev-${prop}`;
|
|
339
|
+
if (!el.hasAttribute(attr)) el.setAttribute(attr, el.style.getPropertyValue(prop));
|
|
340
|
+
}
|
|
341
|
+
function restoreInline(el, prop) {
|
|
342
|
+
const attr = `data-ohw-style-prev-${prop}`;
|
|
343
|
+
if (!el.hasAttribute(attr)) return;
|
|
344
|
+
const prev = el.getAttribute(attr) ?? "";
|
|
345
|
+
if (prev) el.style.setProperty(prop, prev);
|
|
346
|
+
else el.style.removeProperty(prop);
|
|
347
|
+
el.removeAttribute(attr);
|
|
348
|
+
}
|
|
349
|
+
function ensureStyleSheet() {
|
|
350
|
+
let el = document.getElementById(STYLE_SHEET_ID);
|
|
351
|
+
if (!el) {
|
|
352
|
+
el = document.createElement("style");
|
|
353
|
+
el.id = STYLE_SHEET_ID;
|
|
354
|
+
document.head.appendChild(el);
|
|
355
|
+
}
|
|
356
|
+
const css = styleSheetCss();
|
|
357
|
+
if (el.textContent !== css) el.textContent = css;
|
|
358
|
+
}
|
|
359
|
+
function clearSectionAttrs(root) {
|
|
360
|
+
for (const attr of Object.values(SECTION_ATTRS)) {
|
|
361
|
+
for (const el of Array.from(root.querySelectorAll(`[${attr}]`))) el.removeAttribute(attr);
|
|
362
|
+
}
|
|
363
|
+
for (const el of Array.from(root.querySelectorAll("[data-ohw-style-bgcolor]"))) {
|
|
364
|
+
restoreInline(el, "background");
|
|
365
|
+
el.removeAttribute("data-ohw-style-bgcolor");
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
function clearNodeProps(root) {
|
|
369
|
+
for (const el of Array.from(root.querySelectorAll(`[${NODE_WROTE_ATTR}]`))) {
|
|
370
|
+
const h = el;
|
|
371
|
+
for (const prop of NODE_PROPS) restoreInline(h, prop);
|
|
372
|
+
h.removeAttribute(NODE_WROTE_ATTR);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
function buttonSurfaceOf(el) {
|
|
376
|
+
return el.closest("a, button") ?? el;
|
|
377
|
+
}
|
|
378
|
+
function applyStylesToDom(store) {
|
|
379
|
+
ensureStyleSheet();
|
|
380
|
+
clearSectionAttrs(document);
|
|
381
|
+
clearNodeProps(document);
|
|
382
|
+
loadStyleFonts(
|
|
383
|
+
store ? Object.values(store.nodes).flatMap((n) => n.fontFamily ? [n.fontFamily] : []) : []
|
|
384
|
+
);
|
|
385
|
+
if (!store) return;
|
|
386
|
+
for (const [sectionId, override] of Object.entries(store.sections)) {
|
|
387
|
+
const sections = document.querySelectorAll(
|
|
388
|
+
`[data-ohw-section="${CSS.escape(sectionId)}"]`
|
|
389
|
+
);
|
|
390
|
+
for (const section of Array.from(sections)) {
|
|
391
|
+
for (const [prop, attr] of Object.entries(SECTION_ATTRS)) {
|
|
392
|
+
const value = override[prop];
|
|
393
|
+
if (value === void 0) continue;
|
|
394
|
+
if (prop === "sectionBackground" && override.sectionBackgroundColor !== void 0) continue;
|
|
395
|
+
section.setAttribute(attr, String(value).replace(":", "-"));
|
|
396
|
+
}
|
|
397
|
+
if (override.sectionBackgroundColor !== void 0) {
|
|
398
|
+
saveInline(section, "background");
|
|
399
|
+
section.style.setProperty("background", override.sectionBackgroundColor, "important");
|
|
400
|
+
section.setAttribute("data-ohw-style-bgcolor", "");
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
for (const [key, override] of Object.entries(store.nodes)) {
|
|
405
|
+
const nodes = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
|
|
406
|
+
for (const el of Array.from(nodes)) {
|
|
407
|
+
if (override.color !== void 0) {
|
|
408
|
+
saveInline(el, "color");
|
|
409
|
+
el.style.setProperty("color", override.color, "important");
|
|
410
|
+
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
411
|
+
}
|
|
412
|
+
if (override.fontFamily !== void 0) {
|
|
413
|
+
saveInline(el, "font-family");
|
|
414
|
+
el.style.setProperty("font-family", `'${override.fontFamily}'`, "important");
|
|
415
|
+
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
416
|
+
}
|
|
417
|
+
if (override.fontSize !== void 0) {
|
|
418
|
+
saveInline(el, "font-size");
|
|
419
|
+
el.style.setProperty("font-size", `${override.fontSize}px`, "important");
|
|
420
|
+
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
421
|
+
}
|
|
422
|
+
if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
|
|
423
|
+
const surface = buttonSurfaceOf(el);
|
|
424
|
+
if (override.buttonBackground !== void 0) {
|
|
425
|
+
saveInline(surface, "background");
|
|
426
|
+
surface.style.setProperty("background", override.buttonBackground, "important");
|
|
427
|
+
}
|
|
428
|
+
if (override.buttonText !== void 0) {
|
|
429
|
+
saveInline(surface, "color");
|
|
430
|
+
surface.style.setProperty("color", override.buttonText, "important");
|
|
431
|
+
}
|
|
432
|
+
surface.setAttribute(NODE_WROTE_ATTR, "");
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
121
438
|
// src/ui/ai-tree/aiSectionsManager.tsx
|
|
122
439
|
import { flushSync } from "react-dom";
|
|
123
440
|
import { createRoot } from "react-dom/client";
|
|
@@ -132,7 +449,8 @@ function lucideByName(name) {
|
|
|
132
449
|
}
|
|
133
450
|
var typeStyle = (spec, font) => ({
|
|
134
451
|
fontFamily: font,
|
|
135
|
-
|
|
452
|
+
// Headings shrink with the viewport (reaching full size around ~900px wide); body copy stays put.
|
|
453
|
+
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,
|
|
136
454
|
lineHeight: spec.line,
|
|
137
455
|
fontWeight: spec.weight
|
|
138
456
|
});
|
|
@@ -141,12 +459,60 @@ var featureLines = (value) => value.split(/\n|<br\s*\/?>/i).map((line) => line.t
|
|
|
141
459
|
var CHECK_MASK = `data:image/svg+xml,${encodeURIComponent(
|
|
142
460
|
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>'
|
|
143
461
|
)}`;
|
|
462
|
+
var AI_MOBILE_CSS = [
|
|
463
|
+
"@media (max-width: 768px){",
|
|
464
|
+
"[data-ai-section]{overflow-x:hidden}",
|
|
465
|
+
"[data-ai-container]{padding:0 20px !important}",
|
|
466
|
+
"[data-ai-row]{display:flex !important;flex-direction:column !important;align-items:stretch !important}",
|
|
467
|
+
"[data-ai-cell]{width:100%;min-width:0}",
|
|
468
|
+
"[data-ai-grid]{grid-template-columns:1fr !important}",
|
|
469
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
470
|
+
"[data-ai-group]{display:flex !important;flex-direction:column !important}",
|
|
471
|
+
"[data-ai-group] > *{grid-column:auto !important}",
|
|
472
|
+
// The 50:50 form collapses to a single stacked column on phones.
|
|
473
|
+
"[data-ai-form]{grid-template-columns:1fr !important}",
|
|
474
|
+
"[data-ai-section] img{max-width:100%}",
|
|
475
|
+
"}",
|
|
476
|
+
"@media (min-width: 769px) and (max-width: 1024px){",
|
|
477
|
+
"[data-ai-grid]{grid-template-columns:repeat(2, 1fr) !important}",
|
|
478
|
+
"}"
|
|
479
|
+
].join("");
|
|
144
480
|
var FEATURE_LINE_CSS = [
|
|
145
481
|
"[data-ai-features]>div{position:relative;padding-left:40px;min-height:24px}",
|
|
146
482
|
'[data-ai-features]>div::before{content:"";position:absolute;left:0;top:1px;width:24px;height:24px;',
|
|
147
483
|
`background-color:currentColor;-webkit-mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px;`,
|
|
148
484
|
`mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px}`
|
|
149
485
|
].join("");
|
|
486
|
+
function hexLuminance(color) {
|
|
487
|
+
const m = /^#([0-9a-f]{6})$/i.exec(color.trim());
|
|
488
|
+
if (!m) return null;
|
|
489
|
+
const [r2, g, b] = [0, 2, 4].map((i) => {
|
|
490
|
+
const c = parseInt(m[1].slice(i, i + 2), 16) / 255;
|
|
491
|
+
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
492
|
+
});
|
|
493
|
+
return 0.2126 * r2 + 0.7152 * g + 0.0722 * b;
|
|
494
|
+
}
|
|
495
|
+
function hexContrast(a, b) {
|
|
496
|
+
const la = hexLuminance(a);
|
|
497
|
+
const lb = hexLuminance(b);
|
|
498
|
+
if (la === null || lb === null) return null;
|
|
499
|
+
const [hi, lo] = la > lb ? [la, lb] : [lb, la];
|
|
500
|
+
return (hi + 0.05) / (lo + 0.05);
|
|
501
|
+
}
|
|
502
|
+
function accentBandContext(brand) {
|
|
503
|
+
const p = brand.palette;
|
|
504
|
+
const lightWins = (hexContrast(p.light, p.primary) ?? 99) >= (hexContrast(p.dark, p.primary) ?? 0);
|
|
505
|
+
if (lightWins) {
|
|
506
|
+
return {
|
|
507
|
+
brand: { ...brand, palette: { dark: p.light, primary: p.light, accent: p.light, light: p.primary } },
|
|
508
|
+
buttonLabel: p.primary
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
return {
|
|
512
|
+
brand: { ...brand, palette: { dark: p.dark, primary: p.dark, accent: p.dark, light: p.light } },
|
|
513
|
+
buttonLabel: p.light
|
|
514
|
+
};
|
|
515
|
+
}
|
|
150
516
|
function textAttrs(ctx, path) {
|
|
151
517
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
152
518
|
}
|
|
@@ -158,7 +524,12 @@ var AI_RESPONSIVE_CSS = [
|
|
|
158
524
|
"@media (max-width: 640px) {",
|
|
159
525
|
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
160
526
|
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
527
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
528
|
+
" [data-ai-responsive] [data-ai-group] { display: flex !important; flex-direction: column !important; }",
|
|
529
|
+
" [data-ai-responsive] [data-ai-group] > * { grid-column: auto !important; }",
|
|
161
530
|
" [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
531
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
532
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
162
533
|
"}"
|
|
163
534
|
].join("\n");
|
|
164
535
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
@@ -236,7 +607,7 @@ function ButtonEl({
|
|
|
236
607
|
}) {
|
|
237
608
|
const secondary = slots.variant === "secondary";
|
|
238
609
|
const href = str(slots.href);
|
|
239
|
-
const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`) } : {};
|
|
610
|
+
const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`), "data-ohw-role": "button" } : {};
|
|
240
611
|
return /* @__PURE__ */ jsx(
|
|
241
612
|
"a",
|
|
242
613
|
{
|
|
@@ -252,7 +623,7 @@ function ButtonEl({
|
|
|
252
623
|
textDecoration: "none",
|
|
253
624
|
cursor: "pointer",
|
|
254
625
|
...typeStyle(AI_TREE_TOKENS.type.button, ctx.brand.fonts.body),
|
|
255
|
-
...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color: AI_TREE_TOKENS.textPrimaryForeground }
|
|
626
|
+
...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 }
|
|
256
627
|
},
|
|
257
628
|
children: /* @__PURE__ */ jsx("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
|
|
258
629
|
}
|
|
@@ -758,7 +1129,24 @@ function CardBlock({ node, ctx, path }) {
|
|
|
758
1129
|
minWidth: 0
|
|
759
1130
|
},
|
|
760
1131
|
children: [
|
|
761
|
-
media && (horizontal ? /* @__PURE__ */ jsx(
|
|
1132
|
+
media && (horizontal ? /* @__PURE__ */ jsx(
|
|
1133
|
+
"div",
|
|
1134
|
+
{
|
|
1135
|
+
style: (
|
|
1136
|
+
// An icon hugs its glyph — flex:1 gave a 48px icon half the card and pushed the
|
|
1137
|
+
// text to the far side. Photos keep the half-and-half split. The inset has no
|
|
1138
|
+
// inner padding (the photo split absorbed that), so the icon carries its own gap.
|
|
1139
|
+
/^(lucide|simple):/.test(mediaRef) ? {
|
|
1140
|
+
flexShrink: 0,
|
|
1141
|
+
display: "flex",
|
|
1142
|
+
alignItems: "center",
|
|
1143
|
+
padding: mediaInset,
|
|
1144
|
+
[mediaPosition === "right" ? "marginLeft" : "marginRight"]: 20
|
|
1145
|
+
} : { flex: 1, minWidth: 0, display: "flex", alignItems: "center", padding: mediaInset }
|
|
1146
|
+
),
|
|
1147
|
+
children: media
|
|
1148
|
+
}
|
|
1149
|
+
) : /* @__PURE__ */ jsx(
|
|
762
1150
|
"div",
|
|
763
1151
|
{
|
|
764
1152
|
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" },
|
|
@@ -849,13 +1237,44 @@ function AccordionBlock({ node, ctx, path }) {
|
|
|
849
1237
|
) })
|
|
850
1238
|
] }, i)) });
|
|
851
1239
|
}
|
|
1240
|
+
function useIsMobile() {
|
|
1241
|
+
const [mobile, setMobile] = React.useState(
|
|
1242
|
+
() => typeof window !== "undefined" && window.matchMedia("(max-width: 768px)").matches
|
|
1243
|
+
);
|
|
1244
|
+
React.useEffect(() => {
|
|
1245
|
+
const mq = window.matchMedia("(max-width: 768px)");
|
|
1246
|
+
const update = () => setMobile(mq.matches);
|
|
1247
|
+
update();
|
|
1248
|
+
mq.addEventListener("change", update);
|
|
1249
|
+
return () => mq.removeEventListener("change", update);
|
|
1250
|
+
}, []);
|
|
1251
|
+
return mobile;
|
|
1252
|
+
}
|
|
852
1253
|
function Carousel({ items, itemsPerRow, ctx }) {
|
|
1254
|
+
const isMobile = useIsMobile();
|
|
1255
|
+
const perPage = isMobile ? 1 : itemsPerRow;
|
|
1256
|
+
const pages = Math.max(1, Math.ceil(items.length / perPage));
|
|
853
1257
|
const [page, setPage] = React.useState(0);
|
|
854
|
-
const pages = Math.max(1, Math.ceil(items.length / itemsPerRow));
|
|
855
1258
|
const current = Math.min(page, pages - 1);
|
|
1259
|
+
if (pages <= 1) {
|
|
1260
|
+
const cols = Math.max(1, Math.min(items.length, itemsPerRow));
|
|
1261
|
+
return /* @__PURE__ */ jsx(
|
|
1262
|
+
"div",
|
|
1263
|
+
{
|
|
1264
|
+
"data-ai-grid": String(cols),
|
|
1265
|
+
style: {
|
|
1266
|
+
display: "grid",
|
|
1267
|
+
gridTemplateColumns: `repeat(${cols}, 1fr)`,
|
|
1268
|
+
gap: AI_TREE_TOKENS.spacing8,
|
|
1269
|
+
alignItems: "start"
|
|
1270
|
+
},
|
|
1271
|
+
children: items
|
|
1272
|
+
}
|
|
1273
|
+
);
|
|
1274
|
+
}
|
|
856
1275
|
const pageGroups = Array.from(
|
|
857
1276
|
{ length: pages },
|
|
858
|
-
(_, p) => items.slice(p *
|
|
1277
|
+
(_, p) => items.slice(p * perPage, (p + 1) * perPage)
|
|
859
1278
|
);
|
|
860
1279
|
const chrome = (enabled) => ({
|
|
861
1280
|
border: `1px solid ${ctx.brand.palette.dark}`,
|
|
@@ -880,55 +1299,69 @@ function Carousel({ items, itemsPerRow, ctx }) {
|
|
|
880
1299
|
cursor: "pointer",
|
|
881
1300
|
padding: 0
|
|
882
1301
|
});
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
children: /* @__PURE__ */ jsx(ArrowLeft, { size: 24, strokeWidth: 1.5, "aria-hidden": true })
|
|
893
|
-
}
|
|
894
|
-
),
|
|
895
|
-
/* @__PURE__ */ jsx("div", { style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx(
|
|
1302
|
+
const viewport = /* @__PURE__ */ jsx("div", { style: { flex: isMobile ? "0 0 auto" : 1, minWidth: 0, width: "100%", overflow: "hidden" }, children: /* @__PURE__ */ jsx(
|
|
1303
|
+
"div",
|
|
1304
|
+
{
|
|
1305
|
+
style: {
|
|
1306
|
+
display: "flex",
|
|
1307
|
+
transform: `translateX(-${current * 100}%)`,
|
|
1308
|
+
transition: "transform 0.4s ease"
|
|
1309
|
+
},
|
|
1310
|
+
children: pageGroups.map((group, p) => /* @__PURE__ */ jsx(
|
|
896
1311
|
"div",
|
|
897
1312
|
{
|
|
1313
|
+
"data-ai-grid": String(perPage),
|
|
898
1314
|
style: {
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
1315
|
+
flex: "0 0 100%",
|
|
1316
|
+
display: "grid",
|
|
1317
|
+
gridTemplateColumns: `repeat(${perPage}, 1fr)`,
|
|
1318
|
+
gap: AI_TREE_TOKENS.spacing8,
|
|
1319
|
+
alignItems: "start"
|
|
902
1320
|
},
|
|
903
|
-
children:
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
1321
|
+
children: group
|
|
1322
|
+
},
|
|
1323
|
+
p
|
|
1324
|
+
))
|
|
1325
|
+
}
|
|
1326
|
+
) });
|
|
1327
|
+
const prevBtn = /* @__PURE__ */ jsx(
|
|
1328
|
+
"button",
|
|
1329
|
+
{
|
|
1330
|
+
type: "button",
|
|
1331
|
+
"aria-label": "Previous",
|
|
1332
|
+
onClick: () => setPage((p) => Math.max(0, p - 1)),
|
|
1333
|
+
style: chrome(current > 0),
|
|
1334
|
+
children: /* @__PURE__ */ jsx(ArrowLeft, { size: 24, strokeWidth: 1.5, "aria-hidden": true })
|
|
1335
|
+
}
|
|
1336
|
+
);
|
|
1337
|
+
const nextBtn = /* @__PURE__ */ jsx(
|
|
1338
|
+
"button",
|
|
1339
|
+
{
|
|
1340
|
+
type: "button",
|
|
1341
|
+
"aria-label": "Next",
|
|
1342
|
+
onClick: () => setPage((p) => Math.min(pages - 1, p + 1)),
|
|
1343
|
+
style: chrome(current < pages - 1),
|
|
1344
|
+
children: /* @__PURE__ */ jsx(ArrowRight, { size: 24, strokeWidth: 1.5, "aria-hidden": true })
|
|
1345
|
+
}
|
|
1346
|
+
);
|
|
1347
|
+
const dots = /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: 9, justifyContent: "center" }, children: pageGroups.map((_, p) => /* @__PURE__ */ jsx("button", { type: "button", "aria-label": `Page ${p + 1}`, onClick: () => setPage(p), style: dot(p === current) }, p)) });
|
|
1348
|
+
if (isMobile) {
|
|
1349
|
+
return /* @__PURE__ */ jsxs("div", { "data-ai-carousel": "", style: { display: "flex", flexDirection: "column", gap: AI_TREE_TOKENS.spacing6, alignItems: "center" }, children: [
|
|
1350
|
+
viewport,
|
|
1351
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: AI_TREE_TOKENS.spacing6, justifyContent: "center" }, children: [
|
|
1352
|
+
prevBtn,
|
|
1353
|
+
nextBtn
|
|
1354
|
+
] }),
|
|
1355
|
+
dots
|
|
1356
|
+
] });
|
|
1357
|
+
}
|
|
1358
|
+
return /* @__PURE__ */ jsxs("div", { "data-ai-carousel": "", style: { display: "flex", flexDirection: "column", gap: AI_TREE_TOKENS.spacing8, alignItems: "center" }, children: [
|
|
1359
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: AI_TREE_TOKENS.spacing6, width: "100%" }, children: [
|
|
1360
|
+
prevBtn,
|
|
1361
|
+
viewport,
|
|
1362
|
+
nextBtn
|
|
930
1363
|
] }),
|
|
931
|
-
|
|
1364
|
+
dots
|
|
932
1365
|
] });
|
|
933
1366
|
}
|
|
934
1367
|
function CollectionBlock({ node, ctx, path }) {
|
|
@@ -1022,6 +1455,49 @@ function renderNode(node, ctx, path) {
|
|
|
1022
1455
|
switch (node.type) {
|
|
1023
1456
|
case "text":
|
|
1024
1457
|
return /* @__PURE__ */ jsx(TextBlock, { slots, ctx, path });
|
|
1458
|
+
// Layout container: arranges child blocks, contributes no content of its own. `grid` is a
|
|
1459
|
+
// nested 12-column grid the children span (a collage is 3–5 media on it, bottom-aligned so
|
|
1460
|
+
// mixed aspects read as a composition); `split` is exactly two children at a ratio; `stack`
|
|
1461
|
+
// is a column. Children render through this same dispatcher, so edit markers, media
|
|
1462
|
+
// resolution, and copy paths all work unchanged inside a group.
|
|
1463
|
+
case "group": {
|
|
1464
|
+
const layout = str(slots.layout);
|
|
1465
|
+
const gap = slots.spacing === "tight" ? AI_TREE_TOKENS.spacing3 : slots.spacing === "airy" ? AI_TREE_TOKENS.spacing8 : AI_TREE_TOKENS.spacing6;
|
|
1466
|
+
const kids = (node.children ?? []).map((child, i) => /* @__PURE__ */ jsx(
|
|
1467
|
+
"div",
|
|
1468
|
+
{
|
|
1469
|
+
style: layout === "grid" ? {
|
|
1470
|
+
gridColumn: `span ${typeof child.span === "number" ? Math.min(12, Math.max(1, child.span)) : 12}`,
|
|
1471
|
+
minWidth: 0
|
|
1472
|
+
} : { minWidth: 0 },
|
|
1473
|
+
children: renderNode(child, ctx, `${path}.c${i}`)
|
|
1474
|
+
},
|
|
1475
|
+
i
|
|
1476
|
+
));
|
|
1477
|
+
if (layout === "grid") {
|
|
1478
|
+
return /* @__PURE__ */ jsx(
|
|
1479
|
+
"div",
|
|
1480
|
+
{
|
|
1481
|
+
"data-ai-group": "grid",
|
|
1482
|
+
style: { display: "grid", gridTemplateColumns: "repeat(12, 1fr)", gap, alignItems: "end" },
|
|
1483
|
+
children: kids
|
|
1484
|
+
}
|
|
1485
|
+
);
|
|
1486
|
+
}
|
|
1487
|
+
if (layout === "split") {
|
|
1488
|
+
const ratio = str(slots.ratio);
|
|
1489
|
+
const cols = ratio === "3:5" ? "3fr 5fr" : ratio === "5:3" ? "5fr 3fr" : "1fr 1fr";
|
|
1490
|
+
return /* @__PURE__ */ jsx(
|
|
1491
|
+
"div",
|
|
1492
|
+
{
|
|
1493
|
+
"data-ai-group": "split",
|
|
1494
|
+
style: { display: "grid", gridTemplateColumns: cols, gap, alignItems: "center" },
|
|
1495
|
+
children: kids
|
|
1496
|
+
}
|
|
1497
|
+
);
|
|
1498
|
+
}
|
|
1499
|
+
return /* @__PURE__ */ jsx("div", { "data-ai-group": "stack", style: { display: "flex", flexDirection: "column", gap }, children: kids });
|
|
1500
|
+
}
|
|
1025
1501
|
case "button":
|
|
1026
1502
|
return /* @__PURE__ */ jsx(ButtonEl, { slots, ctx, path });
|
|
1027
1503
|
case "button-row":
|
|
@@ -1102,33 +1578,102 @@ function renderNode(node, ctx, path) {
|
|
|
1102
1578
|
}
|
|
1103
1579
|
);
|
|
1104
1580
|
}
|
|
1105
|
-
case "form":
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1581
|
+
case "form": {
|
|
1582
|
+
const formAttrs = ctx.keyFor ? {
|
|
1583
|
+
"data-ohw-editable": "form",
|
|
1584
|
+
"data-ohw-key": ctx.keyFor(`${path}.form`),
|
|
1585
|
+
"data-ohw-success-text": "Thanks \u2014 we'll be in touch shortly."
|
|
1586
|
+
} : {};
|
|
1587
|
+
const fieldStyle = {
|
|
1588
|
+
width: "100%",
|
|
1589
|
+
boxSizing: "border-box",
|
|
1590
|
+
border: `1px solid ${ctx.brand.palette.accent}`,
|
|
1591
|
+
borderRadius: AI_TREE_TOKENS.radiusButton,
|
|
1592
|
+
padding: "12px 14px",
|
|
1593
|
+
background: "#fff",
|
|
1594
|
+
color: ctx.brand.palette.dark,
|
|
1595
|
+
outline: "none",
|
|
1596
|
+
...typeStyle(AI_TREE_TOKENS.type.bodyM, ctx.brand.fonts.body)
|
|
1597
|
+
};
|
|
1598
|
+
const labelStyle = {
|
|
1599
|
+
...typeStyle(AI_TREE_TOKENS.type.bodyMBold, ctx.brand.fonts.body),
|
|
1600
|
+
color: ctx.brand.palette.dark
|
|
1601
|
+
};
|
|
1602
|
+
return /* @__PURE__ */ jsx(
|
|
1603
|
+
"form",
|
|
1604
|
+
{
|
|
1605
|
+
...formAttrs,
|
|
1606
|
+
"data-ai-form": "",
|
|
1607
|
+
style: {
|
|
1608
|
+
display: "grid",
|
|
1609
|
+
gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
|
|
1610
|
+
columnGap: 64,
|
|
1611
|
+
rowGap: AI_TREE_TOKENS.spacing4
|
|
1612
|
+
},
|
|
1613
|
+
children: (node.children ?? []).map((child, i) => {
|
|
1614
|
+
if (child.type === "input") {
|
|
1615
|
+
const cs2 = child.slots ?? {};
|
|
1616
|
+
const kind = str(cs2.kind);
|
|
1617
|
+
const label = str(cs2.label);
|
|
1618
|
+
const placeholder = str(cs2.placeholder);
|
|
1619
|
+
const name = label.toLowerCase().replace(/[^a-z0-9]+/gu, "-").replace(/^-+|-+$/gu, "") || `field-${i}`;
|
|
1620
|
+
const isTextarea = kind === "textarea";
|
|
1621
|
+
return /* @__PURE__ */ jsxs(
|
|
1622
|
+
"div",
|
|
1623
|
+
{
|
|
1624
|
+
style: {
|
|
1625
|
+
display: "flex",
|
|
1626
|
+
flexDirection: "column",
|
|
1627
|
+
gap: 8,
|
|
1628
|
+
...isTextarea ? { gridColumn: "1 / -1", maxWidth: 780 } : {}
|
|
1629
|
+
},
|
|
1630
|
+
children: [
|
|
1631
|
+
/* @__PURE__ */ jsx("label", { ...textAttrs(ctx, `${path}.c${i}.label`), style: labelStyle, children: label }),
|
|
1632
|
+
isTextarea ? /* @__PURE__ */ jsx(
|
|
1633
|
+
"textarea",
|
|
1634
|
+
{
|
|
1635
|
+
name,
|
|
1636
|
+
placeholder,
|
|
1637
|
+
style: { ...fieldStyle, height: 140, resize: "vertical" }
|
|
1638
|
+
}
|
|
1639
|
+
) : /* @__PURE__ */ jsx(
|
|
1640
|
+
"input",
|
|
1641
|
+
{
|
|
1642
|
+
name,
|
|
1643
|
+
type: kind === "email" ? "email" : "text",
|
|
1644
|
+
placeholder,
|
|
1645
|
+
style: { ...fieldStyle, height: 48 }
|
|
1646
|
+
}
|
|
1647
|
+
)
|
|
1648
|
+
]
|
|
1649
|
+
},
|
|
1650
|
+
i
|
|
1651
|
+
);
|
|
1652
|
+
}
|
|
1653
|
+
const cs = child.slots ?? {};
|
|
1654
|
+
return /* @__PURE__ */ jsx(
|
|
1655
|
+
"button",
|
|
1120
1656
|
{
|
|
1657
|
+
type: "submit",
|
|
1121
1658
|
style: {
|
|
1122
|
-
|
|
1659
|
+
gridColumn: "1 / -1",
|
|
1660
|
+
justifySelf: "start",
|
|
1661
|
+
border: "none",
|
|
1662
|
+
cursor: "pointer",
|
|
1663
|
+
padding: `${AI_TREE_TOKENS.spacing3}px ${AI_TREE_TOKENS.spacing6}px`,
|
|
1123
1664
|
borderRadius: AI_TREE_TOKENS.radiusButton,
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1665
|
+
background: ctx.brand.palette.primary,
|
|
1666
|
+
color: AI_TREE_TOKENS.textPrimaryForeground,
|
|
1667
|
+
...typeStyle(AI_TREE_TOKENS.type.button, ctx.brand.fonts.body)
|
|
1668
|
+
},
|
|
1669
|
+
children: /* @__PURE__ */ jsx("span", { ...textAttrs(ctx, `${path}.c${i}.label`), children: str(cs.label) })
|
|
1670
|
+
},
|
|
1671
|
+
i
|
|
1672
|
+
);
|
|
1673
|
+
})
|
|
1129
1674
|
}
|
|
1130
|
-
|
|
1131
|
-
|
|
1675
|
+
);
|
|
1676
|
+
}
|
|
1132
1677
|
case "schedule-widget":
|
|
1133
1678
|
return /* @__PURE__ */ jsx(
|
|
1134
1679
|
"div",
|
|
@@ -1154,11 +1699,14 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1154
1699
|
return null;
|
|
1155
1700
|
}
|
|
1156
1701
|
const resolvedBrand = brand ?? AI_DEFAULT_BRAND;
|
|
1702
|
+
const band = (tree.settings ?? {}).sectionBackground === "accent" ? accentBandContext(resolvedBrand) : null;
|
|
1703
|
+
const blockBrand = band?.brand ?? resolvedBrand;
|
|
1157
1704
|
const ctx = {
|
|
1158
|
-
brand:
|
|
1705
|
+
brand: blockBrand,
|
|
1159
1706
|
resolveMedia: resolveMedia ?? (() => null),
|
|
1160
|
-
cardSurface:
|
|
1161
|
-
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null
|
|
1707
|
+
cardSurface: blockBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${blockBrand.palette.light} 90%, ${blockBrand.palette.dark})`,
|
|
1708
|
+
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
|
|
1709
|
+
...band ? { buttonLabel: band.buttonLabel } : {}
|
|
1162
1710
|
};
|
|
1163
1711
|
const settings = tree.settings ?? {};
|
|
1164
1712
|
const pad = AI_TREE_TOKENS.sectionPadding[settings.spacing ?? "balanced"];
|
|
@@ -1166,6 +1714,20 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1166
1714
|
const overlayAlpha = { low: 0.25, medium: 0.45, high: 0.65 }[settings.overlayIntensity ?? "medium"];
|
|
1167
1715
|
const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
|
|
1168
1716
|
const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
|
|
1717
|
+
const toneBackground = (() => {
|
|
1718
|
+
const { dark, primary, light } = resolvedBrand.palette;
|
|
1719
|
+
switch (settings.sectionBackground) {
|
|
1720
|
+
case "surface":
|
|
1721
|
+
return `color-mix(in srgb, ${light} 94%, ${dark})`;
|
|
1722
|
+
case "accent":
|
|
1723
|
+
return primary;
|
|
1724
|
+
case "accent-soft":
|
|
1725
|
+
return `color-mix(in srgb, ${primary} 12%, ${light})`;
|
|
1726
|
+
default:
|
|
1727
|
+
return void 0;
|
|
1728
|
+
}
|
|
1729
|
+
})();
|
|
1730
|
+
const distributed = !isOverlay && settings.textDistribution;
|
|
1169
1731
|
return /* @__PURE__ */ jsxs(
|
|
1170
1732
|
"section",
|
|
1171
1733
|
{
|
|
@@ -1175,13 +1737,15 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1175
1737
|
style: {
|
|
1176
1738
|
position: "relative",
|
|
1177
1739
|
padding: `${pad}px 0`,
|
|
1178
|
-
background: isOverlay && !backgroundUrl ? "#DBEAFE" : void 0,
|
|
1740
|
+
background: toneBackground ?? (isOverlay && !backgroundUrl ? "#DBEAFE" : void 0),
|
|
1179
1741
|
backgroundImage: backgroundUrl ? `url(${backgroundUrl})` : void 0,
|
|
1180
1742
|
backgroundSize: "cover",
|
|
1181
|
-
backgroundPosition: "center"
|
|
1743
|
+
backgroundPosition: "center",
|
|
1744
|
+
color: settings.sectionBackground === "accent" ? blockBrand.palette.dark : void 0
|
|
1182
1745
|
},
|
|
1183
1746
|
children: [
|
|
1184
1747
|
/* @__PURE__ */ jsx("style", { children: AI_RESPONSIVE_CSS }),
|
|
1748
|
+
/* @__PURE__ */ jsx("style", { children: AI_MOBILE_CSS }),
|
|
1185
1749
|
isOverlay && backgroundUrl && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
1186
1750
|
/* @__PURE__ */ jsx(
|
|
1187
1751
|
"div",
|
|
@@ -1202,10 +1766,24 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1202
1766
|
display: "grid",
|
|
1203
1767
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
1204
1768
|
gap: AI_TREE_TOKENS.spacing6,
|
|
1205
|
-
alignItems: settings.verticalPosition === "top" ? "start" : "center",
|
|
1769
|
+
alignItems: distributed === "space-between" ? "stretch" : (distributed ?? settings.verticalPosition) === "top" ? "start" : "center",
|
|
1206
1770
|
marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
|
|
1207
1771
|
},
|
|
1208
|
-
children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ jsx(
|
|
1772
|
+
children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ jsx(
|
|
1773
|
+
"div",
|
|
1774
|
+
{
|
|
1775
|
+
"data-ai-cell": "",
|
|
1776
|
+
style: {
|
|
1777
|
+
gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
|
|
1778
|
+
minWidth: 0,
|
|
1779
|
+
// space-between: each column becomes a flex column whose content spreads over
|
|
1780
|
+
// the full row height instead of clumping at the top.
|
|
1781
|
+
...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
|
|
1782
|
+
},
|
|
1783
|
+
children: renderNode(block, ctx, `r${r2}.b${b}`)
|
|
1784
|
+
},
|
|
1785
|
+
b
|
|
1786
|
+
))
|
|
1209
1787
|
},
|
|
1210
1788
|
r2
|
|
1211
1789
|
))
|
|
@@ -1221,17 +1799,36 @@ import { jsx as jsx2 } from "react/jsx-runtime";
|
|
|
1221
1799
|
var CONTAINER_ATTR = "data-ohw-ai-generated";
|
|
1222
1800
|
var REPLACED_ATTR = "data-ohw-ai-replaced-by";
|
|
1223
1801
|
var REMOVED_ATTR = "data-ohw-ai-removed";
|
|
1802
|
+
var TEMPLATE_HIDDEN_ATTR = "data-ohw-ai-template-hidden";
|
|
1803
|
+
var CHROME_SECTION_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
1804
|
+
function readRootVar(name) {
|
|
1805
|
+
if (typeof document === "undefined") return "";
|
|
1806
|
+
return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
|
1807
|
+
}
|
|
1808
|
+
function deriveBrandOverride() {
|
|
1809
|
+
const dark = readRootVar("--ohw-brand-dark");
|
|
1810
|
+
const primary = readRootVar("--ohw-brand-primary");
|
|
1811
|
+
const light = readRootVar("--ohw-brand-light");
|
|
1812
|
+
if (!dark || !primary || !light) return null;
|
|
1813
|
+
const accent = readRootVar("--ohw-brand-accent");
|
|
1814
|
+
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
1815
|
+
const body = readRootVar("--font-body");
|
|
1816
|
+
return {
|
|
1817
|
+
palette: { dark, primary, accent: accent || dark, light },
|
|
1818
|
+
fonts: {
|
|
1819
|
+
heading: heading || AI_DEFAULT_BRAND.fonts.heading,
|
|
1820
|
+
body: body || AI_DEFAULT_BRAND.fonts.body
|
|
1821
|
+
}
|
|
1822
|
+
};
|
|
1823
|
+
}
|
|
1224
1824
|
function deriveTemplateBrand() {
|
|
1225
|
-
|
|
1226
|
-
const
|
|
1227
|
-
const
|
|
1228
|
-
const dark = read("--color-dark");
|
|
1229
|
-
const primary = read("--color-primary");
|
|
1230
|
-
const light = read("--color-light");
|
|
1825
|
+
const dark = readRootVar("--color-dark");
|
|
1826
|
+
const primary = readRootVar("--color-primary");
|
|
1827
|
+
const light = readRootVar("--color-light");
|
|
1231
1828
|
if (!dark || !primary || !light) return null;
|
|
1232
|
-
const accent =
|
|
1233
|
-
const heading =
|
|
1234
|
-
const body =
|
|
1829
|
+
const accent = readRootVar("--color-accent");
|
|
1830
|
+
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
1831
|
+
const body = readRootVar("--font-body");
|
|
1235
1832
|
return {
|
|
1236
1833
|
palette: { dark, primary, accent: accent || dark, light },
|
|
1237
1834
|
fonts: {
|
|
@@ -1303,6 +1900,24 @@ function syncRemovedSections(state) {
|
|
|
1303
1900
|
}
|
|
1304
1901
|
}
|
|
1305
1902
|
}
|
|
1903
|
+
function syncTemplateHidden(state, pageHasSections) {
|
|
1904
|
+
const hide = state.hideTemplate === true && pageHasSections;
|
|
1905
|
+
for (const el of Array.from(document.querySelectorAll(`[${TEMPLATE_HIDDEN_ATTR}]`))) {
|
|
1906
|
+
if (!hide) {
|
|
1907
|
+
el.style.removeProperty("display");
|
|
1908
|
+
el.removeAttribute(TEMPLATE_HIDDEN_ATTR);
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
if (!hide) return;
|
|
1912
|
+
for (const el of Array.from(document.querySelectorAll("[data-ohw-section]"))) {
|
|
1913
|
+
if (el.hasAttribute(CONTAINER_ATTR)) continue;
|
|
1914
|
+
if (CHROME_SECTION_IDS.has(el.getAttribute("data-ohw-section") ?? "")) continue;
|
|
1915
|
+
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
1916
|
+
if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(REMOVED_ATTR)) continue;
|
|
1917
|
+
el.style.display = "none";
|
|
1918
|
+
el.setAttribute(TEMPLATE_HIDDEN_ATTR, "");
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1306
1921
|
function syncReplacedOriginals(state) {
|
|
1307
1922
|
for (const el of document.querySelectorAll(`[${REPLACED_ATTR}]`)) {
|
|
1308
1923
|
const byId = el.getAttribute(REPLACED_ATTR) ?? "";
|
|
@@ -1321,10 +1936,63 @@ function syncReplacedOriginals(state) {
|
|
|
1321
1936
|
}
|
|
1322
1937
|
}
|
|
1323
1938
|
}
|
|
1939
|
+
var sectionOrderIndex = /* @__PURE__ */ new Map();
|
|
1940
|
+
function setAiSectionOrder(raw, currentPath) {
|
|
1941
|
+
const next = /* @__PURE__ */ new Map();
|
|
1942
|
+
if (raw) {
|
|
1943
|
+
try {
|
|
1944
|
+
const entries = JSON.parse(raw);
|
|
1945
|
+
for (const entry of entries) {
|
|
1946
|
+
if (!entry.pagePath || entry.pagePath === currentPath) next.set(entry.instanceId, entry.order);
|
|
1947
|
+
}
|
|
1948
|
+
} catch {
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
sectionOrderIndex = next;
|
|
1952
|
+
}
|
|
1953
|
+
function applyExplicitOrder(entries) {
|
|
1954
|
+
if (sectionOrderIndex.size === 0) return entries;
|
|
1955
|
+
return entries.map((entry, index) => ({ entry, index, order: sectionOrderIndex.get(entry.id) })).sort((a, b) => {
|
|
1956
|
+
if (a.order === void 0 && b.order === void 0) return a.index - b.index;
|
|
1957
|
+
if (a.order === void 0) return 1;
|
|
1958
|
+
if (b.order === void 0) return -1;
|
|
1959
|
+
return a.order - b.order;
|
|
1960
|
+
}).map((item) => item.entry);
|
|
1961
|
+
}
|
|
1962
|
+
function orderByChain(sections) {
|
|
1963
|
+
const ids = new Set(sections.map((entry) => entry.id));
|
|
1964
|
+
const after = /* @__PURE__ */ new Map();
|
|
1965
|
+
const roots = [];
|
|
1966
|
+
for (const entry of sections) {
|
|
1967
|
+
const anchor = entry.replaces ?? entry.beforeSection ?? entry.afterSection ?? null;
|
|
1968
|
+
if (anchor && ids.has(anchor)) {
|
|
1969
|
+
const bucket = after.get(anchor);
|
|
1970
|
+
if (bucket) bucket.push(entry);
|
|
1971
|
+
else after.set(anchor, [entry]);
|
|
1972
|
+
} else {
|
|
1973
|
+
roots.push(entry);
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
const out = [];
|
|
1977
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1978
|
+
const visit = (entry) => {
|
|
1979
|
+
if (seen.has(entry.id)) return;
|
|
1980
|
+
seen.add(entry.id);
|
|
1981
|
+
out.push(entry);
|
|
1982
|
+
for (const child of after.get(entry.id) ?? []) visit(child);
|
|
1983
|
+
};
|
|
1984
|
+
for (const root of roots) visit(root);
|
|
1985
|
+
return out.length === sections.length ? out : sections;
|
|
1986
|
+
}
|
|
1324
1987
|
function applyAiSectionsToDom(state, options) {
|
|
1325
1988
|
if (typeof document === "undefined") return;
|
|
1989
|
+
const brandOverride = deriveBrandOverride();
|
|
1326
1990
|
const templateBrand = deriveTemplateBrand();
|
|
1327
|
-
const
|
|
1991
|
+
const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
|
|
1992
|
+
const pagePath = window.location.pathname;
|
|
1993
|
+
const pageSections = state.sections.filter((entry) => (entry.path ?? "/") === pagePath);
|
|
1994
|
+
const activeIds = new Set(pageSections.map((entry) => entry.id));
|
|
1995
|
+
const ordered = state.hideTemplate === true ? applyExplicitOrder(orderByChain(pageSections)) : pageSections;
|
|
1328
1996
|
for (const [id, section] of mounted) {
|
|
1329
1997
|
if (!activeIds.has(id)) {
|
|
1330
1998
|
section.root.unmount();
|
|
@@ -1332,8 +2000,8 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1332
2000
|
mounted.delete(id);
|
|
1333
2001
|
}
|
|
1334
2002
|
}
|
|
1335
|
-
for (const entry of
|
|
1336
|
-
const serialized = JSON.stringify(entry);
|
|
2003
|
+
for (const entry of ordered) {
|
|
2004
|
+
const serialized = JSON.stringify(entry) + brandKey;
|
|
1337
2005
|
const existing = mounted.get(entry.id);
|
|
1338
2006
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
1339
2007
|
continue;
|
|
@@ -1347,6 +2015,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1347
2015
|
mounted.delete(entry.id);
|
|
1348
2016
|
}
|
|
1349
2017
|
container.setAttribute("data-ohw-section", entry.id);
|
|
2018
|
+
container.setAttribute("data-ohw-instance", entry.id);
|
|
1350
2019
|
container.setAttribute("data-ohw-section-label", entry.label);
|
|
1351
2020
|
placeContainer(container, entry);
|
|
1352
2021
|
const root = mounted.get(entry.id)?.root ?? createRoot(container);
|
|
@@ -1357,7 +2026,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1357
2026
|
AiTreeRenderer,
|
|
1358
2027
|
{
|
|
1359
2028
|
tree: entry.tree,
|
|
1360
|
-
brand: entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
2029
|
+
brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
1361
2030
|
resolveMedia,
|
|
1362
2031
|
editKeyPrefix: `ai.${entry.id}`
|
|
1363
2032
|
}
|
|
@@ -1366,8 +2035,20 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1366
2035
|
});
|
|
1367
2036
|
mounted.set(entry.id, { root, container, serialized });
|
|
1368
2037
|
}
|
|
2038
|
+
if (state.hideTemplate === true) {
|
|
2039
|
+
let prev = null;
|
|
2040
|
+
for (const entry of ordered) {
|
|
2041
|
+
const el = mounted.get(entry.id)?.container;
|
|
2042
|
+
if (!el) continue;
|
|
2043
|
+
if (prev && !(prev.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING)) {
|
|
2044
|
+
prev.insertAdjacentElement("afterend", el);
|
|
2045
|
+
}
|
|
2046
|
+
prev = el;
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
1369
2049
|
syncReplacedOriginals(state);
|
|
1370
2050
|
syncRemovedSections(state);
|
|
2051
|
+
syncTemplateHidden(state, pageSections.length > 0);
|
|
1371
2052
|
}
|
|
1372
2053
|
|
|
1373
2054
|
// src/useLinkHrefGuardian.ts
|
|
@@ -1974,7 +2655,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
1974
2655
|
const autoId = useId();
|
|
1975
2656
|
const insertAfter = insertAfterProp ?? autoId;
|
|
1976
2657
|
const [schedule, setSchedule] = useState2(null);
|
|
1977
|
-
const [loading, setLoading] = useState2(
|
|
2658
|
+
const [loading, setLoading] = useState2(initialScheduleId !== null);
|
|
1978
2659
|
const [inEditor, setInEditor] = useState2(false);
|
|
1979
2660
|
const [isHovered, setIsHovered] = useState2(false);
|
|
1980
2661
|
const [modalState, setModalState] = useState2(null);
|
|
@@ -2148,8 +2829,10 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
2148
2829
|
"*"
|
|
2149
2830
|
);
|
|
2150
2831
|
};
|
|
2151
|
-
if (!inEditor && !loading && !schedule) return null;
|
|
2152
2832
|
const sectionId = `scheduling-${insertAfter}`;
|
|
2833
|
+
if (!inEditor && !loading && !schedule) {
|
|
2834
|
+
return /* @__PURE__ */ jsx4("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
|
|
2835
|
+
}
|
|
2153
2836
|
return /* @__PURE__ */ jsxs3(
|
|
2154
2837
|
"section",
|
|
2155
2838
|
{
|
|
@@ -7066,13 +7749,17 @@ function MediaOverlay({
|
|
|
7066
7749
|
hover,
|
|
7067
7750
|
isUploading,
|
|
7068
7751
|
fadingOut = false,
|
|
7752
|
+
selected = false,
|
|
7753
|
+
hovered = false,
|
|
7069
7754
|
onFadeOutComplete,
|
|
7070
7755
|
onReplace,
|
|
7756
|
+
onSelect,
|
|
7071
7757
|
onVideoSettingsChange
|
|
7072
7758
|
}) {
|
|
7073
7759
|
const { rect } = hover;
|
|
7074
7760
|
const skeletonRef = React8.useRef(null);
|
|
7075
7761
|
const isVideo = hover.elementType === "video";
|
|
7762
|
+
const showChrome = !selected || hovered;
|
|
7076
7763
|
const autoplay = hover.videoAutoplay ?? true;
|
|
7077
7764
|
const muted = hover.videoMuted ?? true;
|
|
7078
7765
|
const probeRef = React8.useRef(null);
|
|
@@ -7086,6 +7773,7 @@ function MediaOverlay({
|
|
|
7086
7773
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
7087
7774
|
);
|
|
7088
7775
|
}, [isVideo]);
|
|
7776
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
7089
7777
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
7090
7778
|
const box = {
|
|
7091
7779
|
position: "fixed",
|
|
@@ -7119,7 +7807,7 @@ function MediaOverlay({
|
|
|
7119
7807
|
}
|
|
7120
7808
|
);
|
|
7121
7809
|
}
|
|
7122
|
-
const settingsBar = isVideo && !hover.isDragOver ? /* @__PURE__ */ jsxs7(
|
|
7810
|
+
const settingsBar = isVideo && !hover.isDragOver && showChrome ? /* @__PURE__ */ jsxs7(
|
|
7123
7811
|
"div",
|
|
7124
7812
|
{
|
|
7125
7813
|
"data-ohw-bridge": "",
|
|
@@ -7189,10 +7877,12 @@ function MediaOverlay({
|
|
|
7189
7877
|
// in-document, pointer-events does it natively. The button below opts back in, so
|
|
7190
7878
|
// Replace still works.
|
|
7191
7879
|
pointerEvents: hover.hasTextOverlap ? "none" : "auto",
|
|
7192
|
-
|
|
7193
|
-
|
|
7880
|
+
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
7881
|
+
// than hovered. Hover keeps the existing tinted preview.
|
|
7882
|
+
boxShadow: selected ? "inset 0 0 0 2px var(--color-primary)" : "inset 0 0 0 1.5px var(--color-primary)",
|
|
7883
|
+
background: selected ? "transparent" : "color-mix(in srgb, var(--color-primary) 20%, transparent)"
|
|
7194
7884
|
},
|
|
7195
|
-
onClick: () => onReplace(hover.key),
|
|
7885
|
+
onClick: () => onSelect && !selected ? onSelect(hover.key) : onReplace(hover.key),
|
|
7196
7886
|
children: [
|
|
7197
7887
|
/* @__PURE__ */ jsxs7(
|
|
7198
7888
|
Button,
|
|
@@ -7213,17 +7903,17 @@ function MediaOverlay({
|
|
|
7213
7903
|
},
|
|
7214
7904
|
children: [
|
|
7215
7905
|
isVideo ? /* @__PURE__ */ jsx15(Film, { size: 14 }) : /* @__PURE__ */ jsx15(ImageIcon, { size: 14 }),
|
|
7216
|
-
|
|
7906
|
+
replaceLabel
|
|
7217
7907
|
]
|
|
7218
7908
|
}
|
|
7219
7909
|
),
|
|
7220
|
-
replaceMode
|
|
7910
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ jsxs7(
|
|
7221
7911
|
Button,
|
|
7222
7912
|
{
|
|
7223
7913
|
"data-ohw-media-overlay": "",
|
|
7224
7914
|
variant: "outline",
|
|
7225
7915
|
size: "sm",
|
|
7226
|
-
"aria-label":
|
|
7916
|
+
"aria-label": replaceLabel,
|
|
7227
7917
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
7228
7918
|
style: {
|
|
7229
7919
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -7246,7 +7936,7 @@ function MediaOverlay({
|
|
|
7246
7936
|
},
|
|
7247
7937
|
children: [
|
|
7248
7938
|
isVideo ? /* @__PURE__ */ jsx15(Film, { size: 14 }) : /* @__PURE__ */ jsx15(ImageIcon, { size: 14 }),
|
|
7249
|
-
replaceMode === "full" ?
|
|
7939
|
+
replaceMode === "full" ? replaceLabel : null
|
|
7250
7940
|
]
|
|
7251
7941
|
}
|
|
7252
7942
|
)
|
|
@@ -7317,6 +8007,9 @@ import { Check, X } from "lucide-react";
|
|
|
7317
8007
|
|
|
7318
8008
|
// src/lib/sections.ts
|
|
7319
8009
|
var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
8010
|
+
function isChromeSection(el) {
|
|
8011
|
+
return el.matches("header, nav, footer, aside");
|
|
8012
|
+
}
|
|
7320
8013
|
function titleCaseSectionId(id) {
|
|
7321
8014
|
return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
7322
8015
|
}
|
|
@@ -7327,6 +8020,8 @@ function parseSectionsFromRoot(root) {
|
|
|
7327
8020
|
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
7328
8021
|
if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
|
|
7329
8022
|
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
8023
|
+
if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
|
|
8024
|
+
continue;
|
|
7330
8025
|
seen.add(id);
|
|
7331
8026
|
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
7332
8027
|
sections.push({ id, label });
|
|
@@ -7342,15 +8037,163 @@ function parseSectionsFromHtml(html) {
|
|
|
7342
8037
|
return parseSectionsFromRoot(doc);
|
|
7343
8038
|
}
|
|
7344
8039
|
|
|
7345
|
-
// src/
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
return
|
|
7353
|
-
|
|
8040
|
+
// src/lib/section-instances.ts
|
|
8041
|
+
var SECTION_ORDER_KEY = "__ohw_section_order";
|
|
8042
|
+
var REMOVED_ATTR2 = "data-ohw-section-removed";
|
|
8043
|
+
function isRemovedSection(el) {
|
|
8044
|
+
return el.hasAttribute(REMOVED_ATTR2);
|
|
8045
|
+
}
|
|
8046
|
+
function topLevelSections() {
|
|
8047
|
+
return Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
8048
|
+
(el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el) && !isRemovedSection(el)
|
|
8049
|
+
);
|
|
8050
|
+
}
|
|
8051
|
+
function instanceIdOf(el) {
|
|
8052
|
+
return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
|
|
8053
|
+
}
|
|
8054
|
+
function planSectionMove(instanceId, targetIndex, currentPath) {
|
|
8055
|
+
const sections = topLevelSections();
|
|
8056
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8057
|
+
if (index === -1) return null;
|
|
8058
|
+
const dragged = sections[index];
|
|
8059
|
+
const others = sections.filter((_, i) => i !== index);
|
|
8060
|
+
const clamped = Math.max(0, Math.min(targetIndex, others.length));
|
|
8061
|
+
const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
|
|
8062
|
+
return reordered.map((el, order) => ({
|
|
8063
|
+
instanceId: instanceIdOf(el),
|
|
8064
|
+
type: el.getAttribute("data-ohw-section") ?? "",
|
|
8065
|
+
order,
|
|
8066
|
+
pagePath: currentPath
|
|
8067
|
+
}));
|
|
8068
|
+
}
|
|
8069
|
+
function moveSectionInstance(instanceId, direction, currentPath) {
|
|
8070
|
+
const sections = topLevelSections();
|
|
8071
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8072
|
+
if (index === -1) return null;
|
|
8073
|
+
const siblingIndex = direction === "up" ? index - 1 : index + 1;
|
|
8074
|
+
if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
|
|
8075
|
+
const entries = planSectionMove(instanceId, siblingIndex, currentPath);
|
|
8076
|
+
if (!entries) return null;
|
|
8077
|
+
applyPersistedOrder(entries);
|
|
8078
|
+
return entries;
|
|
8079
|
+
}
|
|
8080
|
+
function syncRemovedFlags(entries) {
|
|
8081
|
+
const removedIds = new Set(entries.filter((e) => e.removed).map((e) => e.instanceId));
|
|
8082
|
+
document.querySelectorAll(`[${REMOVED_ATTR2}]`).forEach((el) => {
|
|
8083
|
+
if (!removedIds.has(instanceIdOf(el))) {
|
|
8084
|
+
el.style.removeProperty("display");
|
|
8085
|
+
el.removeAttribute(REMOVED_ATTR2);
|
|
8086
|
+
}
|
|
8087
|
+
});
|
|
8088
|
+
for (const id of removedIds) {
|
|
8089
|
+
const el = document.querySelector(`[data-ohw-instance="${CSS.escape(id)}"]`);
|
|
8090
|
+
if (el) {
|
|
8091
|
+
el.style.display = "none";
|
|
8092
|
+
el.setAttribute(REMOVED_ATTR2, "");
|
|
8093
|
+
}
|
|
8094
|
+
}
|
|
8095
|
+
}
|
|
8096
|
+
function applyPersistedOrder(entries) {
|
|
8097
|
+
syncRemovedFlags(entries);
|
|
8098
|
+
if (entries.length === 0) return;
|
|
8099
|
+
const sections = topLevelSections();
|
|
8100
|
+
if (sections.length === 0) return;
|
|
8101
|
+
const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
|
|
8102
|
+
const ordered = [...sections].sort((a, b) => {
|
|
8103
|
+
const aOrder = orderIndex.get(instanceIdOf(a));
|
|
8104
|
+
const bOrder = orderIndex.get(instanceIdOf(b));
|
|
8105
|
+
if (aOrder === void 0 && bOrder === void 0) return 0;
|
|
8106
|
+
if (aOrder === void 0) return 1;
|
|
8107
|
+
if (bOrder === void 0) return -1;
|
|
8108
|
+
return aOrder - bOrder;
|
|
8109
|
+
});
|
|
8110
|
+
let prev = null;
|
|
8111
|
+
for (const el of ordered) {
|
|
8112
|
+
if (prev) prev.after(el);
|
|
8113
|
+
prev = el;
|
|
8114
|
+
}
|
|
8115
|
+
}
|
|
8116
|
+
function setSectionRemoved(instanceId, currentPath, existingEntries, removed) {
|
|
8117
|
+
if (!document.querySelector(`[data-ohw-instance="${CSS.escape(instanceId)}"]`)) return null;
|
|
8118
|
+
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
8119
|
+
const allSections = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
8120
|
+
(el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
|
|
8121
|
+
);
|
|
8122
|
+
allSections.forEach((el, order) => {
|
|
8123
|
+
const id = instanceIdOf(el);
|
|
8124
|
+
if (!byId.has(id)) {
|
|
8125
|
+
byId.set(id, { instanceId: id, type: el.getAttribute("data-ohw-section") ?? "", order, pagePath: currentPath });
|
|
8126
|
+
}
|
|
8127
|
+
});
|
|
8128
|
+
const target = byId.get(instanceId);
|
|
8129
|
+
if (!target) return null;
|
|
8130
|
+
byId.set(instanceId, { ...target, removed });
|
|
8131
|
+
const entries = Array.from(byId.values());
|
|
8132
|
+
applyPersistedOrder(entries);
|
|
8133
|
+
return entries;
|
|
8134
|
+
}
|
|
8135
|
+
function deleteSectionInstance(instanceId, currentPath, existingEntries) {
|
|
8136
|
+
return setSectionRemoved(instanceId, currentPath, existingEntries, true);
|
|
8137
|
+
}
|
|
8138
|
+
function restoreSectionInstance(instanceId, currentPath, existingEntries) {
|
|
8139
|
+
return setSectionRemoved(instanceId, currentPath, existingEntries, false);
|
|
8140
|
+
}
|
|
8141
|
+
function newInstanceId() {
|
|
8142
|
+
return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `instance-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
8143
|
+
}
|
|
8144
|
+
function getPageSectionOrderEntries(raw, currentPath) {
|
|
8145
|
+
if (!raw) return [];
|
|
8146
|
+
try {
|
|
8147
|
+
const entries = JSON.parse(raw);
|
|
8148
|
+
return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
|
|
8149
|
+
} catch {
|
|
8150
|
+
return [];
|
|
8151
|
+
}
|
|
8152
|
+
}
|
|
8153
|
+
function rekeySectionSubtree(root, instanceId) {
|
|
8154
|
+
const suffix = `::${instanceId}`;
|
|
8155
|
+
const rekey = (el, attr) => {
|
|
8156
|
+
const current = el.getAttribute(attr);
|
|
8157
|
+
if (current) el.setAttribute(attr, `${current}${suffix}`);
|
|
8158
|
+
};
|
|
8159
|
+
if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
|
|
8160
|
+
if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
|
|
8161
|
+
root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
|
|
8162
|
+
root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
|
|
8163
|
+
}
|
|
8164
|
+
function initSectionInstancesFromContent(content, currentPath) {
|
|
8165
|
+
document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
|
|
8166
|
+
el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
|
|
8167
|
+
});
|
|
8168
|
+
const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
|
|
8169
|
+
for (const entry of entries) {
|
|
8170
|
+
if (entry.instanceId === entry.type) continue;
|
|
8171
|
+
if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
|
|
8172
|
+
const original = document.querySelector(
|
|
8173
|
+
`[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
|
|
8174
|
+
);
|
|
8175
|
+
if (!original) continue;
|
|
8176
|
+
const clone = original.cloneNode(true);
|
|
8177
|
+
clone.setAttribute("data-ohw-instance", entry.instanceId);
|
|
8178
|
+
rekeySectionSubtree(clone, entry.instanceId);
|
|
8179
|
+
original.insertAdjacentElement("afterend", clone);
|
|
8180
|
+
}
|
|
8181
|
+
applyPersistedOrder(entries);
|
|
8182
|
+
}
|
|
8183
|
+
|
|
8184
|
+
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
8185
|
+
import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
8186
|
+
function findSectionElement(instanceId) {
|
|
8187
|
+
const escaped = CSS.escape(instanceId);
|
|
8188
|
+
return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
|
|
8189
|
+
}
|
|
8190
|
+
function readRect(instanceId) {
|
|
8191
|
+
const el = findSectionElement(instanceId);
|
|
8192
|
+
if (!el) return null;
|
|
8193
|
+
const r2 = el.getBoundingClientRect();
|
|
8194
|
+
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
8195
|
+
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
8196
|
+
}
|
|
7354
8197
|
function useLiveSectionRect(sectionId) {
|
|
7355
8198
|
const [rect, setRect] = useState5(null);
|
|
7356
8199
|
useEffect4(() => {
|
|
@@ -7368,7 +8211,7 @@ function useLiveSectionRect(sectionId) {
|
|
|
7368
8211
|
const opts = { capture: true, passive: true };
|
|
7369
8212
|
window.addEventListener("scroll", update, opts);
|
|
7370
8213
|
window.addEventListener("resize", update);
|
|
7371
|
-
const el =
|
|
8214
|
+
const el = findSectionElement(sectionId);
|
|
7372
8215
|
const ro = el ? new ResizeObserver(update) : null;
|
|
7373
8216
|
if (el && ro) ro.observe(el);
|
|
7374
8217
|
const interval = setInterval(update, 500);
|
|
@@ -7381,6 +8224,12 @@ function useLiveSectionRect(sectionId) {
|
|
|
7381
8224
|
}, [sectionId]);
|
|
7382
8225
|
return rect;
|
|
7383
8226
|
}
|
|
8227
|
+
function computeSectionBoundaryFlags(instanceId) {
|
|
8228
|
+
const topLevel = topLevelSections();
|
|
8229
|
+
const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
|
|
8230
|
+
if (index === -1) return { isFirst: true, isLast: true };
|
|
8231
|
+
return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
|
|
8232
|
+
}
|
|
7384
8233
|
var PRIMARY2 = "#0885FE";
|
|
7385
8234
|
function edgeAwareRadius(rect) {
|
|
7386
8235
|
const container = window.innerWidth <= 480 ? 16 : 24;
|
|
@@ -7454,6 +8303,7 @@ function AiSectionOverlay({
|
|
|
7454
8303
|
}) {
|
|
7455
8304
|
const [selectedId, setSelectedId] = useState5(null);
|
|
7456
8305
|
const [reviewId, setReviewId] = useState5(null);
|
|
8306
|
+
const [reviewButtonsHidden, setReviewButtonsHidden] = useState5(false);
|
|
7457
8307
|
const reviewIdRef = useRef4(null);
|
|
7458
8308
|
reviewIdRef.current = reviewId;
|
|
7459
8309
|
const selectedIdRef = useRef4(null);
|
|
@@ -7462,7 +8312,7 @@ function AiSectionOverlay({
|
|
|
7462
8312
|
(el) => {
|
|
7463
8313
|
postToParent2({
|
|
7464
8314
|
type: "ow:section-selected",
|
|
7465
|
-
sectionId: el
|
|
8315
|
+
sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
|
|
7466
8316
|
sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
|
|
7467
8317
|
});
|
|
7468
8318
|
},
|
|
@@ -7471,7 +8321,7 @@ function AiSectionOverlay({
|
|
|
7471
8321
|
const selectFromElement = useCallback2(
|
|
7472
8322
|
(el, options) => {
|
|
7473
8323
|
const sectionEl = el?.closest("[data-ohw-section]") ?? null;
|
|
7474
|
-
const id = sectionEl
|
|
8324
|
+
const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
|
|
7475
8325
|
if (id === selectedIdRef.current) return;
|
|
7476
8326
|
setSelectedId(id);
|
|
7477
8327
|
if (options?.report !== false) report(sectionEl);
|
|
@@ -7492,12 +8342,15 @@ function AiSectionOverlay({
|
|
|
7492
8342
|
selectFromElement(sectionEl);
|
|
7493
8343
|
return sectionEl != null;
|
|
7494
8344
|
},
|
|
7495
|
-
clear: () =>
|
|
8345
|
+
clear: () => {
|
|
8346
|
+
setSelectedId(null);
|
|
8347
|
+
report(null);
|
|
8348
|
+
}
|
|
7496
8349
|
};
|
|
7497
8350
|
return () => {
|
|
7498
8351
|
apiRef.current = null;
|
|
7499
8352
|
};
|
|
7500
|
-
}, [apiRef, selectFromElement]);
|
|
8353
|
+
}, [apiRef, selectFromElement, report]);
|
|
7501
8354
|
useEffect4(() => {
|
|
7502
8355
|
const onMessage = (e) => {
|
|
7503
8356
|
if (e.data?.type === "ow:ai-select" && e.data.sectionId === null) {
|
|
@@ -7512,9 +8365,10 @@ function AiSectionOverlay({
|
|
|
7512
8365
|
}
|
|
7513
8366
|
const found = readRect(sectionId) != null;
|
|
7514
8367
|
setReviewId(found ? sectionId : null);
|
|
8368
|
+
setReviewButtonsHidden(e.data.hideButtons === true);
|
|
7515
8369
|
postToParent2({ type: "ow:ai-review-started", sectionId, found });
|
|
7516
8370
|
if (found) {
|
|
7517
|
-
document.querySelector(`[data-ohw-
|
|
8371
|
+
document.querySelector(`[data-ohw-instance="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
7518
8372
|
}
|
|
7519
8373
|
}
|
|
7520
8374
|
};
|
|
@@ -7533,7 +8387,7 @@ function AiSectionOverlay({
|
|
|
7533
8387
|
return;
|
|
7534
8388
|
}
|
|
7535
8389
|
const sec = t.closest("[data-ohw-section]");
|
|
7536
|
-
setHoveredId(sec
|
|
8390
|
+
setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
|
|
7537
8391
|
};
|
|
7538
8392
|
const onLeave = () => setHoveredId(null);
|
|
7539
8393
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -7565,9 +8419,30 @@ function AiSectionOverlay({
|
|
|
7565
8419
|
},
|
|
7566
8420
|
[postToParent2]
|
|
7567
8421
|
);
|
|
7568
|
-
const
|
|
8422
|
+
const activeSelectionId = reviewId ? null : selectedId;
|
|
8423
|
+
const selectionRect = useLiveSectionRect(activeSelectionId);
|
|
7569
8424
|
const reviewRect = useLiveSectionRect(reviewId);
|
|
7570
8425
|
const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
|
|
8426
|
+
useEffect4(() => {
|
|
8427
|
+
const selectedEl = activeSelectionId ? findSectionElement(activeSelectionId) : null;
|
|
8428
|
+
if (!activeSelectionId || !selectionRect || selectedEl && isChromeSection(selectedEl)) {
|
|
8429
|
+
postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
|
|
8430
|
+
return;
|
|
8431
|
+
}
|
|
8432
|
+
const { isFirst, isLast } = computeSectionBoundaryFlags(activeSelectionId);
|
|
8433
|
+
postToParent2({
|
|
8434
|
+
type: "ow:section-rect",
|
|
8435
|
+
instanceId: activeSelectionId,
|
|
8436
|
+
rect: {
|
|
8437
|
+
top: selectionRect.top + window.scrollY,
|
|
8438
|
+
left: selectionRect.left + window.scrollX,
|
|
8439
|
+
width: selectionRect.width,
|
|
8440
|
+
height: selectionRect.height
|
|
8441
|
+
},
|
|
8442
|
+
isFirst,
|
|
8443
|
+
isLast
|
|
8444
|
+
});
|
|
8445
|
+
}, [activeSelectionId, selectionRect, postToParent2]);
|
|
7571
8446
|
return /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
7572
8447
|
hoverRect && /* @__PURE__ */ jsx17(
|
|
7573
8448
|
"div",
|
|
@@ -7618,13 +8493,16 @@ function AiSectionOverlay({
|
|
|
7618
8493
|
border: `2px solid ${PRIMARY2}`,
|
|
7619
8494
|
borderRadius: edgeAwareRadius(reviewRect),
|
|
7620
8495
|
zIndex: 2147483200,
|
|
7621
|
-
// The veil itself: swallows clicks so the section stays locked until decided.
|
|
8496
|
+
// The veil itself: swallows clicks so the section stays locked until decided. This
|
|
8497
|
+
// stopPropagation only guards the bubble phase; the bridge's capture-phase click
|
|
8498
|
+
// handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
|
|
8499
|
+
// Accept/Discard resolves to the media beneath and opens the file picker.
|
|
7622
8500
|
background: "rgba(8, 133, 254, 0.04)",
|
|
7623
8501
|
pointerEvents: "auto",
|
|
7624
8502
|
cursor: "default"
|
|
7625
8503
|
},
|
|
7626
8504
|
onClick: (e) => e.stopPropagation(),
|
|
7627
|
-
children: /* @__PURE__ */ jsxs9(
|
|
8505
|
+
children: !reviewButtonsHidden && /* @__PURE__ */ jsxs9(
|
|
7628
8506
|
"div",
|
|
7629
8507
|
{
|
|
7630
8508
|
style: {
|
|
@@ -7647,47 +8525,6 @@ function AiSectionOverlay({
|
|
|
7647
8525
|
] });
|
|
7648
8526
|
}
|
|
7649
8527
|
|
|
7650
|
-
// src/lib/section-instances.ts
|
|
7651
|
-
var SECTION_ORDER_KEY = "__ohw_section_order";
|
|
7652
|
-
function getPageSectionOrderEntries(raw, currentPath) {
|
|
7653
|
-
if (!raw) return [];
|
|
7654
|
-
try {
|
|
7655
|
-
const entries = JSON.parse(raw);
|
|
7656
|
-
return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
|
|
7657
|
-
} catch {
|
|
7658
|
-
return [];
|
|
7659
|
-
}
|
|
7660
|
-
}
|
|
7661
|
-
function rekeySectionSubtree(root, instanceId) {
|
|
7662
|
-
const suffix = `::${instanceId}`;
|
|
7663
|
-
const rekey = (el, attr) => {
|
|
7664
|
-
const current = el.getAttribute(attr);
|
|
7665
|
-
if (current) el.setAttribute(attr, `${current}${suffix}`);
|
|
7666
|
-
};
|
|
7667
|
-
if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
|
|
7668
|
-
if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
|
|
7669
|
-
root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
|
|
7670
|
-
root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
|
|
7671
|
-
}
|
|
7672
|
-
function initSectionInstancesFromContent(content, currentPath) {
|
|
7673
|
-
document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
|
|
7674
|
-
el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
|
|
7675
|
-
});
|
|
7676
|
-
const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
|
|
7677
|
-
for (const entry of entries) {
|
|
7678
|
-
if (entry.instanceId === entry.type) continue;
|
|
7679
|
-
if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
|
|
7680
|
-
const original = document.querySelector(
|
|
7681
|
-
`[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
|
|
7682
|
-
);
|
|
7683
|
-
if (!original) continue;
|
|
7684
|
-
const clone = original.cloneNode(true);
|
|
7685
|
-
clone.setAttribute("data-ohw-instance", entry.instanceId);
|
|
7686
|
-
rekeySectionSubtree(clone, entry.instanceId);
|
|
7687
|
-
original.insertAdjacentElement("afterend", clone);
|
|
7688
|
-
}
|
|
7689
|
-
}
|
|
7690
|
-
|
|
7691
8528
|
// src/OhhwellsBridge.tsx
|
|
7692
8529
|
import { createPortal as createPortal2 } from "react-dom";
|
|
7693
8530
|
import { usePathname as usePathname2, useRouter as useRouter3, useSearchParams } from "next/navigation";
|
|
@@ -10232,8 +11069,13 @@ function referenceBox(slot) {
|
|
|
10232
11069
|
const neighbour = row ? Array.from(row.querySelectorAll('[data-ohw-editable="icon"]')).find(
|
|
10233
11070
|
(el) => el !== slot && !el.hasAttribute("data-ohw-social-icon-placeholder")
|
|
10234
11071
|
) : null;
|
|
10235
|
-
|
|
10236
|
-
|
|
11072
|
+
if (neighbour) {
|
|
11073
|
+
const box2 = neighbour.querySelector(GLYPH_SELECTOR)?.getBoundingClientRect();
|
|
11074
|
+
if (box2?.width && box2.height) return box2;
|
|
11075
|
+
}
|
|
11076
|
+
const own = slot.getBoundingClientRect();
|
|
11077
|
+
if (own.width && own.height) return own;
|
|
11078
|
+
const box = slot.querySelector(GLYPH_SELECTOR)?.getBoundingClientRect() ?? null;
|
|
10237
11079
|
return box?.width && box.height ? box : null;
|
|
10238
11080
|
}
|
|
10239
11081
|
function iconMarkupSizedFor(slot, markup) {
|
|
@@ -12034,6 +12876,7 @@ function readLogoSizeState(content, placement) {
|
|
|
12034
12876
|
function getLogoElement(el) {
|
|
12035
12877
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
12036
12878
|
if (marked) return marked;
|
|
12879
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
12037
12880
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
12038
12881
|
if (!root) return null;
|
|
12039
12882
|
const anchor = el.closest("a");
|
|
@@ -12913,6 +13756,334 @@ function useNavItemDrag({
|
|
|
12913
13756
|
};
|
|
12914
13757
|
}
|
|
12915
13758
|
|
|
13759
|
+
// src/useSectionDrag.ts
|
|
13760
|
+
import { useCallback as useCallback7, useEffect as useEffect11, useRef as useRef9, useState as useState11 } from "react";
|
|
13761
|
+
|
|
13762
|
+
// src/lib/section-dnd.ts
|
|
13763
|
+
function isFooterSection(el) {
|
|
13764
|
+
return el.dataset.ohwSection === "footer";
|
|
13765
|
+
}
|
|
13766
|
+
function buildSectionDropSlots(draggedInstanceId) {
|
|
13767
|
+
const sections = topLevelSections().filter(
|
|
13768
|
+
(el) => instanceIdOf(el) !== draggedInstanceId && !isFooterSection(el)
|
|
13769
|
+
);
|
|
13770
|
+
const slots = [];
|
|
13771
|
+
if (sections.length === 0) return slots;
|
|
13772
|
+
const left = 0;
|
|
13773
|
+
const width = document.documentElement.clientWidth;
|
|
13774
|
+
for (let i = 0; i <= sections.length; i++) {
|
|
13775
|
+
let y;
|
|
13776
|
+
if (i === 0) {
|
|
13777
|
+
y = sections[0].getBoundingClientRect().top;
|
|
13778
|
+
} else if (i === sections.length) {
|
|
13779
|
+
y = sections[sections.length - 1].getBoundingClientRect().bottom;
|
|
13780
|
+
} else {
|
|
13781
|
+
const prev = sections[i - 1].getBoundingClientRect();
|
|
13782
|
+
const next = sections[i].getBoundingClientRect();
|
|
13783
|
+
y = (prev.bottom + next.top) / 2;
|
|
13784
|
+
}
|
|
13785
|
+
slots.push({ insertIndex: i, y, left, width });
|
|
13786
|
+
}
|
|
13787
|
+
return slots;
|
|
13788
|
+
}
|
|
13789
|
+
function hitTestSectionDropSlot(y, slots) {
|
|
13790
|
+
let best = null;
|
|
13791
|
+
for (const slot of slots) {
|
|
13792
|
+
const dist = Math.abs(y - slot.y);
|
|
13793
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
13794
|
+
}
|
|
13795
|
+
return best?.slot ?? null;
|
|
13796
|
+
}
|
|
13797
|
+
|
|
13798
|
+
// src/useSectionDrag.ts
|
|
13799
|
+
var PRESS_THRESHOLD = 10;
|
|
13800
|
+
var EDGE_ZONE = 60;
|
|
13801
|
+
var MAX_AUTO_SCROLL_SPEED = 18;
|
|
13802
|
+
var SECTION_DRAG_EXCLUDED_SELECTOR = [
|
|
13803
|
+
"[data-ohw-toolbar]",
|
|
13804
|
+
"[data-ohw-edit-chrome]",
|
|
13805
|
+
"[data-ohw-item-interaction]",
|
|
13806
|
+
"[data-ohw-drag-handle-container]",
|
|
13807
|
+
'[data-slot="drag-handle"]',
|
|
13808
|
+
"[data-ohw-item-toolbar-anchor]",
|
|
13809
|
+
"[data-ohw-item-drag-surface]",
|
|
13810
|
+
"[data-ohw-more-menu]",
|
|
13811
|
+
'[data-slot="dropdown-menu-content"]',
|
|
13812
|
+
'[data-slot="dropdown-menu-item"]',
|
|
13813
|
+
"[data-ohw-state-toggle]",
|
|
13814
|
+
"[data-ohw-max-badge]",
|
|
13815
|
+
"[data-ohw-floating-panel]",
|
|
13816
|
+
"[data-ohw-section-picker]",
|
|
13817
|
+
"[data-ohw-link-popover-root]",
|
|
13818
|
+
"[data-ohw-link-modal-root]",
|
|
13819
|
+
"[data-ohw-link-page-dropdown]",
|
|
13820
|
+
'[data-slot="popover-content"]',
|
|
13821
|
+
'[data-slot="dialog-content"]',
|
|
13822
|
+
'[data-slot="dialog-overlay"]',
|
|
13823
|
+
"[data-ohw-ai-review]",
|
|
13824
|
+
"[data-ohw-editable]",
|
|
13825
|
+
"[data-ohw-editable-state]",
|
|
13826
|
+
"[contenteditable]",
|
|
13827
|
+
"[data-ohw-href-key]",
|
|
13828
|
+
"[data-ohw-footer-col]",
|
|
13829
|
+
"[data-ohw-social-label]",
|
|
13830
|
+
"a",
|
|
13831
|
+
"button",
|
|
13832
|
+
'[role="button"]',
|
|
13833
|
+
'[data-ohw-role="navbar-button"]',
|
|
13834
|
+
'[data-ohw-role="button"]',
|
|
13835
|
+
"[data-ohw-carousel]",
|
|
13836
|
+
"[data-ohw-carousel-value]",
|
|
13837
|
+
"[data-ohw-carousel-slide]",
|
|
13838
|
+
"[data-ohw-carousel-overlay]",
|
|
13839
|
+
"[data-ohw-media-chrome]",
|
|
13840
|
+
"[data-ohw-media-overlay]",
|
|
13841
|
+
"[data-ohw-media-skeleton]"
|
|
13842
|
+
].join(", ");
|
|
13843
|
+
function visibleClip(ps) {
|
|
13844
|
+
if (!ps) return null;
|
|
13845
|
+
const top = Math.max(0, ps.headerH - ps.iframeOffsetTop);
|
|
13846
|
+
const bottom = Math.min(window.innerHeight, ps.headerH + ps.canvasH - ps.iframeOffsetTop);
|
|
13847
|
+
return { top, bottom: Math.max(top, bottom) };
|
|
13848
|
+
}
|
|
13849
|
+
function useSectionDrag({
|
|
13850
|
+
isEditMode,
|
|
13851
|
+
editContentRef,
|
|
13852
|
+
postToParentRef,
|
|
13853
|
+
parentScrollRef,
|
|
13854
|
+
navDragRef,
|
|
13855
|
+
footerDragRef,
|
|
13856
|
+
suppressNextClickRef,
|
|
13857
|
+
suppressClickUntilRef
|
|
13858
|
+
}) {
|
|
13859
|
+
const sectionDragRef = useRef9(null);
|
|
13860
|
+
const [sectionDropSlots, setSectionDropSlots] = useState11([]);
|
|
13861
|
+
const [activeSectionDropIndex, setActiveSectionDropIndex] = useState11(null);
|
|
13862
|
+
const [isSectionDragging, setIsSectionDragging] = useState11(false);
|
|
13863
|
+
const sectionPointerDragRef = useRef9(null);
|
|
13864
|
+
const autoScrollRafRef = useRef9(null);
|
|
13865
|
+
const autoScrollDeltaRef = useRef9(0);
|
|
13866
|
+
const stopAutoScroll = useCallback7(() => {
|
|
13867
|
+
if (autoScrollRafRef.current != null) {
|
|
13868
|
+
cancelAnimationFrame(autoScrollRafRef.current);
|
|
13869
|
+
autoScrollRafRef.current = null;
|
|
13870
|
+
}
|
|
13871
|
+
autoScrollDeltaRef.current = 0;
|
|
13872
|
+
}, []);
|
|
13873
|
+
const tickAutoScroll = useCallback7(() => {
|
|
13874
|
+
if (!sectionDragRef.current) {
|
|
13875
|
+
stopAutoScroll();
|
|
13876
|
+
return;
|
|
13877
|
+
}
|
|
13878
|
+
if (autoScrollDeltaRef.current !== 0) {
|
|
13879
|
+
postToParentRef.current({ type: "ow:request-scroll", deltaY: autoScrollDeltaRef.current });
|
|
13880
|
+
}
|
|
13881
|
+
autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
|
|
13882
|
+
}, [postToParentRef, stopAutoScroll]);
|
|
13883
|
+
const updateAutoScroll = useCallback7(
|
|
13884
|
+
(clientY) => {
|
|
13885
|
+
const clip = visibleClip(parentScrollRef.current);
|
|
13886
|
+
let delta = 0;
|
|
13887
|
+
if (clip) {
|
|
13888
|
+
const distTop = clientY - clip.top;
|
|
13889
|
+
const distBottom = clip.bottom - clientY;
|
|
13890
|
+
if (distTop >= 0 && distTop < EDGE_ZONE) {
|
|
13891
|
+
delta = -MAX_AUTO_SCROLL_SPEED * (1 - distTop / EDGE_ZONE);
|
|
13892
|
+
} else if (distBottom >= 0 && distBottom < EDGE_ZONE) {
|
|
13893
|
+
delta = MAX_AUTO_SCROLL_SPEED * (1 - distBottom / EDGE_ZONE);
|
|
13894
|
+
}
|
|
13895
|
+
}
|
|
13896
|
+
autoScrollDeltaRef.current = delta;
|
|
13897
|
+
if (delta !== 0 && autoScrollRafRef.current == null) {
|
|
13898
|
+
autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
|
|
13899
|
+
} else if (delta === 0) {
|
|
13900
|
+
stopAutoScroll();
|
|
13901
|
+
}
|
|
13902
|
+
},
|
|
13903
|
+
[parentScrollRef, stopAutoScroll, tickAutoScroll]
|
|
13904
|
+
);
|
|
13905
|
+
const clearSectionDragVisuals = useCallback7(() => {
|
|
13906
|
+
sectionDragRef.current?.draggedEl.removeAttribute("data-ohw-section-dragging");
|
|
13907
|
+
sectionDragRef.current = null;
|
|
13908
|
+
setSectionDropSlots([]);
|
|
13909
|
+
setActiveSectionDropIndex(null);
|
|
13910
|
+
setIsSectionDragging(false);
|
|
13911
|
+
stopAutoScroll();
|
|
13912
|
+
document.documentElement.removeAttribute("data-ohw-section-dragging-root");
|
|
13913
|
+
unlockItemDragInteraction();
|
|
13914
|
+
}, [stopAutoScroll]);
|
|
13915
|
+
const refreshSectionDragVisuals = useCallback7(
|
|
13916
|
+
(session, clientX, clientY) => {
|
|
13917
|
+
session.lastClientX = clientX;
|
|
13918
|
+
session.lastClientY = clientY;
|
|
13919
|
+
const slots = buildSectionDropSlots(session.instanceId);
|
|
13920
|
+
const activeSlot = hitTestSectionDropSlot(clientY, slots);
|
|
13921
|
+
session.activeSlot = activeSlot;
|
|
13922
|
+
setSectionDropSlots(slots);
|
|
13923
|
+
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
13924
|
+
setActiveSectionDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
13925
|
+
updateAutoScroll(clientY);
|
|
13926
|
+
},
|
|
13927
|
+
[updateAutoScroll]
|
|
13928
|
+
);
|
|
13929
|
+
const beginSectionDrag = useCallback7(
|
|
13930
|
+
(session) => {
|
|
13931
|
+
sectionDragRef.current = session;
|
|
13932
|
+
setIsSectionDragging(true);
|
|
13933
|
+
lockItemDuringDrag();
|
|
13934
|
+
document.documentElement.setAttribute("data-ohw-section-dragging-root", "");
|
|
13935
|
+
session.draggedEl.setAttribute("data-ohw-section-dragging", "");
|
|
13936
|
+
refreshSectionDragVisuals(session, session.lastClientX, session.lastClientY);
|
|
13937
|
+
},
|
|
13938
|
+
[refreshSectionDragVisuals]
|
|
13939
|
+
);
|
|
13940
|
+
const commitSectionDrag = useCallback7(() => {
|
|
13941
|
+
const session = sectionDragRef.current;
|
|
13942
|
+
if (!session) {
|
|
13943
|
+
clearSectionDragVisuals();
|
|
13944
|
+
return;
|
|
13945
|
+
}
|
|
13946
|
+
const slot = session.activeSlot ?? hitTestSectionDropSlot(session.lastClientY, buildSectionDropSlots(session.instanceId));
|
|
13947
|
+
const entries = slot ? planSectionMove(session.instanceId, slot.insertIndex, window.location.pathname) : null;
|
|
13948
|
+
if (!entries) {
|
|
13949
|
+
clearSectionDragVisuals();
|
|
13950
|
+
return;
|
|
13951
|
+
}
|
|
13952
|
+
const orderJson = JSON.stringify(entries);
|
|
13953
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
13954
|
+
setAiSectionOrder(orderJson, window.location.pathname);
|
|
13955
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
13956
|
+
applyPersistedOrder(entries);
|
|
13957
|
+
clearSectionDragVisuals();
|
|
13958
|
+
requestAnimationFrame(() => {
|
|
13959
|
+
if (editContentRef.current[SECTION_ORDER_KEY] === orderJson) {
|
|
13960
|
+
applyPersistedOrder(entries);
|
|
13961
|
+
}
|
|
13962
|
+
requestAnimationFrame(() => {
|
|
13963
|
+
window.dispatchEvent(new Event("resize"));
|
|
13964
|
+
});
|
|
13965
|
+
});
|
|
13966
|
+
}, [clearSectionDragVisuals, editContentRef, postToParentRef]);
|
|
13967
|
+
const startSectionPressDrag = useCallback7(
|
|
13968
|
+
(el, clientX, clientY, pointerId) => {
|
|
13969
|
+
if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return false;
|
|
13970
|
+
const instanceId = instanceIdOf(el);
|
|
13971
|
+
if (!instanceId) return false;
|
|
13972
|
+
sectionPointerDragRef.current = {
|
|
13973
|
+
el,
|
|
13974
|
+
instanceId,
|
|
13975
|
+
startX: clientX,
|
|
13976
|
+
startY: clientY,
|
|
13977
|
+
pointerId,
|
|
13978
|
+
started: false
|
|
13979
|
+
};
|
|
13980
|
+
return true;
|
|
13981
|
+
},
|
|
13982
|
+
[footerDragRef, navDragRef]
|
|
13983
|
+
);
|
|
13984
|
+
useEffect11(() => {
|
|
13985
|
+
if (!isEditMode) return;
|
|
13986
|
+
const onPointerDown = (e) => {
|
|
13987
|
+
if (e.button !== 0) return;
|
|
13988
|
+
if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return;
|
|
13989
|
+
if (sectionPointerDragRef.current) return;
|
|
13990
|
+
const target = e.target;
|
|
13991
|
+
if (!(target instanceof HTMLElement)) return;
|
|
13992
|
+
if (target.closest(SECTION_DRAG_EXCLUDED_SELECTOR)) return;
|
|
13993
|
+
const sectionEl = target.closest("[data-ohw-section]");
|
|
13994
|
+
if (!sectionEl || isChromeSection(sectionEl) || sectionEl.dataset.ohwSection === "footer") return;
|
|
13995
|
+
if (!topLevelSections().includes(sectionEl)) return;
|
|
13996
|
+
startSectionPressDrag(sectionEl, e.clientX, e.clientY, e.pointerId);
|
|
13997
|
+
};
|
|
13998
|
+
const onPointerMove = (e) => {
|
|
13999
|
+
const pending = sectionPointerDragRef.current;
|
|
14000
|
+
if (!pending) return;
|
|
14001
|
+
if (pending.started) {
|
|
14002
|
+
e.preventDefault();
|
|
14003
|
+
clearTextSelection();
|
|
14004
|
+
const session = sectionDragRef.current;
|
|
14005
|
+
if (!session) return;
|
|
14006
|
+
refreshSectionDragVisuals(session, e.clientX, e.clientY);
|
|
14007
|
+
return;
|
|
14008
|
+
}
|
|
14009
|
+
const dx = e.clientX - pending.startX;
|
|
14010
|
+
const dy = e.clientY - pending.startY;
|
|
14011
|
+
if (dx * dx + dy * dy < PRESS_THRESHOLD * PRESS_THRESHOLD) return;
|
|
14012
|
+
e.preventDefault();
|
|
14013
|
+
pending.started = true;
|
|
14014
|
+
armItemPressDrag();
|
|
14015
|
+
clearTextSelection();
|
|
14016
|
+
try {
|
|
14017
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
14018
|
+
} catch {
|
|
14019
|
+
}
|
|
14020
|
+
beginSectionDrag({
|
|
14021
|
+
instanceId: pending.instanceId,
|
|
14022
|
+
draggedEl: pending.el,
|
|
14023
|
+
lastClientX: e.clientX,
|
|
14024
|
+
lastClientY: e.clientY,
|
|
14025
|
+
activeSlot: null
|
|
14026
|
+
});
|
|
14027
|
+
};
|
|
14028
|
+
const endPointerDrag = (e) => {
|
|
14029
|
+
const pending = sectionPointerDragRef.current;
|
|
14030
|
+
sectionPointerDragRef.current = null;
|
|
14031
|
+
try {
|
|
14032
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
14033
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
14034
|
+
}
|
|
14035
|
+
} catch {
|
|
14036
|
+
}
|
|
14037
|
+
if (!pending) return;
|
|
14038
|
+
if (!pending.started) {
|
|
14039
|
+
unlockItemDragInteraction();
|
|
14040
|
+
return;
|
|
14041
|
+
}
|
|
14042
|
+
suppressNextClickRef.current = true;
|
|
14043
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
14044
|
+
commitSectionDrag();
|
|
14045
|
+
};
|
|
14046
|
+
const onKeyDown = (e) => {
|
|
14047
|
+
if (e.key !== "Escape") return;
|
|
14048
|
+
if (!sectionDragRef.current && !sectionPointerDragRef.current) return;
|
|
14049
|
+
sectionPointerDragRef.current = null;
|
|
14050
|
+
clearSectionDragVisuals();
|
|
14051
|
+
};
|
|
14052
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
14053
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
14054
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
14055
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
14056
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
14057
|
+
return () => {
|
|
14058
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
14059
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
14060
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
14061
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
14062
|
+
document.removeEventListener("keydown", onKeyDown, true);
|
|
14063
|
+
unlockItemDragInteraction();
|
|
14064
|
+
stopAutoScroll();
|
|
14065
|
+
};
|
|
14066
|
+
}, [
|
|
14067
|
+
beginSectionDrag,
|
|
14068
|
+
clearSectionDragVisuals,
|
|
14069
|
+
commitSectionDrag,
|
|
14070
|
+
footerDragRef,
|
|
14071
|
+
isEditMode,
|
|
14072
|
+
navDragRef,
|
|
14073
|
+
refreshSectionDragVisuals,
|
|
14074
|
+
startSectionPressDrag,
|
|
14075
|
+
stopAutoScroll,
|
|
14076
|
+
suppressClickUntilRef,
|
|
14077
|
+
suppressNextClickRef
|
|
14078
|
+
]);
|
|
14079
|
+
return {
|
|
14080
|
+
sectionDragRef,
|
|
14081
|
+
sectionDropSlots,
|
|
14082
|
+
activeSectionDropIndex,
|
|
14083
|
+
isSectionDragging
|
|
14084
|
+
};
|
|
14085
|
+
}
|
|
14086
|
+
|
|
12916
14087
|
// src/ui/footer-container-chrome.tsx
|
|
12917
14088
|
import { Plus as Plus2 } from "lucide-react";
|
|
12918
14089
|
import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
@@ -12965,7 +14136,7 @@ function FooterContainerChrome({
|
|
|
12965
14136
|
}
|
|
12966
14137
|
|
|
12967
14138
|
// src/lib/carousel.ts
|
|
12968
|
-
import { useEffect as
|
|
14139
|
+
import { useEffect as useEffect12, useState as useState12 } from "react";
|
|
12969
14140
|
var CAROUSEL_ATTR = "data-ohw-carousel";
|
|
12970
14141
|
var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
|
|
12971
14142
|
var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
|
|
@@ -13027,8 +14198,8 @@ function applyCarouselNode(key, val) {
|
|
|
13027
14198
|
return true;
|
|
13028
14199
|
}
|
|
13029
14200
|
function useOhwCarousel(key, initial) {
|
|
13030
|
-
const [images, setImages] =
|
|
13031
|
-
|
|
14201
|
+
const [images, setImages] = useState12(initial);
|
|
14202
|
+
useEffect12(() => {
|
|
13032
14203
|
const el = document.querySelector(
|
|
13033
14204
|
`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
|
|
13034
14205
|
);
|
|
@@ -13110,6 +14281,7 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
13110
14281
|
NAV_ORDER_KEY,
|
|
13111
14282
|
FOOTER_ORDER_KEY,
|
|
13112
14283
|
NAV_COUNT_KEY,
|
|
14284
|
+
SECTION_ORDER_KEY,
|
|
13113
14285
|
// A socials row's order and its icons-vs-words setting live under keys no element carries,
|
|
13114
14286
|
// so collecting the DOM alone left them behind: the draft knew the row was showing icons and
|
|
13115
14287
|
// had gained an item, and the published page went back to the template's own (OHH-736).
|
|
@@ -13573,6 +14745,7 @@ function fadeInImageElement(img, onReady) {
|
|
|
13573
14745
|
function applyEditableImageSrc(img, url) {
|
|
13574
14746
|
img.removeAttribute("srcset");
|
|
13575
14747
|
img.removeAttribute("sizes");
|
|
14748
|
+
if (img.loading === "lazy") img.loading = "eager";
|
|
13576
14749
|
img.src = url;
|
|
13577
14750
|
}
|
|
13578
14751
|
function fadeInBgImage(el, url, onReady) {
|
|
@@ -13637,21 +14810,10 @@ function parseSchedulingInsertAfter(insertAfter) {
|
|
|
13637
14810
|
insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
|
|
13638
14811
|
};
|
|
13639
14812
|
}
|
|
13640
|
-
function
|
|
13641
|
-
|
|
13642
|
-
const
|
|
13643
|
-
|
|
13644
|
-
return { effectiveInsertAfter, insertBefore };
|
|
13645
|
-
}
|
|
13646
|
-
function getSchedulingMountPoint(insertAfter) {
|
|
13647
|
-
const { anchor } = parseSchedulingInsertAfter(insertAfter);
|
|
13648
|
-
let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
|
|
13649
|
-
if (!anchorEl && anchor === "scheduling") {
|
|
13650
|
-
const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
|
|
13651
|
-
anchorEl = widgets.at(-1) ?? null;
|
|
13652
|
-
}
|
|
13653
|
-
if (!anchorEl) return null;
|
|
13654
|
-
return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
14813
|
+
function resolveEntryAnchor(entry) {
|
|
14814
|
+
if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
|
|
14815
|
+
const parsed = parseSchedulingInsertAfter(entry.insertAfter);
|
|
14816
|
+
return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
|
|
13655
14817
|
}
|
|
13656
14818
|
function schedulingMountDepth(insertAfter) {
|
|
13657
14819
|
if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
|
|
@@ -13668,8 +14830,7 @@ function getPageSchedulingEntries(raw) {
|
|
|
13668
14830
|
}
|
|
13669
14831
|
}
|
|
13670
14832
|
function isSchedulingWidgetMissing(entry) {
|
|
13671
|
-
|
|
13672
|
-
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
|
|
14833
|
+
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
|
|
13673
14834
|
}
|
|
13674
14835
|
function hasMissingSchedulingWidgets(entries) {
|
|
13675
14836
|
return entries.some(isSchedulingWidgetMissing);
|
|
@@ -13699,16 +14860,17 @@ function initSectionsFromContent(content, removeExisting = false) {
|
|
|
13699
14860
|
} catch {
|
|
13700
14861
|
}
|
|
13701
14862
|
}
|
|
13702
|
-
function mountSchedulingWidget(
|
|
13703
|
-
const
|
|
13704
|
-
const sectionId = schedulingSectionId(
|
|
14863
|
+
function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
|
|
14864
|
+
const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
|
|
14865
|
+
const sectionId = schedulingSectionId(widgetId);
|
|
13705
14866
|
if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
|
|
13706
|
-
const
|
|
13707
|
-
if (!
|
|
14867
|
+
const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
|
|
14868
|
+
if (!anchorEl) return false;
|
|
14869
|
+
const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
13708
14870
|
const container = document.createElement("div");
|
|
13709
14871
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
13710
|
-
if (
|
|
13711
|
-
const beforeAnchor = document.querySelector(`[data-ohw-section="${
|
|
14872
|
+
if (beforeId) {
|
|
14873
|
+
const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
|
|
13712
14874
|
const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
|
|
13713
14875
|
if (!beforePoint) return false;
|
|
13714
14876
|
beforePoint.insertAdjacentElement("beforebegin", container);
|
|
@@ -13719,19 +14881,25 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
13719
14881
|
}
|
|
13720
14882
|
tail.insertAdjacentElement("afterend", container);
|
|
13721
14883
|
}
|
|
13722
|
-
|
|
13723
|
-
|
|
13724
|
-
|
|
13725
|
-
|
|
13726
|
-
|
|
13727
|
-
|
|
13728
|
-
|
|
13729
|
-
|
|
13730
|
-
|
|
13731
|
-
|
|
13732
|
-
|
|
13733
|
-
|
|
13734
|
-
|
|
14884
|
+
try {
|
|
14885
|
+
const root = createRoot2(container);
|
|
14886
|
+
flushSync2(() => {
|
|
14887
|
+
root.render(
|
|
14888
|
+
/* @__PURE__ */ jsx33(
|
|
14889
|
+
SchedulingWidget,
|
|
14890
|
+
{
|
|
14891
|
+
notifyOnConnect,
|
|
14892
|
+
initialScheduleId: scheduleId,
|
|
14893
|
+
insertAfter: widgetId
|
|
14894
|
+
}
|
|
14895
|
+
)
|
|
14896
|
+
);
|
|
14897
|
+
});
|
|
14898
|
+
} catch (err) {
|
|
14899
|
+
console.error("[ow:scheduling] render threw", err);
|
|
14900
|
+
container.remove();
|
|
14901
|
+
return false;
|
|
14902
|
+
}
|
|
13735
14903
|
const tracker = getSectionsTracker();
|
|
13736
14904
|
let sections = [];
|
|
13737
14905
|
try {
|
|
@@ -13739,10 +14907,12 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
13739
14907
|
} catch {
|
|
13740
14908
|
}
|
|
13741
14909
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
13742
|
-
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter ===
|
|
14910
|
+
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
|
|
13743
14911
|
sections.push({
|
|
13744
14912
|
type: "scheduling",
|
|
13745
|
-
insertAfter:
|
|
14913
|
+
insertAfter: widgetId,
|
|
14914
|
+
anchorId,
|
|
14915
|
+
beforeId: beforeId ?? null,
|
|
13746
14916
|
pagePath: window.location.pathname,
|
|
13747
14917
|
...scheduleId ? { scheduleId } : {}
|
|
13748
14918
|
});
|
|
@@ -13756,7 +14926,8 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
13756
14926
|
for (let i = pending.length - 1; i >= 0; i--) {
|
|
13757
14927
|
const entry = pending[i];
|
|
13758
14928
|
const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
|
|
13759
|
-
|
|
14929
|
+
const { anchorId, beforeId } = resolveEntryAnchor(entry);
|
|
14930
|
+
if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
|
|
13760
14931
|
pending.splice(i, 1);
|
|
13761
14932
|
}
|
|
13762
14933
|
}
|
|
@@ -13914,6 +15085,11 @@ function applyLinkByKey(key, val) {
|
|
|
13914
15085
|
hrefAnchors.forEach((el) => applyLinkHref(el, val));
|
|
13915
15086
|
}
|
|
13916
15087
|
}
|
|
15088
|
+
function isInsideLinkEditor(target) {
|
|
15089
|
+
return Boolean(
|
|
15090
|
+
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"]')
|
|
15091
|
+
);
|
|
15092
|
+
}
|
|
13917
15093
|
function isInsideFloatingPanel(target) {
|
|
13918
15094
|
return Boolean(target.closest("[data-ohw-floating-panel]"));
|
|
13919
15095
|
}
|
|
@@ -13921,11 +15097,6 @@ function isPointOverFloatingPanel(clientX, clientY) {
|
|
|
13921
15097
|
const el = document.elementFromPoint(clientX, clientY);
|
|
13922
15098
|
return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
|
|
13923
15099
|
}
|
|
13924
|
-
function isInsideLinkEditor(target) {
|
|
13925
|
-
return Boolean(
|
|
13926
|
-
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"]')
|
|
13927
|
-
);
|
|
13928
|
-
}
|
|
13929
15100
|
function getHrefKeyFromElement(el) {
|
|
13930
15101
|
if (!el) return null;
|
|
13931
15102
|
const anchor = el.closest("[data-ohw-href-key]");
|
|
@@ -14184,7 +15355,7 @@ function getNavigationSelectionParent(el) {
|
|
|
14184
15355
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
14185
15356
|
return getFooterLinksContainer();
|
|
14186
15357
|
}
|
|
14187
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
15358
|
+
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)) {
|
|
14188
15359
|
return getNavigationRoot(el);
|
|
14189
15360
|
}
|
|
14190
15361
|
return null;
|
|
@@ -14399,7 +15570,6 @@ var ICONS = {
|
|
|
14399
15570
|
insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
|
|
14400
15571
|
insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
|
|
14401
15572
|
};
|
|
14402
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
14403
15573
|
var SELECTION_CHROME_GAP2 = 4;
|
|
14404
15574
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
14405
15575
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -14779,6 +15949,45 @@ function StateToggle({
|
|
|
14779
15949
|
);
|
|
14780
15950
|
}
|
|
14781
15951
|
var contentCache = /* @__PURE__ */ new Map();
|
|
15952
|
+
var fetchedContentPaths = /* @__PURE__ */ new Set();
|
|
15953
|
+
var OHW_LOADER_STYLE = {
|
|
15954
|
+
position: "fixed",
|
|
15955
|
+
inset: 0,
|
|
15956
|
+
background: "#fff",
|
|
15957
|
+
zIndex: 2147483646,
|
|
15958
|
+
display: "flex",
|
|
15959
|
+
alignItems: "center",
|
|
15960
|
+
justifyContent: "center"
|
|
15961
|
+
};
|
|
15962
|
+
function OhwLoaderSpinner() {
|
|
15963
|
+
return /* @__PURE__ */ jsxs20("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", "aria-hidden": true, children: [
|
|
15964
|
+
/* @__PURE__ */ jsx33("circle", { cx: "14", cy: "14", r: "11", stroke: "#E7E5E4", strokeWidth: "3" }),
|
|
15965
|
+
/* @__PURE__ */ jsx33(
|
|
15966
|
+
"circle",
|
|
15967
|
+
{
|
|
15968
|
+
cx: "14",
|
|
15969
|
+
cy: "14",
|
|
15970
|
+
r: "11",
|
|
15971
|
+
stroke: "#1C1917",
|
|
15972
|
+
strokeWidth: "3",
|
|
15973
|
+
strokeDasharray: "17 52",
|
|
15974
|
+
strokeLinecap: "round",
|
|
15975
|
+
children: /* @__PURE__ */ jsx33(
|
|
15976
|
+
"animateTransform",
|
|
15977
|
+
{
|
|
15978
|
+
attributeName: "transform",
|
|
15979
|
+
type: "rotate",
|
|
15980
|
+
from: "0 14 14",
|
|
15981
|
+
to: "360 14 14",
|
|
15982
|
+
dur: "0.7s",
|
|
15983
|
+
repeatCount: "indefinite"
|
|
15984
|
+
}
|
|
15985
|
+
)
|
|
15986
|
+
}
|
|
15987
|
+
)
|
|
15988
|
+
] });
|
|
15989
|
+
}
|
|
15990
|
+
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){}})();`;
|
|
14782
15991
|
function resolveSubdomain(subdomainFromQuery) {
|
|
14783
15992
|
if (subdomainFromQuery) return subdomainFromQuery;
|
|
14784
15993
|
if (typeof window !== "undefined") {
|
|
@@ -14801,8 +16010,8 @@ function OhhwellsBridge() {
|
|
|
14801
16010
|
const router = useRouter3();
|
|
14802
16011
|
const searchParams = useSearchParams();
|
|
14803
16012
|
const isEditMode = isEditSessionActive();
|
|
14804
|
-
const [bridgeRoot, setBridgeRoot] =
|
|
14805
|
-
|
|
16013
|
+
const [bridgeRoot, setBridgeRoot] = useState13(null);
|
|
16014
|
+
useEffect13(() => {
|
|
14806
16015
|
const figtreeFontId = "ohw-figtree-font";
|
|
14807
16016
|
if (!document.getElementById(figtreeFontId)) {
|
|
14808
16017
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -14831,82 +16040,146 @@ function OhhwellsBridge() {
|
|
|
14831
16040
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
14832
16041
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
14833
16042
|
useSavedLinkNavigation(isEditMode);
|
|
14834
|
-
const postToParent2 =
|
|
16043
|
+
const postToParent2 = useCallback8((data) => {
|
|
14835
16044
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
14836
16045
|
window.parent.postMessage(data, "*");
|
|
14837
16046
|
}
|
|
14838
16047
|
}, []);
|
|
14839
|
-
const [fetchState, setFetchState] =
|
|
14840
|
-
const autoSaveTimers =
|
|
14841
|
-
const activeElRef =
|
|
14842
|
-
const pointerHeldRef =
|
|
14843
|
-
const selectedElRef =
|
|
14844
|
-
const selectedHrefKeyRef =
|
|
14845
|
-
const selectedFooterColAttrRef =
|
|
14846
|
-
const originalContentRef =
|
|
14847
|
-
const activeStateElRef =
|
|
14848
|
-
const parentScrollRef =
|
|
14849
|
-
const visibleViewportRef =
|
|
14850
|
-
const [dialogPortalContainer, setDialogPortalContainer] =
|
|
14851
|
-
const attachVisibleViewport =
|
|
16048
|
+
const [fetchState, setFetchState] = useState13("idle");
|
|
16049
|
+
const autoSaveTimers = useRef10(/* @__PURE__ */ new Map());
|
|
16050
|
+
const activeElRef = useRef10(null);
|
|
16051
|
+
const pointerHeldRef = useRef10(false);
|
|
16052
|
+
const selectedElRef = useRef10(null);
|
|
16053
|
+
const selectedHrefKeyRef = useRef10(null);
|
|
16054
|
+
const selectedFooterColAttrRef = useRef10(null);
|
|
16055
|
+
const originalContentRef = useRef10(null);
|
|
16056
|
+
const activeStateElRef = useRef10(null);
|
|
16057
|
+
const parentScrollRef = useRef10(null);
|
|
16058
|
+
const visibleViewportRef = useRef10(null);
|
|
16059
|
+
const [dialogPortalContainer, setDialogPortalContainer] = useState13(null);
|
|
16060
|
+
const attachVisibleViewport = useCallback8((node) => {
|
|
14852
16061
|
visibleViewportRef.current = node;
|
|
14853
16062
|
setDialogPortalContainer(node);
|
|
14854
16063
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
14855
16064
|
}, []);
|
|
14856
|
-
const toolbarElRef =
|
|
14857
|
-
const glowElRef =
|
|
14858
|
-
const hoveredImageRef =
|
|
14859
|
-
const hoveredImageHasTextOverlapRef =
|
|
14860
|
-
const dragOverElRef =
|
|
14861
|
-
const [mediaHover, setMediaHover] =
|
|
14862
|
-
const [
|
|
14863
|
-
const
|
|
14864
|
-
const
|
|
14865
|
-
|
|
14866
|
-
|
|
14867
|
-
|
|
14868
|
-
|
|
16065
|
+
const toolbarElRef = useRef10(null);
|
|
16066
|
+
const glowElRef = useRef10(null);
|
|
16067
|
+
const hoveredImageRef = useRef10(null);
|
|
16068
|
+
const hoveredImageHasTextOverlapRef = useRef10(false);
|
|
16069
|
+
const dragOverElRef = useRef10(null);
|
|
16070
|
+
const [mediaHover, setMediaHover] = useState13(null);
|
|
16071
|
+
const [selectedMedia, setSelectedMedia] = useState13(null);
|
|
16072
|
+
const selectedMediaElRef = useRef10(null);
|
|
16073
|
+
const clearMediaSelection = useCallback8(() => {
|
|
16074
|
+
const prev = selectedMediaElRef.current;
|
|
16075
|
+
selectedMediaElRef.current = null;
|
|
16076
|
+
setSelectedMedia(null);
|
|
16077
|
+
const sectionEl = prev?.closest("[data-ohw-section]") ?? null;
|
|
16078
|
+
if (sectionEl) {
|
|
16079
|
+
postToParentRef.current({
|
|
16080
|
+
type: "ow:section-selected",
|
|
16081
|
+
sectionId: sectionEl.dataset.ohwSection ?? null,
|
|
16082
|
+
sectionLabel: sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? ""),
|
|
16083
|
+
key: null
|
|
16084
|
+
});
|
|
16085
|
+
}
|
|
16086
|
+
}, []);
|
|
16087
|
+
const clearMediaSelectionRef = useRef10(clearMediaSelection);
|
|
16088
|
+
clearMediaSelectionRef.current = clearMediaSelection;
|
|
16089
|
+
const selectMediaElement = useCallback8((el) => {
|
|
16090
|
+
const r2 = el.getBoundingClientRect();
|
|
16091
|
+
const video = el.dataset.ohwEditable === "video" ? el.querySelector("video") : null;
|
|
16092
|
+
selectedMediaElRef.current = el;
|
|
16093
|
+
setSelectedMedia({
|
|
16094
|
+
key: el.dataset.ohwKey ?? "",
|
|
16095
|
+
rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
|
|
16096
|
+
elementType: el.dataset.ohwEditable ?? "image",
|
|
16097
|
+
hasTextOverlap: false,
|
|
16098
|
+
isDragOver: false,
|
|
16099
|
+
...video ? { videoAutoplay: video.autoplay, videoMuted: video.muted } : {}
|
|
16100
|
+
});
|
|
16101
|
+
const sectionEl = el.closest("[data-ohw-section]");
|
|
16102
|
+
aiSectionApiRef.current?.selectFromElement(el, { report: false });
|
|
16103
|
+
postToParentRef.current({
|
|
16104
|
+
type: "ow:section-selected",
|
|
16105
|
+
sectionId: sectionEl?.dataset.ohwSection ?? null,
|
|
16106
|
+
sectionLabel: sectionEl ? sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? "") : null,
|
|
16107
|
+
key: el.dataset.ohwKey ?? null,
|
|
16108
|
+
// Display name for the pill — the raw key prettifies into fragments ("Img"); the
|
|
16109
|
+
// bridge knows what the node IS, so it names it.
|
|
16110
|
+
keyLabel: el.dataset.ohwEditable === "video" ? "Video" : el.dataset.ohwEditable === "bg-image" ? "Background" : "Image"
|
|
16111
|
+
});
|
|
16112
|
+
}, []);
|
|
16113
|
+
const selectMediaElementRef = useRef10(selectMediaElement);
|
|
16114
|
+
selectMediaElementRef.current = selectMediaElement;
|
|
16115
|
+
useEffect13(() => {
|
|
16116
|
+
if (!selectedMedia) return;
|
|
16117
|
+
const update = () => {
|
|
16118
|
+
const el = selectedMediaElRef.current;
|
|
16119
|
+
if (!el || !el.isConnected) {
|
|
16120
|
+
clearMediaSelection();
|
|
16121
|
+
return;
|
|
16122
|
+
}
|
|
16123
|
+
const r2 = el.getBoundingClientRect();
|
|
16124
|
+
setSelectedMedia(
|
|
16125
|
+
(prev) => prev ? { ...prev, rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } } : prev
|
|
16126
|
+
);
|
|
16127
|
+
};
|
|
16128
|
+
window.addEventListener("scroll", update, true);
|
|
16129
|
+
window.addEventListener("resize", update);
|
|
16130
|
+
return () => {
|
|
16131
|
+
window.removeEventListener("scroll", update, true);
|
|
16132
|
+
window.removeEventListener("resize", update);
|
|
16133
|
+
};
|
|
16134
|
+
}, [selectedMedia !== null]);
|
|
16135
|
+
const [carouselHover, setCarouselHover] = useState13(null);
|
|
16136
|
+
const [uploadingRects, setUploadingRects] = useState13({});
|
|
16137
|
+
const hoveredGapRef = useRef10(null);
|
|
16138
|
+
const imageUnhoverTimerRef = useRef10(null);
|
|
16139
|
+
const imageShowTimerRef = useRef10(null);
|
|
16140
|
+
const editStylesRef = useRef10(null);
|
|
16141
|
+
const activateRef = useRef10(() => {
|
|
14869
16142
|
});
|
|
14870
|
-
const deactivateRef =
|
|
16143
|
+
const deactivateRef = useRef10(() => {
|
|
14871
16144
|
});
|
|
14872
|
-
const selectRef =
|
|
16145
|
+
const selectRef = useRef10(() => {
|
|
14873
16146
|
});
|
|
14874
|
-
const selectFrameRef =
|
|
16147
|
+
const selectFrameRef = useRef10(() => {
|
|
14875
16148
|
});
|
|
14876
|
-
const selectLogoRef =
|
|
16149
|
+
const selectLogoRef = useRef10(() => {
|
|
14877
16150
|
});
|
|
14878
|
-
const openLogoSizePanelRef =
|
|
16151
|
+
const openLogoSizePanelRef = useRef10(() => {
|
|
14879
16152
|
});
|
|
14880
|
-
const deselectRef =
|
|
16153
|
+
const deselectRef = useRef10(() => {
|
|
14881
16154
|
});
|
|
14882
|
-
const closeFloatingPanelOnlyRef =
|
|
16155
|
+
const closeFloatingPanelOnlyRef = useRef10(() => {
|
|
14883
16156
|
});
|
|
14884
|
-
const reselectNavigationItemRef =
|
|
16157
|
+
const reselectNavigationItemRef = useRef10(() => {
|
|
14885
16158
|
});
|
|
14886
|
-
const commitNavigationTextEditRef =
|
|
16159
|
+
const commitNavigationTextEditRef = useRef10(() => {
|
|
14887
16160
|
});
|
|
14888
|
-
const handleDeleteSelectedRef =
|
|
14889
|
-
const runPendingDeleteUndoRef =
|
|
14890
|
-
const isFooterFrameSelectionRef =
|
|
14891
|
-
const refreshActiveCommandsRef =
|
|
16161
|
+
const handleDeleteSelectedRef = useRef10(() => false);
|
|
16162
|
+
const runPendingDeleteUndoRef = useRef10(() => false);
|
|
16163
|
+
const isFooterFrameSelectionRef = useRef10(false);
|
|
16164
|
+
const refreshActiveCommandsRef = useRef10(() => {
|
|
14892
16165
|
});
|
|
14893
|
-
const postToParentRef =
|
|
16166
|
+
const postToParentRef = useRef10(postToParent2);
|
|
14894
16167
|
postToParentRef.current = postToParent2;
|
|
14895
|
-
const aiSectionApiRef =
|
|
14896
|
-
const sectionsLoadedRef =
|
|
14897
|
-
const pendingScheduleConfigRequests =
|
|
14898
|
-
const [toolbarRect, setToolbarRect] =
|
|
14899
|
-
const [formPickRect, setFormPickRect] =
|
|
14900
|
-
const formPickElRef =
|
|
14901
|
-
const [formViewState, setFormViewStateUi] =
|
|
14902
|
-
const [formPickCount, setFormPickCount] =
|
|
14903
|
-
const [formHoverRect, setFormHoverRect] =
|
|
14904
|
-
const formHoverElRef =
|
|
14905
|
-
const [fieldPickRect, setFieldPickRect] =
|
|
14906
|
-
const fieldPickElRef =
|
|
14907
|
-
const [fieldPickState, setFieldPickState] =
|
|
14908
|
-
const [fieldTypePickerOpen, setFieldTypePickerOpen] =
|
|
14909
|
-
const clearFormPick =
|
|
16168
|
+
const aiSectionApiRef = useRef10(null);
|
|
16169
|
+
const sectionsLoadedRef = useRef10(false);
|
|
16170
|
+
const pendingScheduleConfigRequests = useRef10([]);
|
|
16171
|
+
const [toolbarRect, setToolbarRect] = useState13(null);
|
|
16172
|
+
const [formPickRect, setFormPickRect] = useState13(null);
|
|
16173
|
+
const formPickElRef = useRef10(null);
|
|
16174
|
+
const [formViewState, setFormViewStateUi] = useState13("default");
|
|
16175
|
+
const [formPickCount, setFormPickCount] = useState13(null);
|
|
16176
|
+
const [formHoverRect, setFormHoverRect] = useState13(null);
|
|
16177
|
+
const formHoverElRef = useRef10(null);
|
|
16178
|
+
const [fieldPickRect, setFieldPickRect] = useState13(null);
|
|
16179
|
+
const fieldPickElRef = useRef10(null);
|
|
16180
|
+
const [fieldPickState, setFieldPickState] = useState13(null);
|
|
16181
|
+
const [fieldTypePickerOpen, setFieldTypePickerOpen] = useState13(false);
|
|
16182
|
+
const clearFormPick = useCallback8(() => {
|
|
14910
16183
|
const form = formPickElRef.current;
|
|
14911
16184
|
const editing = fieldPickElRef.current;
|
|
14912
16185
|
if (commitPlaceholderEdit(editing) && editing) {
|
|
@@ -14926,7 +16199,7 @@ function OhhwellsBridge() {
|
|
|
14926
16199
|
formPickElRef.current = null;
|
|
14927
16200
|
setFormPickRect(null);
|
|
14928
16201
|
}, []);
|
|
14929
|
-
const clearFieldPick =
|
|
16202
|
+
const clearFieldPick = useCallback8(() => {
|
|
14930
16203
|
const wrapper = fieldPickElRef.current;
|
|
14931
16204
|
if (commitPlaceholderEdit(wrapper) && wrapper) {
|
|
14932
16205
|
const form = wrapper.closest('[data-ohw-editable="form"]');
|
|
@@ -14936,9 +16209,9 @@ function OhhwellsBridge() {
|
|
|
14936
16209
|
setFieldPickRect(null);
|
|
14937
16210
|
setFieldPickState(null);
|
|
14938
16211
|
}, []);
|
|
14939
|
-
const persistFieldsRef =
|
|
16212
|
+
const persistFieldsRef = useRef10(() => {
|
|
14940
16213
|
});
|
|
14941
|
-
const persistFields =
|
|
16214
|
+
const persistFields = useCallback8(
|
|
14942
16215
|
(form) => {
|
|
14943
16216
|
const key = formKeyOf(form);
|
|
14944
16217
|
if (!key) return;
|
|
@@ -14949,7 +16222,7 @@ function OhhwellsBridge() {
|
|
|
14949
16222
|
[]
|
|
14950
16223
|
);
|
|
14951
16224
|
persistFieldsRef.current = persistFields;
|
|
14952
|
-
const selectField =
|
|
16225
|
+
const selectField = useCallback8((wrapper) => {
|
|
14953
16226
|
if (fieldPickElRef.current && fieldPickElRef.current !== wrapper) {
|
|
14954
16227
|
commitPlaceholderEdit(fieldPickElRef.current);
|
|
14955
16228
|
}
|
|
@@ -14962,7 +16235,7 @@ function OhhwellsBridge() {
|
|
|
14962
16235
|
setFieldPickState({ type: fieldTypeOf(wrapper), required: isFieldRequired(wrapper) });
|
|
14963
16236
|
setFieldTypePickerOpen(false);
|
|
14964
16237
|
}, []);
|
|
14965
|
-
const withSelectedField =
|
|
16238
|
+
const withSelectedField = useCallback8(
|
|
14966
16239
|
(run) => {
|
|
14967
16240
|
const wrapper = fieldPickElRef.current;
|
|
14968
16241
|
const form = formPickElRef.current;
|
|
@@ -14975,28 +16248,28 @@ function OhhwellsBridge() {
|
|
|
14975
16248
|
},
|
|
14976
16249
|
[persistFields]
|
|
14977
16250
|
);
|
|
14978
|
-
const handleFieldTypeChange =
|
|
16251
|
+
const handleFieldTypeChange = useCallback8(
|
|
14979
16252
|
(type) => withSelectedField((_form, wrapper) => {
|
|
14980
16253
|
applyFieldType(wrapper, type);
|
|
14981
16254
|
selectField(wrapper);
|
|
14982
16255
|
}),
|
|
14983
16256
|
[selectField, withSelectedField]
|
|
14984
16257
|
);
|
|
14985
|
-
const handleFieldRequiredToggle =
|
|
16258
|
+
const handleFieldRequiredToggle = useCallback8(
|
|
14986
16259
|
() => withSelectedField((_form, wrapper) => {
|
|
14987
16260
|
setFieldRequired(wrapper, !isFieldRequired(wrapper));
|
|
14988
16261
|
selectField(wrapper);
|
|
14989
16262
|
}),
|
|
14990
16263
|
[selectField, withSelectedField]
|
|
14991
16264
|
);
|
|
14992
|
-
const handleFieldDuplicate =
|
|
16265
|
+
const handleFieldDuplicate = useCallback8(
|
|
14993
16266
|
() => withSelectedField((form, wrapper) => {
|
|
14994
16267
|
const copy = duplicateField(form, wrapper);
|
|
14995
16268
|
selectField(copy);
|
|
14996
16269
|
}),
|
|
14997
16270
|
[selectField, withSelectedField]
|
|
14998
16271
|
);
|
|
14999
|
-
const handleFieldDelete =
|
|
16272
|
+
const handleFieldDelete = useCallback8(
|
|
15000
16273
|
() => withSelectedField((_form, wrapper) => {
|
|
15001
16274
|
removeField(wrapper);
|
|
15002
16275
|
clearFieldPick();
|
|
@@ -15004,7 +16277,7 @@ function OhhwellsBridge() {
|
|
|
15004
16277
|
}),
|
|
15005
16278
|
[clearFieldPick, withSelectedField]
|
|
15006
16279
|
);
|
|
15007
|
-
const handleAddField =
|
|
16280
|
+
const handleAddField = useCallback8(
|
|
15008
16281
|
(type) => {
|
|
15009
16282
|
const form = formPickElRef.current;
|
|
15010
16283
|
if (!form) return;
|
|
@@ -15020,8 +16293,8 @@ function OhhwellsBridge() {
|
|
|
15020
16293
|
},
|
|
15021
16294
|
[persistFields, selectField]
|
|
15022
16295
|
);
|
|
15023
|
-
const fieldDragRef =
|
|
15024
|
-
const buildFieldDropSlots =
|
|
16296
|
+
const fieldDragRef = useRef10(null);
|
|
16297
|
+
const buildFieldDropSlots = useCallback8((form, draggedKey) => {
|
|
15025
16298
|
const others = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== draggedKey);
|
|
15026
16299
|
const slots = others.map((el) => {
|
|
15027
16300
|
const rect = el.getBoundingClientRect();
|
|
@@ -15034,7 +16307,7 @@ function OhhwellsBridge() {
|
|
|
15034
16307
|
}
|
|
15035
16308
|
return slots;
|
|
15036
16309
|
}, []);
|
|
15037
|
-
const handleFieldDragStart =
|
|
16310
|
+
const handleFieldDragStart = useCallback8(() => {
|
|
15038
16311
|
const wrapper = fieldPickElRef.current;
|
|
15039
16312
|
const form = formPickElRef.current;
|
|
15040
16313
|
if (!wrapper || !form) return;
|
|
@@ -15043,18 +16316,18 @@ function OhhwellsBridge() {
|
|
|
15043
16316
|
setFieldDragging(true);
|
|
15044
16317
|
setFieldDropSlots(buildFieldDropSlots(form, key));
|
|
15045
16318
|
}, [buildFieldDropSlots]);
|
|
15046
|
-
const handleFieldDragEnd =
|
|
16319
|
+
const handleFieldDragEnd = useCallback8(() => {
|
|
15047
16320
|
fieldDragRef.current = null;
|
|
15048
16321
|
setFieldDropIndex(null);
|
|
15049
16322
|
setFieldDropSlots([]);
|
|
15050
16323
|
setFieldDragging(false);
|
|
15051
16324
|
}, []);
|
|
15052
|
-
const [fieldDropIndex, setFieldDropIndex] =
|
|
15053
|
-
const [fieldDropSlots, setFieldDropSlots] =
|
|
15054
|
-
const [fieldDragging, setFieldDragging] =
|
|
15055
|
-
const clearFormPickRef =
|
|
16325
|
+
const [fieldDropIndex, setFieldDropIndex] = useState13(null);
|
|
16326
|
+
const [fieldDropSlots, setFieldDropSlots] = useState13([]);
|
|
16327
|
+
const [fieldDragging, setFieldDragging] = useState13(false);
|
|
16328
|
+
const clearFormPickRef = useRef10(clearFormPick);
|
|
15056
16329
|
clearFormPickRef.current = clearFormPick;
|
|
15057
|
-
|
|
16330
|
+
useEffect13(() => {
|
|
15058
16331
|
const el = fieldPickElRef.current;
|
|
15059
16332
|
if (!el || fieldPickRect === null) return;
|
|
15060
16333
|
const observer = new ResizeObserver(() => {
|
|
@@ -15063,7 +16336,7 @@ function OhhwellsBridge() {
|
|
|
15063
16336
|
observer.observe(el);
|
|
15064
16337
|
return () => observer.disconnect();
|
|
15065
16338
|
}, [fieldPickRect !== null, fieldPickState]);
|
|
15066
|
-
|
|
16339
|
+
useEffect13(() => {
|
|
15067
16340
|
const el = formPickElRef.current;
|
|
15068
16341
|
if (!el || formPickRect === null) return;
|
|
15069
16342
|
const observer = new ResizeObserver(() => {
|
|
@@ -15072,25 +16345,25 @@ function OhhwellsBridge() {
|
|
|
15072
16345
|
observer.observe(el);
|
|
15073
16346
|
return () => observer.disconnect();
|
|
15074
16347
|
}, [formPickRect !== null, formViewState]);
|
|
15075
|
-
const [toolbarVariant, setToolbarVariant] =
|
|
15076
|
-
const toolbarVariantRef =
|
|
16348
|
+
const [toolbarVariant, setToolbarVariant] = useState13("none");
|
|
16349
|
+
const toolbarVariantRef = useRef10("none");
|
|
15077
16350
|
toolbarVariantRef.current = toolbarVariant;
|
|
15078
|
-
const [selectedIsCta, setSelectedIsCta] =
|
|
15079
|
-
const [selectedIsSocial, setSelectedIsSocial] =
|
|
15080
|
-
const [selectedIsSocialsRow, setSelectedIsSocialsRow] =
|
|
15081
|
-
const [reorderHrefKey, setReorderHrefKey] =
|
|
15082
|
-
const [reorderDragDisabled, setReorderDragDisabled] =
|
|
15083
|
-
const [toggleState, setToggleState] =
|
|
15084
|
-
const [maxBadge, setMaxBadge] =
|
|
15085
|
-
const [activeCommands, setActiveCommands] =
|
|
15086
|
-
const [sectionGap, setSectionGap] =
|
|
15087
|
-
const [toolbarShowEditLink, setToolbarShowEditLink] =
|
|
15088
|
-
const hoveredNavContainerRef =
|
|
15089
|
-
const [hoveredNavContainerRect, setHoveredNavContainerRect] =
|
|
15090
|
-
const hoveredItemElRef =
|
|
15091
|
-
const [hoveredItemRect, setHoveredItemRect] =
|
|
15092
|
-
const [hoveredTextRect, setHoveredTextRect] =
|
|
15093
|
-
|
|
16351
|
+
const [selectedIsCta, setSelectedIsCta] = useState13(false);
|
|
16352
|
+
const [selectedIsSocial, setSelectedIsSocial] = useState13(false);
|
|
16353
|
+
const [selectedIsSocialsRow, setSelectedIsSocialsRow] = useState13(false);
|
|
16354
|
+
const [reorderHrefKey, setReorderHrefKey] = useState13(null);
|
|
16355
|
+
const [reorderDragDisabled, setReorderDragDisabled] = useState13(false);
|
|
16356
|
+
const [toggleState, setToggleState] = useState13(null);
|
|
16357
|
+
const [maxBadge, setMaxBadge] = useState13(null);
|
|
16358
|
+
const [activeCommands, setActiveCommands] = useState13(/* @__PURE__ */ new Set());
|
|
16359
|
+
const [sectionGap, setSectionGap] = useState13(null);
|
|
16360
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = useState13(false);
|
|
16361
|
+
const hoveredNavContainerRef = useRef10(null);
|
|
16362
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState13(null);
|
|
16363
|
+
const hoveredItemElRef = useRef10(null);
|
|
16364
|
+
const [hoveredItemRect, setHoveredItemRect] = useState13(null);
|
|
16365
|
+
const [hoveredTextRect, setHoveredTextRect] = useState13(null);
|
|
16366
|
+
useEffect13(() => {
|
|
15094
16367
|
const sync = () => {
|
|
15095
16368
|
const el = document.querySelector(
|
|
15096
16369
|
'[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]):not([data-ohw-editable="form"] *)'
|
|
@@ -15115,43 +16388,56 @@ function OhhwellsBridge() {
|
|
|
15115
16388
|
});
|
|
15116
16389
|
return () => observer.disconnect();
|
|
15117
16390
|
}, []);
|
|
15118
|
-
const siblingHintElRef =
|
|
15119
|
-
const [siblingHintRect, setSiblingHintRect] =
|
|
15120
|
-
const [siblingHintRects, setSiblingHintRects] =
|
|
15121
|
-
const [isItemDragging, setIsItemDragging] =
|
|
15122
|
-
const [isFooterFrameSelection, setIsFooterFrameSelection] =
|
|
16391
|
+
const siblingHintElRef = useRef10(null);
|
|
16392
|
+
const [siblingHintRect, setSiblingHintRect] = useState13(null);
|
|
16393
|
+
const [siblingHintRects, setSiblingHintRects] = useState13([]);
|
|
16394
|
+
const [isItemDragging, setIsItemDragging] = useState13(false);
|
|
16395
|
+
const [isFooterFrameSelection, setIsFooterFrameSelection] = useState13(false);
|
|
15123
16396
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
15124
|
-
const [
|
|
15125
|
-
const
|
|
15126
|
-
|
|
15127
|
-
const [
|
|
15128
|
-
const [
|
|
15129
|
-
const [
|
|
15130
|
-
const
|
|
15131
|
-
const
|
|
15132
|
-
const
|
|
15133
|
-
const
|
|
15134
|
-
const
|
|
15135
|
-
const
|
|
15136
|
-
const
|
|
15137
|
-
const
|
|
15138
|
-
const
|
|
15139
|
-
const
|
|
15140
|
-
const
|
|
15141
|
-
const
|
|
15142
|
-
const
|
|
15143
|
-
const
|
|
15144
|
-
const
|
|
15145
|
-
const
|
|
15146
|
-
const [
|
|
15147
|
-
const [
|
|
15148
|
-
const
|
|
15149
|
-
const
|
|
15150
|
-
const
|
|
15151
|
-
const
|
|
15152
|
-
const
|
|
16397
|
+
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState13(null);
|
|
16398
|
+
const [footerHeadingVisible, setFooterHeadingVisible] = useState13(null);
|
|
16399
|
+
const footerDragRef = useRef10(null);
|
|
16400
|
+
const [footerDropSlots, setFooterDropSlots] = useState13([]);
|
|
16401
|
+
const [activeFooterDropIndex, setActiveFooterDropIndex] = useState13(null);
|
|
16402
|
+
const [draggedItemRect, setDraggedItemRect] = useState13(null);
|
|
16403
|
+
const footerPointerDragRef = useRef10(null);
|
|
16404
|
+
const suppressNextClickRef = useRef10(false);
|
|
16405
|
+
const suppressClickUntilRef = useRef10(0);
|
|
16406
|
+
const [linkPopover, setLinkPopover] = useState13(null);
|
|
16407
|
+
const linkPopoverSessionRef = useRef10(null);
|
|
16408
|
+
const addNavAfterAnchorRef = useRef10(null);
|
|
16409
|
+
const editContentRef = useRef10({});
|
|
16410
|
+
const aiSectionsRef = useRef10("");
|
|
16411
|
+
const brandKitRef = useRef10("");
|
|
16412
|
+
const stylesRef = useRef10("");
|
|
16413
|
+
const pendingDeleteUndoRef = useRef10(null);
|
|
16414
|
+
const [floatingPanel, setFloatingPanel] = useState13(null);
|
|
16415
|
+
const floatingPanelOpenRef = useRef10(false);
|
|
16416
|
+
const setFloatingPanelRef = useRef10(setFloatingPanel);
|
|
16417
|
+
const [floatingPanelPos, setFloatingPanelPos] = useState13(null);
|
|
16418
|
+
const [logoSizeDraft, setLogoSizeDraft] = useState13(null);
|
|
16419
|
+
const [editorViewport, setEditorViewport] = useState13("desktop");
|
|
16420
|
+
const [parentScrollSnap, setParentScrollSnap] = useState13(null);
|
|
16421
|
+
const [sitePages, setSitePages] = useState13([]);
|
|
16422
|
+
const [sectionsByPath, setSectionsByPath] = useState13({});
|
|
16423
|
+
const sectionsPrefetchGenRef = useRef10(0);
|
|
16424
|
+
const setLinkPopoverRef = useRef10(setLinkPopover);
|
|
16425
|
+
const linkPopoverPanelRef = useRef10(null);
|
|
16426
|
+
const linkPopoverOpenRef = useRef10(false);
|
|
16427
|
+
const linkPopoverGraceUntilRef = useRef10(0);
|
|
15153
16428
|
setLinkPopoverRef.current = setLinkPopover;
|
|
16429
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
15154
16430
|
linkPopoverSessionRef.current = linkPopover;
|
|
16431
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
16432
|
+
useEffect13(() => {
|
|
16433
|
+
const syncViewport = () => {
|
|
16434
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
16435
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
16436
|
+
};
|
|
16437
|
+
syncViewport();
|
|
16438
|
+
window.addEventListener("resize", syncViewport);
|
|
16439
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
16440
|
+
}, []);
|
|
15155
16441
|
const {
|
|
15156
16442
|
navDragRef,
|
|
15157
16443
|
navDropSlots,
|
|
@@ -15184,10 +16470,20 @@ function OhhwellsBridge() {
|
|
|
15184
16470
|
getNavigationItemAnchor,
|
|
15185
16471
|
isDragHandleDisabled
|
|
15186
16472
|
});
|
|
16473
|
+
const { sectionDropSlots, activeSectionDropIndex, isSectionDragging } = useSectionDrag({
|
|
16474
|
+
isEditMode,
|
|
16475
|
+
editContentRef,
|
|
16476
|
+
postToParentRef,
|
|
16477
|
+
parentScrollRef,
|
|
16478
|
+
navDragRef,
|
|
16479
|
+
footerDragRef,
|
|
16480
|
+
suppressNextClickRef,
|
|
16481
|
+
suppressClickUntilRef
|
|
16482
|
+
});
|
|
15187
16483
|
const bumpLinkPopoverGrace = () => {
|
|
15188
16484
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
15189
16485
|
};
|
|
15190
|
-
const runSectionsPrefetch =
|
|
16486
|
+
const runSectionsPrefetch = useCallback8((pages) => {
|
|
15191
16487
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
15192
16488
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
15193
16489
|
const paths = pages.map((p) => p.path);
|
|
@@ -15206,9 +16502,9 @@ function OhhwellsBridge() {
|
|
|
15206
16502
|
);
|
|
15207
16503
|
});
|
|
15208
16504
|
}, [isEditMode, pathname]);
|
|
15209
|
-
const runSectionsPrefetchRef =
|
|
16505
|
+
const runSectionsPrefetchRef = useRef10(runSectionsPrefetch);
|
|
15210
16506
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
15211
|
-
|
|
16507
|
+
useEffect13(() => {
|
|
15212
16508
|
if (!linkPopover) {
|
|
15213
16509
|
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
15214
16510
|
return;
|
|
@@ -15236,7 +16532,7 @@ function OhhwellsBridge() {
|
|
|
15236
16532
|
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
15237
16533
|
};
|
|
15238
16534
|
}, [linkPopover, postToParent2]);
|
|
15239
|
-
|
|
16535
|
+
useEffect13(() => {
|
|
15240
16536
|
if (!isEditMode) return;
|
|
15241
16537
|
const useFixtures = shouldUseDevFixtures();
|
|
15242
16538
|
if (useFixtures) {
|
|
@@ -15260,14 +16556,14 @@ function OhhwellsBridge() {
|
|
|
15260
16556
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
15261
16557
|
return () => window.removeEventListener("message", onSitePages);
|
|
15262
16558
|
}, [isEditMode, postToParent2]);
|
|
15263
|
-
|
|
16559
|
+
useEffect13(() => {
|
|
15264
16560
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
15265
16561
|
void loadAllSectionsManifest().then((manifest) => {
|
|
15266
16562
|
if (Object.keys(manifest).length === 0) return;
|
|
15267
16563
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
15268
16564
|
});
|
|
15269
16565
|
}, [isEditMode]);
|
|
15270
|
-
|
|
16566
|
+
useEffect13(() => {
|
|
15271
16567
|
const update = () => {
|
|
15272
16568
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
15273
16569
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -15291,10 +16587,10 @@ function OhhwellsBridge() {
|
|
|
15291
16587
|
vvp.removeEventListener("resize", update);
|
|
15292
16588
|
};
|
|
15293
16589
|
}, []);
|
|
15294
|
-
const refreshStateRules =
|
|
16590
|
+
const refreshStateRules = useCallback8(() => {
|
|
15295
16591
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
15296
16592
|
}, []);
|
|
15297
|
-
const processConfigRequest =
|
|
16593
|
+
const processConfigRequest = useCallback8((insertAfterVal) => {
|
|
15298
16594
|
const tracker = getSectionsTracker();
|
|
15299
16595
|
let entries = [];
|
|
15300
16596
|
try {
|
|
@@ -15317,7 +16613,7 @@ function OhhwellsBridge() {
|
|
|
15317
16613
|
}
|
|
15318
16614
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
15319
16615
|
}, [isEditMode]);
|
|
15320
|
-
const deactivate =
|
|
16616
|
+
const deactivate = useCallback8(() => {
|
|
15321
16617
|
const el = activeElRef.current;
|
|
15322
16618
|
if (!el) return;
|
|
15323
16619
|
const isFormBlock = el.dataset.ohwEditable === "form";
|
|
@@ -15333,7 +16629,7 @@ function OhhwellsBridge() {
|
|
|
15333
16629
|
const original = originalContentRef.current ?? "";
|
|
15334
16630
|
if (html !== sanitizeHtml(original)) {
|
|
15335
16631
|
postToParentRef.current({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
15336
|
-
const h = document.
|
|
16632
|
+
const h = document.body.scrollHeight;
|
|
15337
16633
|
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
15338
16634
|
}
|
|
15339
16635
|
}
|
|
@@ -15358,12 +16654,12 @@ function OhhwellsBridge() {
|
|
|
15358
16654
|
setToolbarShowEditLink(false);
|
|
15359
16655
|
postToParent2({ type: "ow:exit-edit" });
|
|
15360
16656
|
}, [postToParent2]);
|
|
15361
|
-
const clearSelectedAttr =
|
|
16657
|
+
const clearSelectedAttr = useCallback8(() => {
|
|
15362
16658
|
document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
|
|
15363
16659
|
el.removeAttribute("data-ohw-selected");
|
|
15364
16660
|
});
|
|
15365
16661
|
}, []);
|
|
15366
|
-
const deselect =
|
|
16662
|
+
const deselect = useCallback8(() => {
|
|
15367
16663
|
clearSelectedAttr();
|
|
15368
16664
|
selectedElRef.current = null;
|
|
15369
16665
|
selectedHrefKeyRef.current = null;
|
|
@@ -15392,20 +16688,20 @@ function OhhwellsBridge() {
|
|
|
15392
16688
|
setToolbarVariant("none");
|
|
15393
16689
|
}
|
|
15394
16690
|
}, [clearSelectedAttr]);
|
|
15395
|
-
const markSelected =
|
|
16691
|
+
const markSelected = useCallback8((el) => {
|
|
15396
16692
|
clearSelectedAttr();
|
|
15397
16693
|
el.removeAttribute("data-ohw-hovered");
|
|
15398
16694
|
el.setAttribute("data-ohw-selected", "");
|
|
15399
16695
|
}, [clearSelectedAttr]);
|
|
15400
|
-
const isSelectedForHover =
|
|
16696
|
+
const isSelectedForHover = useCallback8((el) => {
|
|
15401
16697
|
if (!el) return false;
|
|
15402
16698
|
return [selectedElRef.current, activeElRef.current].some(
|
|
15403
16699
|
(busy) => busy && (el === busy || busy.contains(el) || el.contains(busy))
|
|
15404
16700
|
);
|
|
15405
16701
|
}, []);
|
|
15406
|
-
const isSelectedForHoverRef =
|
|
16702
|
+
const isSelectedForHoverRef = useRef10(isSelectedForHover);
|
|
15407
16703
|
isSelectedForHoverRef.current = isSelectedForHover;
|
|
15408
|
-
const resolveHrefKeyElement =
|
|
16704
|
+
const resolveHrefKeyElement = useCallback8((hrefKey) => {
|
|
15409
16705
|
if (isFooterHrefKey(hrefKey)) {
|
|
15410
16706
|
return document.querySelector(
|
|
15411
16707
|
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
@@ -15420,7 +16716,7 @@ function OhhwellsBridge() {
|
|
|
15420
16716
|
`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
15421
16717
|
);
|
|
15422
16718
|
}, []);
|
|
15423
|
-
const resyncSelectedNavigationItem =
|
|
16719
|
+
const resyncSelectedNavigationItem = useCallback8(() => {
|
|
15424
16720
|
const hrefKey = selectedHrefKeyRef.current;
|
|
15425
16721
|
if (hrefKey) {
|
|
15426
16722
|
const link = resolveHrefKeyElement(hrefKey);
|
|
@@ -15458,7 +16754,7 @@ function OhhwellsBridge() {
|
|
|
15458
16754
|
);
|
|
15459
16755
|
}
|
|
15460
16756
|
}, [resolveHrefKeyElement]);
|
|
15461
|
-
const reselectNavigationItem =
|
|
16757
|
+
const reselectNavigationItem = useCallback8((navAnchor) => {
|
|
15462
16758
|
selectedElRef.current = navAnchor;
|
|
15463
16759
|
selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
|
|
15464
16760
|
selectedFooterColAttrRef.current = null;
|
|
@@ -15489,7 +16785,7 @@ function OhhwellsBridge() {
|
|
|
15489
16785
|
setToolbarShowEditLink(false);
|
|
15490
16786
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
15491
16787
|
}, [markSelected]);
|
|
15492
|
-
const commitNavigationTextEdit =
|
|
16788
|
+
const commitNavigationTextEdit = useCallback8((navAnchor) => {
|
|
15493
16789
|
const el = activeElRef.current;
|
|
15494
16790
|
if (!el) return;
|
|
15495
16791
|
const key = el.dataset.ohwKey;
|
|
@@ -15503,7 +16799,7 @@ function OhhwellsBridge() {
|
|
|
15503
16799
|
const original = originalContentRef.current ?? "";
|
|
15504
16800
|
if (html !== sanitizeHtml(original)) {
|
|
15505
16801
|
postToParent2({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
15506
|
-
const h = document.
|
|
16802
|
+
const h = document.body.scrollHeight;
|
|
15507
16803
|
if (h > 50) postToParent2({ type: "ow:height", height: h });
|
|
15508
16804
|
}
|
|
15509
16805
|
}
|
|
@@ -15522,7 +16818,7 @@ function OhhwellsBridge() {
|
|
|
15522
16818
|
postToParent2({ type: "ow:exit-edit" });
|
|
15523
16819
|
reselectNavigationItem(navAnchor);
|
|
15524
16820
|
}, [postToParent2, reselectNavigationItem]);
|
|
15525
|
-
const handleAddTopLevelNavItem =
|
|
16821
|
+
const handleAddTopLevelNavItem = useCallback8(() => {
|
|
15526
16822
|
const items = listNavbarRootItems();
|
|
15527
16823
|
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
15528
16824
|
deselectRef.current();
|
|
@@ -15534,7 +16830,7 @@ function OhhwellsBridge() {
|
|
|
15534
16830
|
intent: "add-nav"
|
|
15535
16831
|
});
|
|
15536
16832
|
}, []);
|
|
15537
|
-
const maybeWarnNavLinkDropdownConflict =
|
|
16833
|
+
const maybeWarnNavLinkDropdownConflict = useCallback8(
|
|
15538
16834
|
(anchor) => {
|
|
15539
16835
|
if (!isNavbarHrefKey(anchor.getAttribute("data-ohw-href-key"))) return;
|
|
15540
16836
|
if (!navDropdownsOpenOnClick()) return;
|
|
@@ -15547,7 +16843,7 @@ function OhhwellsBridge() {
|
|
|
15547
16843
|
},
|
|
15548
16844
|
[postToParent2]
|
|
15549
16845
|
);
|
|
15550
|
-
const handleNavDropdownOpenChange =
|
|
16846
|
+
const handleNavDropdownOpenChange = useCallback8((open) => {
|
|
15551
16847
|
const selected = selectedElRef.current;
|
|
15552
16848
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
15553
16849
|
setNavGroupForceOpen(selected, open);
|
|
@@ -15559,7 +16855,7 @@ function OhhwellsBridge() {
|
|
|
15559
16855
|
}
|
|
15560
16856
|
});
|
|
15561
16857
|
}, []);
|
|
15562
|
-
const handleFooterHeadingVisibleChange =
|
|
16858
|
+
const handleFooterHeadingVisibleChange = useCallback8(
|
|
15563
16859
|
(visible) => {
|
|
15564
16860
|
const selected = selectedElRef.current;
|
|
15565
16861
|
if (!selected || !isFooterFrameSelectionRef.current) return;
|
|
@@ -15583,7 +16879,7 @@ function OhhwellsBridge() {
|
|
|
15583
16879
|
},
|
|
15584
16880
|
[postToParent2]
|
|
15585
16881
|
);
|
|
15586
|
-
const enterEditOnNewItem =
|
|
16882
|
+
const enterEditOnNewItem = useCallback8((anchor) => {
|
|
15587
16883
|
const label = anchor.querySelector('[data-ohw-editable="text"]');
|
|
15588
16884
|
if (!label) {
|
|
15589
16885
|
selectRef.current(anchor);
|
|
@@ -15592,8 +16888,8 @@ function OhhwellsBridge() {
|
|
|
15592
16888
|
setNavGroupForceOpen(anchor, true);
|
|
15593
16889
|
activateRef.current(label);
|
|
15594
16890
|
}, []);
|
|
15595
|
-
const pendingSocialAddRef =
|
|
15596
|
-
const handleAddChildItem =
|
|
16891
|
+
const pendingSocialAddRef = useRef10(null);
|
|
16892
|
+
const handleAddChildItem = useCallback8(() => {
|
|
15597
16893
|
const selected = selectedElRef.current;
|
|
15598
16894
|
if (!selected) return;
|
|
15599
16895
|
const socialsRow = isSocialsRow(selected) ? selected : findSocialsRow(selected);
|
|
@@ -15702,7 +16998,7 @@ function OhhwellsBridge() {
|
|
|
15702
16998
|
enterEditOnNewItem(result.anchor);
|
|
15703
16999
|
});
|
|
15704
17000
|
}, [enterEditOnNewItem, isFooterFrameSelection, maybeWarnNavLinkDropdownConflict, postToParent2]);
|
|
15705
|
-
const handleAddFooterColumn =
|
|
17001
|
+
const handleAddFooterColumn = useCallback8(() => {
|
|
15706
17002
|
if (!canAddFooterColumn()) {
|
|
15707
17003
|
postToParent2({
|
|
15708
17004
|
type: "ow:toast",
|
|
@@ -15723,7 +17019,7 @@ function OhhwellsBridge() {
|
|
|
15723
17019
|
selectRef.current(result.firstLink);
|
|
15724
17020
|
});
|
|
15725
17021
|
}, [postToParent2]);
|
|
15726
|
-
const clearFooterDragVisuals =
|
|
17022
|
+
const clearFooterDragVisuals = useCallback8(() => {
|
|
15727
17023
|
footerDragRef.current = null;
|
|
15728
17024
|
setSiblingHintRects([]);
|
|
15729
17025
|
setFooterDropSlots([]);
|
|
@@ -15732,7 +17028,7 @@ function OhhwellsBridge() {
|
|
|
15732
17028
|
setIsItemDragging(false);
|
|
15733
17029
|
unlockFooterDragInteraction();
|
|
15734
17030
|
}, []);
|
|
15735
|
-
const refreshFooterDragVisuals =
|
|
17031
|
+
const refreshFooterDragVisuals = useCallback8((session, activeSlot, clientX, clientY) => {
|
|
15736
17032
|
const dragged = session.draggedEl;
|
|
15737
17033
|
setDraggedItemRect(dragged.getBoundingClientRect());
|
|
15738
17034
|
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
@@ -15764,13 +17060,13 @@ function OhhwellsBridge() {
|
|
|
15764
17060
|
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
15765
17061
|
setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
15766
17062
|
}, []);
|
|
15767
|
-
const refreshFooterDragVisualsRef =
|
|
17063
|
+
const refreshFooterDragVisualsRef = useRef10(refreshFooterDragVisuals);
|
|
15768
17064
|
refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
|
|
15769
|
-
const commitFooterDragRef =
|
|
17065
|
+
const commitFooterDragRef = useRef10(() => {
|
|
15770
17066
|
});
|
|
15771
|
-
const beginFooterDragRef =
|
|
17067
|
+
const beginFooterDragRef = useRef10(() => {
|
|
15772
17068
|
});
|
|
15773
|
-
const beginFooterDrag =
|
|
17069
|
+
const beginFooterDrag = useCallback8(
|
|
15774
17070
|
(session) => {
|
|
15775
17071
|
const rect = session.draggedEl.getBoundingClientRect();
|
|
15776
17072
|
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
@@ -15790,7 +17086,7 @@ function OhhwellsBridge() {
|
|
|
15790
17086
|
[refreshFooterDragVisuals]
|
|
15791
17087
|
);
|
|
15792
17088
|
beginFooterDragRef.current = beginFooterDrag;
|
|
15793
|
-
const commitFooterDrag =
|
|
17089
|
+
const commitFooterDrag = useCallback8(
|
|
15794
17090
|
(clientX, clientY) => {
|
|
15795
17091
|
const session = footerDragRef.current;
|
|
15796
17092
|
if (!session) {
|
|
@@ -15919,7 +17215,7 @@ function OhhwellsBridge() {
|
|
|
15919
17215
|
[clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
|
|
15920
17216
|
);
|
|
15921
17217
|
commitFooterDragRef.current = commitFooterDrag;
|
|
15922
|
-
const startFooterLinkDrag =
|
|
17218
|
+
const startFooterLinkDrag = useCallback8(
|
|
15923
17219
|
(anchor, clientX, clientY, wasSelected) => {
|
|
15924
17220
|
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
15925
17221
|
if (!hrefKey) return false;
|
|
@@ -15955,7 +17251,7 @@ function OhhwellsBridge() {
|
|
|
15955
17251
|
},
|
|
15956
17252
|
[beginFooterDrag]
|
|
15957
17253
|
);
|
|
15958
|
-
const startFooterColumnDrag =
|
|
17254
|
+
const startFooterColumnDrag = useCallback8(
|
|
15959
17255
|
(columnEl, clientX, clientY, wasSelected) => {
|
|
15960
17256
|
const columns = listFooterColumns();
|
|
15961
17257
|
const idx = columns.indexOf(columnEl);
|
|
@@ -15975,7 +17271,7 @@ function OhhwellsBridge() {
|
|
|
15975
17271
|
},
|
|
15976
17272
|
[beginFooterDrag]
|
|
15977
17273
|
);
|
|
15978
|
-
const handleItemDragStart =
|
|
17274
|
+
const handleItemDragStart = useCallback8(
|
|
15979
17275
|
(e) => {
|
|
15980
17276
|
const selected = selectedElRef.current;
|
|
15981
17277
|
if (!selected) {
|
|
@@ -15995,7 +17291,7 @@ function OhhwellsBridge() {
|
|
|
15995
17291
|
},
|
|
15996
17292
|
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
|
|
15997
17293
|
);
|
|
15998
|
-
const handleItemDragEnd =
|
|
17294
|
+
const handleItemDragEnd = useCallback8(
|
|
15999
17295
|
(e) => {
|
|
16000
17296
|
if (footerDragRef.current) {
|
|
16001
17297
|
const x = e?.clientX;
|
|
@@ -16021,7 +17317,7 @@ function OhhwellsBridge() {
|
|
|
16021
17317
|
},
|
|
16022
17318
|
[commitFooterDrag, commitNavDrag, navDragRef]
|
|
16023
17319
|
);
|
|
16024
|
-
const handleItemChromePointerDown =
|
|
17320
|
+
const handleItemChromePointerDown = useCallback8((e) => {
|
|
16025
17321
|
if (e.button !== 0) return;
|
|
16026
17322
|
const selected = selectedElRef.current;
|
|
16027
17323
|
if (!selected) return;
|
|
@@ -16052,7 +17348,7 @@ function OhhwellsBridge() {
|
|
|
16052
17348
|
}
|
|
16053
17349
|
if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
|
|
16054
17350
|
}, [armNavPressFromChrome]);
|
|
16055
|
-
const handleItemChromeClick =
|
|
17351
|
+
const handleItemChromeClick = useCallback8((clientX, clientY) => {
|
|
16056
17352
|
if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
|
|
16057
17353
|
suppressNextClickRef.current = false;
|
|
16058
17354
|
return;
|
|
@@ -16065,7 +17361,7 @@ function OhhwellsBridge() {
|
|
|
16065
17361
|
}, []);
|
|
16066
17362
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
16067
17363
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
16068
|
-
const select =
|
|
17364
|
+
const select = useCallback8((anchor) => {
|
|
16069
17365
|
if (!isNavigationItem2(anchor)) return;
|
|
16070
17366
|
if (activeElRef.current) deactivate();
|
|
16071
17367
|
aiSectionApiRef.current?.selectFromElement(anchor);
|
|
@@ -16108,7 +17404,7 @@ function OhhwellsBridge() {
|
|
|
16108
17404
|
setFloatingPanel(null);
|
|
16109
17405
|
setLogoSizeDraft(null);
|
|
16110
17406
|
}, [deactivate, markSelected]);
|
|
16111
|
-
const selectFrame =
|
|
17407
|
+
const selectFrame = useCallback8((el) => {
|
|
16112
17408
|
if (!isNavigationContainer(el)) return;
|
|
16113
17409
|
if (activeElRef.current) deactivate();
|
|
16114
17410
|
aiSectionApiRef.current?.selectFromElement(el);
|
|
@@ -16159,7 +17455,7 @@ function OhhwellsBridge() {
|
|
|
16159
17455
|
setFloatingPanel(null);
|
|
16160
17456
|
setLogoSizeDraft(null);
|
|
16161
17457
|
}, [deactivate, markSelected, postToParent2]);
|
|
16162
|
-
const selectLogo =
|
|
17458
|
+
const selectLogo = useCallback8(
|
|
16163
17459
|
(logoEl) => {
|
|
16164
17460
|
if (activeElRef.current) deactivate();
|
|
16165
17461
|
selectedElRef.current = logoEl;
|
|
@@ -16188,7 +17484,7 @@ function OhhwellsBridge() {
|
|
|
16188
17484
|
},
|
|
16189
17485
|
[deactivate, markSelected]
|
|
16190
17486
|
);
|
|
16191
|
-
const openLogoSizePanel =
|
|
17487
|
+
const openLogoSizePanel = useCallback8((logoEl) => {
|
|
16192
17488
|
const placement = getLogoPlacement(logoEl);
|
|
16193
17489
|
const draft = readLogoSizeState(editContentRef.current, placement);
|
|
16194
17490
|
setLogoSizeDraft(draft);
|
|
@@ -16201,7 +17497,7 @@ function OhhwellsBridge() {
|
|
|
16201
17497
|
placement
|
|
16202
17498
|
});
|
|
16203
17499
|
}, []);
|
|
16204
|
-
const openSocialsDisplayPanel =
|
|
17500
|
+
const openSocialsDisplayPanel = useCallback8((row) => {
|
|
16205
17501
|
setParentScrollSnap(parentScrollRef.current);
|
|
16206
17502
|
setFloatingPanel({
|
|
16207
17503
|
key: "socials-display",
|
|
@@ -16211,11 +17507,11 @@ function OhhwellsBridge() {
|
|
|
16211
17507
|
row
|
|
16212
17508
|
});
|
|
16213
17509
|
}, []);
|
|
16214
|
-
const isEditModeRef =
|
|
16215
|
-
const requestMissingSocialIconsRef =
|
|
17510
|
+
const isEditModeRef = useRef10(false);
|
|
17511
|
+
const requestMissingSocialIconsRef = useRef10(() => {
|
|
16216
17512
|
});
|
|
16217
|
-
const askedSocialIconsRef =
|
|
16218
|
-
const requestMissingSocialIcons =
|
|
17513
|
+
const askedSocialIconsRef = useRef10(/* @__PURE__ */ new Set());
|
|
17514
|
+
const requestMissingSocialIcons = useCallback8(() => {
|
|
16219
17515
|
const items = Array.from(document.querySelectorAll(`[${SOCIALS_ROW_ATTR}]`)).filter((row) => socialsDisplayFor(row, editContentRef.current).icon).flatMap((row) => {
|
|
16220
17516
|
const missing = socialsMissingIcons(row);
|
|
16221
17517
|
listSocialItems(row).forEach((item) => ensureIconSlot(item));
|
|
@@ -16227,7 +17523,7 @@ function OhhwellsBridge() {
|
|
|
16227
17523
|
}, []);
|
|
16228
17524
|
requestMissingSocialIconsRef.current = requestMissingSocialIcons;
|
|
16229
17525
|
isEditModeRef.current = isEditMode;
|
|
16230
|
-
const changeSocialsDisplay =
|
|
17526
|
+
const changeSocialsDisplay = useCallback8(
|
|
16231
17527
|
(row, next) => {
|
|
16232
17528
|
if (next.icon) {
|
|
16233
17529
|
const missing = socialsMissingIcons(row);
|
|
@@ -16251,17 +17547,17 @@ function OhhwellsBridge() {
|
|
|
16251
17547
|
},
|
|
16252
17548
|
[]
|
|
16253
17549
|
);
|
|
16254
|
-
const closeFloatingPanelOnly =
|
|
17550
|
+
const closeFloatingPanelOnly = useCallback8(() => {
|
|
16255
17551
|
setFloatingPanel(null);
|
|
16256
17552
|
setLogoSizeDraft(null);
|
|
16257
17553
|
}, []);
|
|
16258
17554
|
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
16259
|
-
const closeFloatingPanelAndDeselect =
|
|
17555
|
+
const closeFloatingPanelAndDeselect = useCallback8(() => {
|
|
16260
17556
|
setFloatingPanel(null);
|
|
16261
17557
|
setLogoSizeDraft(null);
|
|
16262
17558
|
deselectRef.current();
|
|
16263
17559
|
}, []);
|
|
16264
|
-
|
|
17560
|
+
useEffect13(() => {
|
|
16265
17561
|
const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
|
|
16266
17562
|
if (!session || !logoSizeDraft) {
|
|
16267
17563
|
postToParentRef.current({ type: "ow:logo-size-panel", open: false });
|
|
@@ -16280,7 +17576,7 @@ function OhhwellsBridge() {
|
|
|
16280
17576
|
max: LOGO_SIZE_MAX
|
|
16281
17577
|
});
|
|
16282
17578
|
}, [floatingPanel, logoSizeDraft, editorViewport]);
|
|
16283
|
-
const persistLogoSizeDraft =
|
|
17579
|
+
const persistLogoSizeDraft = useCallback8(
|
|
16284
17580
|
(placement, draft) => {
|
|
16285
17581
|
const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
|
|
16286
17582
|
const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
|
|
@@ -16320,7 +17616,7 @@ function OhhwellsBridge() {
|
|
|
16320
17616
|
},
|
|
16321
17617
|
[postToParent2]
|
|
16322
17618
|
);
|
|
16323
|
-
const activate =
|
|
17619
|
+
const activate = useCallback8((el, options) => {
|
|
16324
17620
|
if (activeElRef.current === el) return;
|
|
16325
17621
|
document.querySelectorAll("[data-ohw-hovered]").forEach((hovered) => {
|
|
16326
17622
|
hovered.removeAttribute("data-ohw-hovered");
|
|
@@ -16418,8 +17714,8 @@ function OhhwellsBridge() {
|
|
|
16418
17714
|
openLogoSizePanelRef.current = openLogoSizePanel;
|
|
16419
17715
|
deselectRef.current = deselect;
|
|
16420
17716
|
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
16421
|
-
const lastSiteWideScopeRef =
|
|
16422
|
-
|
|
17717
|
+
const lastSiteWideScopeRef = useRef10(null);
|
|
17718
|
+
useEffect13(() => {
|
|
16423
17719
|
if (!isEditMode) {
|
|
16424
17720
|
if (lastSiteWideScopeRef.current !== false) {
|
|
16425
17721
|
lastSiteWideScopeRef.current = false;
|
|
@@ -16452,15 +17748,31 @@ function OhhwellsBridge() {
|
|
|
16452
17748
|
}
|
|
16453
17749
|
const applyContent = (content) => {
|
|
16454
17750
|
const imageLoads = [];
|
|
17751
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
17752
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
17753
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
17754
|
+
} else {
|
|
17755
|
+
brandKitRef.current = "";
|
|
17756
|
+
applyBrandToDom(null);
|
|
17757
|
+
}
|
|
16455
17758
|
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
16456
17759
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
17760
|
+
setAiSectionOrder(content[SECTION_ORDER_KEY], window.location.pathname);
|
|
16457
17761
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
16458
17762
|
}
|
|
17763
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
17764
|
+
stylesRef.current = content[STYLE_STORE_KEY];
|
|
17765
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
17766
|
+
}
|
|
17767
|
+
applyBrandChrome(content);
|
|
16459
17768
|
for (const [key, val] of Object.entries(content)) {
|
|
16460
17769
|
if (key === "__ohw_sections") continue;
|
|
16461
17770
|
if (key === AI_SECTIONS_KEY) continue;
|
|
16462
17771
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
16463
17772
|
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
17773
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
17774
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17775
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
16464
17776
|
if (applyVideoSettingNode(key, val)) continue;
|
|
16465
17777
|
if (applyCarouselNode(key, val)) continue;
|
|
16466
17778
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -16521,7 +17833,9 @@ function OhhwellsBridge() {
|
|
|
16521
17833
|
let cancelled = false;
|
|
16522
17834
|
setFetchState("loading");
|
|
16523
17835
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
16524
|
-
|
|
17836
|
+
const initialPath = pathname;
|
|
17837
|
+
fetchedContentPaths.add(`${subdomain}::${initialPath}`);
|
|
17838
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
16525
17839
|
if (cancelled) return;
|
|
16526
17840
|
const content = data?.content ?? {};
|
|
16527
17841
|
contentCache.set(subdomain, content);
|
|
@@ -16534,7 +17848,7 @@ function OhhwellsBridge() {
|
|
|
16534
17848
|
cancelled = true;
|
|
16535
17849
|
};
|
|
16536
17850
|
}, [subdomain, isEditMode]);
|
|
16537
|
-
|
|
17851
|
+
useEffect13(() => {
|
|
16538
17852
|
if (!isEditMode) return;
|
|
16539
17853
|
const resolveIndex = (form, clientY) => {
|
|
16540
17854
|
const wrappers = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== fieldDragRef.current?.key);
|
|
@@ -16575,7 +17889,7 @@ function OhhwellsBridge() {
|
|
|
16575
17889
|
window.removeEventListener("drop", onDrop, true);
|
|
16576
17890
|
};
|
|
16577
17891
|
}, [buildFieldDropSlots, isEditMode, persistFields, selectField]);
|
|
16578
|
-
|
|
17892
|
+
useEffect13(() => {
|
|
16579
17893
|
if (!isEditMode) return;
|
|
16580
17894
|
const mark = () => document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
16581
17895
|
markFormFields(form);
|
|
@@ -16587,7 +17901,7 @@ function OhhwellsBridge() {
|
|
|
16587
17901
|
});
|
|
16588
17902
|
return () => observer.disconnect();
|
|
16589
17903
|
}, [isEditMode, fetchState, pathname]);
|
|
16590
|
-
|
|
17904
|
+
useEffect13(() => {
|
|
16591
17905
|
if (!isEditMode) return;
|
|
16592
17906
|
let saveTimer = null;
|
|
16593
17907
|
const onInput = (e) => {
|
|
@@ -16609,14 +17923,14 @@ function OhhwellsBridge() {
|
|
|
16609
17923
|
document.addEventListener("input", onInput, true);
|
|
16610
17924
|
return () => document.removeEventListener("input", onInput, true);
|
|
16611
17925
|
}, [isEditMode, persistFields]);
|
|
16612
|
-
|
|
17926
|
+
useEffect13(() => {
|
|
16613
17927
|
if (isEditMode || fetchState !== "done") return;
|
|
16614
17928
|
const content = contentCache.get(subdomain) ?? {};
|
|
16615
17929
|
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
16616
17930
|
reconcileFieldsFromContent(form, content);
|
|
16617
17931
|
});
|
|
16618
17932
|
}, [isEditMode, fetchState, subdomain]);
|
|
16619
|
-
|
|
17933
|
+
useEffect13(() => {
|
|
16620
17934
|
if (!isEditMode) return;
|
|
16621
17935
|
const swallow = (e) => {
|
|
16622
17936
|
const target = e.target;
|
|
@@ -16625,12 +17939,12 @@ function OhhwellsBridge() {
|
|
|
16625
17939
|
document.addEventListener("submit", swallow, true);
|
|
16626
17940
|
return () => document.removeEventListener("submit", swallow, true);
|
|
16627
17941
|
}, [isEditMode]);
|
|
16628
|
-
|
|
17942
|
+
useEffect13(() => {
|
|
16629
17943
|
if (isEditMode || fetchState !== "done") return;
|
|
16630
17944
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
16631
17945
|
bindPublishedForms(apiUrl, subdomain, contentCache.get(subdomain) ?? {});
|
|
16632
17946
|
}, [isEditMode, fetchState, subdomain]);
|
|
16633
|
-
|
|
17947
|
+
useEffect13(() => {
|
|
16634
17948
|
if (!subdomain || isEditMode) return;
|
|
16635
17949
|
let debounceTimer = null;
|
|
16636
17950
|
let observer = null;
|
|
@@ -16641,10 +17955,28 @@ function OhhwellsBridge() {
|
|
|
16641
17955
|
initSectionInstancesFromContent(content, window.location.pathname);
|
|
16642
17956
|
observer?.disconnect();
|
|
16643
17957
|
try {
|
|
17958
|
+
applyBrandChrome(content);
|
|
17959
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
17960
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
17961
|
+
} else {
|
|
17962
|
+
applyBrandToDom(null);
|
|
17963
|
+
}
|
|
17964
|
+
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
17965
|
+
setAiSectionOrder(content[SECTION_ORDER_KEY], window.location.pathname);
|
|
17966
|
+
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
17967
|
+
}
|
|
17968
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
17969
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
17970
|
+
}
|
|
16644
17971
|
for (const [key, val] of Object.entries(content)) {
|
|
16645
17972
|
if (key === "__ohw_sections") continue;
|
|
17973
|
+
if (key === AI_SECTIONS_KEY) continue;
|
|
16646
17974
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
16647
17975
|
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
17976
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
17977
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17978
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17979
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
16648
17980
|
if (applyVideoSettingNode(key, val)) continue;
|
|
16649
17981
|
if (applyCarouselNode(key, val)) continue;
|
|
16650
17982
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -16690,6 +18022,17 @@ function OhhwellsBridge() {
|
|
|
16690
18022
|
debounceTimer = setTimeout(applyFromCache, 150);
|
|
16691
18023
|
};
|
|
16692
18024
|
applyFromCache();
|
|
18025
|
+
const pathCacheKey = `${subdomain}::${pathname}`;
|
|
18026
|
+
if (!fetchedContentPaths.has(pathCacheKey)) {
|
|
18027
|
+
fetchedContentPaths.add(pathCacheKey);
|
|
18028
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
18029
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
18030
|
+
if (!data?.content) return;
|
|
18031
|
+
contentCache.set(subdomain, data.content);
|
|
18032
|
+
applyFromCache();
|
|
18033
|
+
}).catch(() => {
|
|
18034
|
+
});
|
|
18035
|
+
}
|
|
16693
18036
|
observer = new MutationObserver(scheduleApply);
|
|
16694
18037
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
16695
18038
|
return () => {
|
|
@@ -16703,10 +18046,10 @@ function OhhwellsBridge() {
|
|
|
16703
18046
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
16704
18047
|
el.style.display = visible ? "flex" : "none";
|
|
16705
18048
|
}, [subdomain, fetchState]);
|
|
16706
|
-
|
|
18049
|
+
useEffect13(() => {
|
|
16707
18050
|
postToParent2({ type: "ow:navigation", path: pathname });
|
|
16708
18051
|
}, [pathname, postToParent2]);
|
|
16709
|
-
|
|
18052
|
+
useEffect13(() => {
|
|
16710
18053
|
if (!isEditMode) return;
|
|
16711
18054
|
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
16712
18055
|
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
@@ -16714,7 +18057,7 @@ function OhhwellsBridge() {
|
|
|
16714
18057
|
deselectRef.current();
|
|
16715
18058
|
deactivateRef.current();
|
|
16716
18059
|
}, [pathname, isEditMode]);
|
|
16717
|
-
|
|
18060
|
+
useEffect13(() => {
|
|
16718
18061
|
const contentForNav = () => {
|
|
16719
18062
|
if (isEditMode) return editContentRef.current;
|
|
16720
18063
|
if (!subdomain) return {};
|
|
@@ -16783,35 +18126,36 @@ function OhhwellsBridge() {
|
|
|
16783
18126
|
observer?.disconnect();
|
|
16784
18127
|
};
|
|
16785
18128
|
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
16786
|
-
|
|
18129
|
+
useEffect13(() => {
|
|
16787
18130
|
if (!isEditMode) return;
|
|
18131
|
+
let lastPosted = 0;
|
|
16788
18132
|
const measure = () => {
|
|
16789
18133
|
const h = document.body.scrollHeight;
|
|
16790
|
-
if (h > 50
|
|
18134
|
+
if (h > 50 && Math.abs(h - lastPosted) > 1) {
|
|
18135
|
+
lastPosted = h;
|
|
18136
|
+
postToParent2({ type: "ow:height", height: h });
|
|
18137
|
+
}
|
|
18138
|
+
};
|
|
18139
|
+
let raf = null;
|
|
18140
|
+
const schedule = () => {
|
|
18141
|
+
if (raf != null) return;
|
|
18142
|
+
raf = requestAnimationFrame(() => {
|
|
18143
|
+
raf = null;
|
|
18144
|
+
measure();
|
|
18145
|
+
});
|
|
16791
18146
|
};
|
|
16792
18147
|
const t1 = setTimeout(measure, 50);
|
|
16793
18148
|
const t2 = setTimeout(measure, 500);
|
|
16794
|
-
|
|
16795
|
-
|
|
16796
|
-
const clearResizeTimers = () => {
|
|
16797
|
-
resizeTimers.forEach(clearTimeout);
|
|
16798
|
-
resizeTimers = [];
|
|
16799
|
-
};
|
|
16800
|
-
const handleResize = () => {
|
|
16801
|
-
if (window.innerWidth === lastWidth) return;
|
|
16802
|
-
lastWidth = window.innerWidth;
|
|
16803
|
-
clearResizeTimers();
|
|
16804
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
16805
|
-
};
|
|
16806
|
-
window.addEventListener("resize", handleResize);
|
|
18149
|
+
const ro = new ResizeObserver(schedule);
|
|
18150
|
+
ro.observe(document.body);
|
|
16807
18151
|
return () => {
|
|
16808
18152
|
clearTimeout(t1);
|
|
16809
18153
|
clearTimeout(t2);
|
|
16810
|
-
|
|
16811
|
-
|
|
18154
|
+
if (raf != null) cancelAnimationFrame(raf);
|
|
18155
|
+
ro.disconnect();
|
|
16812
18156
|
};
|
|
16813
18157
|
}, [pathname, isEditMode, postToParent2]);
|
|
16814
|
-
|
|
18158
|
+
useEffect13(() => {
|
|
16815
18159
|
if (!subdomainFromQuery || isEditMode) return;
|
|
16816
18160
|
const handleClick = (e) => {
|
|
16817
18161
|
const anchor = e.target.closest("a");
|
|
@@ -16827,7 +18171,7 @@ function OhhwellsBridge() {
|
|
|
16827
18171
|
document.addEventListener("click", handleClick, true);
|
|
16828
18172
|
return () => document.removeEventListener("click", handleClick, true);
|
|
16829
18173
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
16830
|
-
|
|
18174
|
+
useEffect13(() => {
|
|
16831
18175
|
if (!isEditMode) {
|
|
16832
18176
|
editStylesRef.current?.base.remove();
|
|
16833
18177
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -17049,6 +18393,7 @@ function OhhwellsBridge() {
|
|
|
17049
18393
|
return;
|
|
17050
18394
|
}
|
|
17051
18395
|
const target = e.target;
|
|
18396
|
+
if (target.closest("[data-ohw-ai-review]")) return;
|
|
17052
18397
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
17053
18398
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
17054
18399
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
@@ -17060,6 +18405,9 @@ function OhhwellsBridge() {
|
|
|
17060
18405
|
)) {
|
|
17061
18406
|
return;
|
|
17062
18407
|
}
|
|
18408
|
+
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
18409
|
+
clearMediaSelectionRef.current();
|
|
18410
|
+
}
|
|
17063
18411
|
{
|
|
17064
18412
|
const formEl = getFormElement(target);
|
|
17065
18413
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -17214,8 +18562,11 @@ function OhhwellsBridge() {
|
|
|
17214
18562
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
17215
18563
|
e.preventDefault();
|
|
17216
18564
|
e.stopPropagation();
|
|
17217
|
-
|
|
17218
|
-
|
|
18565
|
+
if (selectedMediaElRef.current === editable) {
|
|
18566
|
+
postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
|
|
18567
|
+
} else {
|
|
18568
|
+
selectMediaElementRef.current(editable);
|
|
18569
|
+
}
|
|
17219
18570
|
return;
|
|
17220
18571
|
}
|
|
17221
18572
|
const socialItem = getSocialItem(editable);
|
|
@@ -17351,6 +18702,7 @@ function OhhwellsBridge() {
|
|
|
17351
18702
|
};
|
|
17352
18703
|
const handleDblClick = (e) => {
|
|
17353
18704
|
const target = e.target;
|
|
18705
|
+
if (target.closest("[data-ohw-ai-review]")) return;
|
|
17354
18706
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
17355
18707
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
17356
18708
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
@@ -17402,6 +18754,9 @@ function OhhwellsBridge() {
|
|
|
17402
18754
|
setHoveredItemRect(null);
|
|
17403
18755
|
hoveredNavContainerRef.current = null;
|
|
17404
18756
|
setHoveredNavContainerRect(null);
|
|
18757
|
+
siblingHintElRef.current = null;
|
|
18758
|
+
setSiblingHintRect(null);
|
|
18759
|
+
setSiblingHintRects([]);
|
|
17405
18760
|
return;
|
|
17406
18761
|
}
|
|
17407
18762
|
{
|
|
@@ -17520,7 +18875,6 @@ function OhhwellsBridge() {
|
|
|
17520
18875
|
hoveredNavContainerRef.current = null;
|
|
17521
18876
|
setHoveredNavContainerRect(null);
|
|
17522
18877
|
hoveredItemElRef.current = editable;
|
|
17523
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
17524
18878
|
}
|
|
17525
18879
|
}
|
|
17526
18880
|
}
|
|
@@ -17817,7 +19171,7 @@ function OhhwellsBridge() {
|
|
|
17817
19171
|
}
|
|
17818
19172
|
};
|
|
17819
19173
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
17820
|
-
if (linkPopoverOpenRef.current) {
|
|
19174
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
17821
19175
|
if (hoveredImageRef.current) {
|
|
17822
19176
|
hoveredImageRef.current = null;
|
|
17823
19177
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -18151,7 +19505,9 @@ function OhhwellsBridge() {
|
|
|
18151
19505
|
return;
|
|
18152
19506
|
}
|
|
18153
19507
|
const { y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
18154
|
-
const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).
|
|
19508
|
+
const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
19509
|
+
(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
|
|
19510
|
+
).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
|
|
18155
19511
|
const ZONE = 20;
|
|
18156
19512
|
for (let i = 0; i < sections.length; i++) {
|
|
18157
19513
|
const a = sections[i];
|
|
@@ -18180,8 +19536,7 @@ function OhhwellsBridge() {
|
|
|
18180
19536
|
};
|
|
18181
19537
|
const handleMouseMove = (e) => {
|
|
18182
19538
|
const { clientX, clientY } = e;
|
|
18183
|
-
if (
|
|
18184
|
-
if (isOverEditorChrome(clientX, clientY)) {
|
|
19539
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
|
|
18185
19540
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
18186
19541
|
formHoverElRef.current = null;
|
|
18187
19542
|
setFormHoverRect(null);
|
|
@@ -18189,6 +19544,12 @@ function OhhwellsBridge() {
|
|
|
18189
19544
|
setHoveredItemRect(null);
|
|
18190
19545
|
hoveredNavContainerRef.current = null;
|
|
18191
19546
|
setHoveredNavContainerRect(null);
|
|
19547
|
+
siblingHintElRef.current = null;
|
|
19548
|
+
setSiblingHintRect(null);
|
|
19549
|
+
setSiblingHintRects([]);
|
|
19550
|
+
dismissImageHover();
|
|
19551
|
+
clearImageHover();
|
|
19552
|
+
setSectionGap(null);
|
|
18192
19553
|
return;
|
|
18193
19554
|
}
|
|
18194
19555
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -18200,7 +19561,11 @@ function OhhwellsBridge() {
|
|
|
18200
19561
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
18201
19562
|
const { clientX, clientY } = e.data;
|
|
18202
19563
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
18203
|
-
if (
|
|
19564
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
19565
|
+
dismissImageHover();
|
|
19566
|
+
clearImageHover();
|
|
19567
|
+
return;
|
|
19568
|
+
}
|
|
18204
19569
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
18205
19570
|
probeSectionGapAt(clientX, clientY);
|
|
18206
19571
|
probeImageAt(clientX, clientY);
|
|
@@ -18475,7 +19840,7 @@ function OhhwellsBridge() {
|
|
|
18475
19840
|
timers.set(key, setTimeout(() => {
|
|
18476
19841
|
timers.delete(key);
|
|
18477
19842
|
postToParentRef.current({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
18478
|
-
const h = document.
|
|
19843
|
+
const h = document.body.scrollHeight;
|
|
18479
19844
|
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
18480
19845
|
}, 400));
|
|
18481
19846
|
};
|
|
@@ -18483,10 +19848,23 @@ function OhhwellsBridge() {
|
|
|
18483
19848
|
if (e.data?.type !== "ow:hydrate") return;
|
|
18484
19849
|
const content = e.data.content;
|
|
18485
19850
|
if (!content) return;
|
|
19851
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
19852
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
19853
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
19854
|
+
} else {
|
|
19855
|
+
brandKitRef.current = "";
|
|
19856
|
+
applyBrandToDom(null);
|
|
19857
|
+
}
|
|
18486
19858
|
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
18487
19859
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
19860
|
+
setAiSectionOrder(content[SECTION_ORDER_KEY], window.location.pathname);
|
|
18488
19861
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
18489
19862
|
}
|
|
19863
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
19864
|
+
stylesRef.current = content[STYLE_STORE_KEY];
|
|
19865
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
19866
|
+
}
|
|
19867
|
+
applyBrandChrome(content);
|
|
18490
19868
|
let sectionsJson = null;
|
|
18491
19869
|
for (const [key, val] of Object.entries(content)) {
|
|
18492
19870
|
if (key === "__ohw_sections") {
|
|
@@ -18496,6 +19874,9 @@ function OhhwellsBridge() {
|
|
|
18496
19874
|
if (key === AI_SECTIONS_KEY) continue;
|
|
18497
19875
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
18498
19876
|
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
19877
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
19878
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
19879
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
18499
19880
|
if (applyVideoSettingNode(key, val)) continue;
|
|
18500
19881
|
if (applyCarouselNode(key, val)) continue;
|
|
18501
19882
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -18509,6 +19890,8 @@ function OhhwellsBridge() {
|
|
|
18509
19890
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
18510
19891
|
} else if (el.dataset.ohwEditable === "link") {
|
|
18511
19892
|
applyLinkHref(el, val);
|
|
19893
|
+
} else if (el.dataset.ohwEditable === "icon") {
|
|
19894
|
+
applyIconMarkup(el, val);
|
|
18512
19895
|
} else if (isIconMarkupValue(val)) {
|
|
18513
19896
|
} else {
|
|
18514
19897
|
el.innerHTML = val;
|
|
@@ -18529,7 +19912,7 @@ function OhhwellsBridge() {
|
|
|
18529
19912
|
reconcileFooterOrderFromContent(editContentRef.current);
|
|
18530
19913
|
syncNavigationDragCursorAttrs();
|
|
18531
19914
|
enforceLinkHrefs();
|
|
18532
|
-
const hydratedHeight = document.
|
|
19915
|
+
const hydratedHeight = document.body.scrollHeight;
|
|
18533
19916
|
if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
|
|
18534
19917
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
18535
19918
|
};
|
|
@@ -18593,16 +19976,25 @@ function OhhwellsBridge() {
|
|
|
18593
19976
|
nodes: collectEditableNodes(editContentRef.current)
|
|
18594
19977
|
});
|
|
18595
19978
|
};
|
|
19979
|
+
const clearInteractionChrome = () => {
|
|
19980
|
+
deactivateRef.current();
|
|
19981
|
+
deselectRef.current();
|
|
19982
|
+
clearMediaSelectionRef.current();
|
|
19983
|
+
};
|
|
18596
19984
|
const handleAiApplyTree = (e) => {
|
|
18597
19985
|
if (e.data?.type !== "ow:ai-apply-tree") return;
|
|
18598
19986
|
const payload = e.data.payload;
|
|
18599
19987
|
if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
|
|
19988
|
+
clearInteractionChrome();
|
|
18600
19989
|
const previous = aiSectionsRef.current;
|
|
18601
|
-
const nextState = applyTreeToState(parseAiSectionsState(previous),
|
|
19990
|
+
const nextState = applyTreeToState(parseAiSectionsState(previous), {
|
|
19991
|
+
...payload,
|
|
19992
|
+
path: payload.path ?? window.location.pathname
|
|
19993
|
+
});
|
|
18602
19994
|
const nextValue = serializeAiSectionsState(nextState);
|
|
18603
19995
|
aiSectionsRef.current = nextValue;
|
|
18604
19996
|
applyAiSectionsToDom(nextState);
|
|
18605
|
-
const newHeight = document.
|
|
19997
|
+
const newHeight = document.body.scrollHeight;
|
|
18606
19998
|
if (newHeight > 50) postToParentRef.current({ type: "ow:height", height: newHeight });
|
|
18607
19999
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: nextValue }] });
|
|
18608
20000
|
const appliedEl = document.querySelector(`[data-ohw-section="${CSS.escape(payload.id)}"]`);
|
|
@@ -18619,12 +20011,13 @@ function OhhwellsBridge() {
|
|
|
18619
20011
|
const exists = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
|
|
18620
20012
|
if (!exists) return;
|
|
18621
20013
|
if (isPageFrameSection(exists)) return;
|
|
20014
|
+
clearInteractionChrome();
|
|
18622
20015
|
const previous = aiSectionsRef.current;
|
|
18623
20016
|
const nextState = deleteSectionFromState(parseAiSectionsState(previous), sectionId);
|
|
18624
20017
|
const nextValue = serializeAiSectionsState(nextState);
|
|
18625
20018
|
aiSectionsRef.current = nextValue;
|
|
18626
20019
|
applyAiSectionsToDom(nextState);
|
|
18627
|
-
const newHeight = document.
|
|
20020
|
+
const newHeight = document.body.scrollHeight;
|
|
18628
20021
|
if (newHeight > 50) postToParentRef.current({ type: "ow:height", height: newHeight });
|
|
18629
20022
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: nextValue }] });
|
|
18630
20023
|
postToParentRef.current({ type: "ow:ai-section-deleted", sectionId, previous, value: nextValue });
|
|
@@ -18634,20 +20027,107 @@ function OhhwellsBridge() {
|
|
|
18634
20027
|
const handleAiSetSections = (e) => {
|
|
18635
20028
|
if (e.data?.type !== "ow:ai-set-sections") return;
|
|
18636
20029
|
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
20030
|
+
clearInteractionChrome();
|
|
18637
20031
|
aiSectionsRef.current = value;
|
|
18638
20032
|
applyAiSectionsToDom(parseAiSectionsState(value));
|
|
18639
|
-
|
|
20033
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
20034
|
+
const restoredHeight = document.body.scrollHeight;
|
|
18640
20035
|
if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
|
|
18641
20036
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
|
|
18642
20037
|
postAiSectionsChanged();
|
|
18643
20038
|
};
|
|
18644
20039
|
window.addEventListener("message", handleAiSetSections);
|
|
20040
|
+
const handleMoveSection = (e) => {
|
|
20041
|
+
if (e.data?.type !== "ow:move-section") return;
|
|
20042
|
+
const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
|
|
20043
|
+
const direction = e.data.direction === "up" || e.data.direction === "down" ? e.data.direction : null;
|
|
20044
|
+
if (!instanceId || !direction) return;
|
|
20045
|
+
const entries = moveSectionInstance(instanceId, direction, window.location.pathname);
|
|
20046
|
+
if (!entries) return;
|
|
20047
|
+
const orderJson = JSON.stringify(entries);
|
|
20048
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
20049
|
+
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20050
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20051
|
+
window.dispatchEvent(new Event("resize"));
|
|
20052
|
+
};
|
|
20053
|
+
window.addEventListener("message", handleMoveSection);
|
|
20054
|
+
const handleAiSetBrand = (e) => {
|
|
20055
|
+
if (e.data?.type !== "ow:ai-set-brand") return;
|
|
20056
|
+
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
20057
|
+
const previous = brandKitRef.current;
|
|
20058
|
+
brandKitRef.current = value;
|
|
20059
|
+
applyBrandToDom(parseBrandKit(value));
|
|
20060
|
+
if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
|
|
20061
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
20062
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
|
|
20063
|
+
postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
|
|
20064
|
+
};
|
|
20065
|
+
window.addEventListener("message", handleAiSetBrand);
|
|
20066
|
+
const handleAiSetStyles = (e) => {
|
|
20067
|
+
if (e.data?.type !== "ow:ai-set-styles") return;
|
|
20068
|
+
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
20069
|
+
const previous = stylesRef.current;
|
|
20070
|
+
stylesRef.current = value;
|
|
20071
|
+
applyStylesToDom(parseStyleStore(value));
|
|
20072
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
|
|
20073
|
+
postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
|
|
20074
|
+
};
|
|
20075
|
+
window.addEventListener("message", handleAiSetStyles);
|
|
20076
|
+
const handleGetBrand = (e) => {
|
|
20077
|
+
if (e.data?.type !== "ow:get-brand") return;
|
|
20078
|
+
const template = deriveTemplateBrand();
|
|
20079
|
+
const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
|
|
20080
|
+
postToParentRef.current({ type: "ow:brand-value", value });
|
|
20081
|
+
};
|
|
20082
|
+
window.addEventListener("message", handleGetBrand);
|
|
18645
20083
|
const handlePanelDragging = (e) => {
|
|
18646
20084
|
if (e.data?.type !== "ow:panel-dragging") return;
|
|
18647
20085
|
if (e.data.dragging) document.documentElement.setAttribute("data-ohw-panel-dragging", "");
|
|
18648
20086
|
else document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
18649
20087
|
};
|
|
18650
20088
|
window.addEventListener("message", handlePanelDragging);
|
|
20089
|
+
const handleDeleteSection = (e) => {
|
|
20090
|
+
if (e.data?.type !== "ow:delete-section") return;
|
|
20091
|
+
const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
|
|
20092
|
+
if (!instanceId) return;
|
|
20093
|
+
const currentEntries = getPageSectionOrderEntries(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname);
|
|
20094
|
+
const entries = deleteSectionInstance(instanceId, window.location.pathname, currentEntries);
|
|
20095
|
+
if (!entries) return;
|
|
20096
|
+
const orderJson = JSON.stringify(entries);
|
|
20097
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
20098
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20099
|
+
aiSectionApiRef.current?.clear();
|
|
20100
|
+
window.dispatchEvent(new Event("resize"));
|
|
20101
|
+
const deleteHeight = document.body.scrollHeight;
|
|
20102
|
+
if (deleteHeight > 50) postToParentRef.current({ type: "ow:height", height: deleteHeight });
|
|
20103
|
+
const actionId = newInstanceId();
|
|
20104
|
+
pendingDeleteUndoRef.current = {
|
|
20105
|
+
actionId,
|
|
20106
|
+
restore: () => {
|
|
20107
|
+
const restoredEntries = getPageSectionOrderEntries(
|
|
20108
|
+
editContentRef.current[SECTION_ORDER_KEY],
|
|
20109
|
+
window.location.pathname
|
|
20110
|
+
);
|
|
20111
|
+
const restored = restoreSectionInstance(instanceId, window.location.pathname, restoredEntries);
|
|
20112
|
+
if (!restored) return;
|
|
20113
|
+
const restoredJson = JSON.stringify(restored);
|
|
20114
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: restoredJson };
|
|
20115
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: restoredJson }] });
|
|
20116
|
+
window.dispatchEvent(new Event("resize"));
|
|
20117
|
+
const restoreHeight = document.body.scrollHeight;
|
|
20118
|
+
if (restoreHeight > 50) postToParentRef.current({ type: "ow:height", height: restoreHeight });
|
|
20119
|
+
}
|
|
20120
|
+
};
|
|
20121
|
+
postToParentRef.current({
|
|
20122
|
+
type: "ow:toast",
|
|
20123
|
+
title: "Section deleted",
|
|
20124
|
+
toastType: "success",
|
|
20125
|
+
actionLabel: "Undo",
|
|
20126
|
+
actionId,
|
|
20127
|
+
duration: 6e3
|
|
20128
|
+
});
|
|
20129
|
+
};
|
|
20130
|
+
window.addEventListener("message", handleDeleteSection);
|
|
18651
20131
|
const handleDeactivate = (e) => {
|
|
18652
20132
|
if (e.data?.type !== "ow:deactivate") return;
|
|
18653
20133
|
if (document.documentElement.hasAttribute("data-ohw-panel-dragging")) return;
|
|
@@ -18657,8 +20137,15 @@ function OhhwellsBridge() {
|
|
|
18657
20137
|
closeLinkPopoverRef.current();
|
|
18658
20138
|
return;
|
|
18659
20139
|
}
|
|
20140
|
+
if (floatingPanelOpenRef.current) {
|
|
20141
|
+
setFloatingPanelRef.current(null);
|
|
20142
|
+
deselectRef.current();
|
|
20143
|
+
deactivateRef.current();
|
|
20144
|
+
return;
|
|
20145
|
+
}
|
|
18660
20146
|
deselectRef.current();
|
|
18661
20147
|
deactivateRef.current();
|
|
20148
|
+
clearMediaSelectionRef.current();
|
|
18662
20149
|
};
|
|
18663
20150
|
window.addEventListener("message", handleDeactivate);
|
|
18664
20151
|
const handleToastAction = (e) => {
|
|
@@ -18744,6 +20231,10 @@ function OhhwellsBridge() {
|
|
|
18744
20231
|
const handleKeyDown = (e) => {
|
|
18745
20232
|
if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
|
|
18746
20233
|
if (e.key === "Escape" && document.querySelector("[data-ohw-more-menu]")) return;
|
|
20234
|
+
if (e.key === "Escape" && selectedMediaElRef.current) {
|
|
20235
|
+
clearMediaSelectionRef.current();
|
|
20236
|
+
return;
|
|
20237
|
+
}
|
|
18747
20238
|
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
|
|
18748
20239
|
e.preventDefault();
|
|
18749
20240
|
selectAllTextInEditable(activeElRef.current);
|
|
@@ -18903,6 +20394,12 @@ function OhhwellsBridge() {
|
|
|
18903
20394
|
if (aiSectionsRef.current) {
|
|
18904
20395
|
nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
|
|
18905
20396
|
}
|
|
20397
|
+
if (stylesRef.current) {
|
|
20398
|
+
nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
|
|
20399
|
+
}
|
|
20400
|
+
if (brandKitRef.current) {
|
|
20401
|
+
nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
|
|
20402
|
+
}
|
|
18906
20403
|
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
18907
20404
|
const formKey = formKeyOf(form);
|
|
18908
20405
|
if (!formKey) return;
|
|
@@ -18920,8 +20417,12 @@ function OhhwellsBridge() {
|
|
|
18920
20417
|
if (inserted) {
|
|
18921
20418
|
const tracker = getSectionsTracker();
|
|
18922
20419
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
18923
|
-
const
|
|
18924
|
-
|
|
20420
|
+
const reportHeight = () => {
|
|
20421
|
+
const h = document.body.scrollHeight;
|
|
20422
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
20423
|
+
};
|
|
20424
|
+
reportHeight();
|
|
20425
|
+
setTimeout(reportHeight, 500);
|
|
18925
20426
|
}
|
|
18926
20427
|
};
|
|
18927
20428
|
const handleSwitchSchedule = (e) => {
|
|
@@ -18962,7 +20463,7 @@ function OhhwellsBridge() {
|
|
|
18962
20463
|
const updated = sections.filter((s) => !(s.type === "scheduling" && s.pagePath === currentPath));
|
|
18963
20464
|
tracker.textContent = JSON.stringify(updated);
|
|
18964
20465
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent }] });
|
|
18965
|
-
const h = document.
|
|
20466
|
+
const h = document.body.scrollHeight;
|
|
18966
20467
|
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
18967
20468
|
};
|
|
18968
20469
|
const handleCollectSection = (e) => {
|
|
@@ -19317,19 +20818,24 @@ function OhhwellsBridge() {
|
|
|
19317
20818
|
window.removeEventListener("message", handleAiApplyTree);
|
|
19318
20819
|
window.removeEventListener("message", handleAiDeleteSection);
|
|
19319
20820
|
window.removeEventListener("message", handleAiSetSections);
|
|
20821
|
+
window.removeEventListener("message", handleMoveSection);
|
|
20822
|
+
window.removeEventListener("message", handleAiSetBrand);
|
|
20823
|
+
window.removeEventListener("message", handleAiSetStyles);
|
|
20824
|
+
window.removeEventListener("message", handleGetBrand);
|
|
19320
20825
|
window.removeEventListener("message", handlePanelDragging);
|
|
20826
|
+
window.removeEventListener("message", handleDeleteSection);
|
|
19321
20827
|
window.removeEventListener("message", handleDeactivate);
|
|
19322
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
19323
20828
|
window.removeEventListener("message", handleToastAction);
|
|
19324
20829
|
window.removeEventListener("message", handleFormCount);
|
|
19325
20830
|
window.removeEventListener("message", handleUiEscape);
|
|
20831
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
19326
20832
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
19327
20833
|
autoSaveTimers.current.clear();
|
|
19328
20834
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
19329
20835
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
19330
20836
|
};
|
|
19331
20837
|
}, [isEditMode, refreshStateRules]);
|
|
19332
|
-
|
|
20838
|
+
useEffect13(() => {
|
|
19333
20839
|
if (!isEditMode) return;
|
|
19334
20840
|
const THRESHOLD = 10;
|
|
19335
20841
|
const resolveWasSelected = (el) => {
|
|
@@ -19485,7 +20991,7 @@ function OhhwellsBridge() {
|
|
|
19485
20991
|
unlockFooterDragInteraction();
|
|
19486
20992
|
};
|
|
19487
20993
|
}, [isEditMode]);
|
|
19488
|
-
|
|
20994
|
+
useEffect13(() => {
|
|
19489
20995
|
const handler = (e) => {
|
|
19490
20996
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
19491
20997
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -19501,7 +21007,7 @@ function OhhwellsBridge() {
|
|
|
19501
21007
|
window.addEventListener("message", handler);
|
|
19502
21008
|
return () => window.removeEventListener("message", handler);
|
|
19503
21009
|
}, [processConfigRequest]);
|
|
19504
|
-
|
|
21010
|
+
useEffect13(() => {
|
|
19505
21011
|
if (!isEditMode) return;
|
|
19506
21012
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
19507
21013
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -19525,7 +21031,7 @@ function OhhwellsBridge() {
|
|
|
19525
21031
|
postToParent2({
|
|
19526
21032
|
type: "ow:ready",
|
|
19527
21033
|
version: "1",
|
|
19528
|
-
bridgeVersion: "0.1.
|
|
21034
|
+
bridgeVersion: "0.1.73",
|
|
19529
21035
|
path: pathname,
|
|
19530
21036
|
nodes: collectEditableNodes(editContentRef.current),
|
|
19531
21037
|
sections
|
|
@@ -19537,13 +21043,13 @@ function OhhwellsBridge() {
|
|
|
19537
21043
|
clearTimeout(timer);
|
|
19538
21044
|
};
|
|
19539
21045
|
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
19540
|
-
|
|
21046
|
+
useEffect13(() => {
|
|
19541
21047
|
scrollToHashSectionWhenReady();
|
|
19542
21048
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
19543
21049
|
window.addEventListener("hashchange", onHashChange);
|
|
19544
21050
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
19545
21051
|
}, [pathname]);
|
|
19546
|
-
const handleCommand =
|
|
21052
|
+
const handleCommand = useCallback8((cmd) => {
|
|
19547
21053
|
const el = activeElRef.current;
|
|
19548
21054
|
const selBefore = window.getSelection();
|
|
19549
21055
|
let savedOffsets = null;
|
|
@@ -19579,7 +21085,7 @@ function OhhwellsBridge() {
|
|
|
19579
21085
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
19580
21086
|
refreshActiveCommandsRef.current();
|
|
19581
21087
|
}, []);
|
|
19582
|
-
|
|
21088
|
+
useEffect13(() => {
|
|
19583
21089
|
const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
|
|
19584
21090
|
if (!session || !logoSizeDraft) return;
|
|
19585
21091
|
const onPanelAction = (e) => {
|
|
@@ -19617,7 +21123,7 @@ function OhhwellsBridge() {
|
|
|
19617
21123
|
window.addEventListener("message", onPanelAction);
|
|
19618
21124
|
return () => window.removeEventListener("message", onPanelAction);
|
|
19619
21125
|
}, [floatingPanel, logoSizeDraft, editorViewport, persistLogoSizeDraft, closeFloatingPanelAndDeselect]);
|
|
19620
|
-
const handleStateChange =
|
|
21126
|
+
const handleStateChange = useCallback8((state) => {
|
|
19621
21127
|
if (!activeStateElRef.current) return;
|
|
19622
21128
|
const el = activeStateElRef.current;
|
|
19623
21129
|
if (state === "Default") {
|
|
@@ -19630,7 +21136,7 @@ function OhhwellsBridge() {
|
|
|
19630
21136
|
}
|
|
19631
21137
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
19632
21138
|
}, [deactivate]);
|
|
19633
|
-
const reselectAfterLinkPopover =
|
|
21139
|
+
const reselectAfterLinkPopover = useCallback8(
|
|
19634
21140
|
(hrefKey) => {
|
|
19635
21141
|
requestAnimationFrame(() => {
|
|
19636
21142
|
const el = resolveHrefKeyElement(hrefKey);
|
|
@@ -19639,7 +21145,7 @@ function OhhwellsBridge() {
|
|
|
19639
21145
|
},
|
|
19640
21146
|
[resolveHrefKeyElement]
|
|
19641
21147
|
);
|
|
19642
|
-
const closeLinkPopover =
|
|
21148
|
+
const closeLinkPopover = useCallback8(() => {
|
|
19643
21149
|
const session = linkPopoverSessionRef.current;
|
|
19644
21150
|
addNavAfterAnchorRef.current = null;
|
|
19645
21151
|
setLinkPopover(null);
|
|
@@ -19647,9 +21153,9 @@ function OhhwellsBridge() {
|
|
|
19647
21153
|
reselectAfterLinkPopover(session.key);
|
|
19648
21154
|
}
|
|
19649
21155
|
}, [reselectAfterLinkPopover]);
|
|
19650
|
-
const closeLinkPopoverRef =
|
|
21156
|
+
const closeLinkPopoverRef = useRef10(closeLinkPopover);
|
|
19651
21157
|
closeLinkPopoverRef.current = closeLinkPopover;
|
|
19652
|
-
const openLinkPopoverForActive =
|
|
21158
|
+
const openLinkPopoverForActive = useCallback8(() => {
|
|
19653
21159
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
19654
21160
|
if (!hrefCtx) return;
|
|
19655
21161
|
bumpLinkPopoverGrace();
|
|
@@ -19660,7 +21166,7 @@ function OhhwellsBridge() {
|
|
|
19660
21166
|
});
|
|
19661
21167
|
deactivate();
|
|
19662
21168
|
}, [deactivate]);
|
|
19663
|
-
const openLinkPopoverForSelected =
|
|
21169
|
+
const openLinkPopoverForSelected = useCallback8(() => {
|
|
19664
21170
|
const anchor = selectedElRef.current;
|
|
19665
21171
|
if (!anchor) return;
|
|
19666
21172
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -19677,7 +21183,7 @@ function OhhwellsBridge() {
|
|
|
19677
21183
|
});
|
|
19678
21184
|
deselect();
|
|
19679
21185
|
}, [deselect]);
|
|
19680
|
-
const handleSelectParent =
|
|
21186
|
+
const handleSelectParent = useCallback8(() => {
|
|
19681
21187
|
const selected = selectedElRef.current;
|
|
19682
21188
|
if (!selected) return;
|
|
19683
21189
|
if (toolbarVariantRef.current === "select-frame") {
|
|
@@ -19704,7 +21210,7 @@ function OhhwellsBridge() {
|
|
|
19704
21210
|
}
|
|
19705
21211
|
deselectRef.current();
|
|
19706
21212
|
}, []);
|
|
19707
|
-
const handleDuplicateSelected =
|
|
21213
|
+
const handleDuplicateSelected = useCallback8(() => {
|
|
19708
21214
|
const selected = selectedElRef.current;
|
|
19709
21215
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
19710
21216
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
@@ -19837,7 +21343,7 @@ function OhhwellsBridge() {
|
|
|
19837
21343
|
});
|
|
19838
21344
|
}
|
|
19839
21345
|
}, [postToParent2]);
|
|
19840
|
-
const runPendingDeleteUndo =
|
|
21346
|
+
const runPendingDeleteUndo = useCallback8(() => {
|
|
19841
21347
|
const pending = pendingDeleteUndoRef.current;
|
|
19842
21348
|
if (!pending) return false;
|
|
19843
21349
|
pendingDeleteUndoRef.current = null;
|
|
@@ -19845,7 +21351,7 @@ function OhhwellsBridge() {
|
|
|
19845
21351
|
enforceLinkHrefs();
|
|
19846
21352
|
return true;
|
|
19847
21353
|
}, []);
|
|
19848
|
-
const handleDeleteSelected =
|
|
21354
|
+
const handleDeleteSelected = useCallback8(() => {
|
|
19849
21355
|
const selected = selectedElRef.current;
|
|
19850
21356
|
if (!selected) return false;
|
|
19851
21357
|
return deleteSelectedNavFooterItem({
|
|
@@ -19866,7 +21372,7 @@ function OhhwellsBridge() {
|
|
|
19866
21372
|
}, [postToParent2]);
|
|
19867
21373
|
handleDeleteSelectedRef.current = handleDeleteSelected;
|
|
19868
21374
|
runPendingDeleteUndoRef.current = runPendingDeleteUndo;
|
|
19869
|
-
const handleLinkPopoverSubmit =
|
|
21375
|
+
const handleLinkPopoverSubmit = useCallback8(
|
|
19870
21376
|
(target) => {
|
|
19871
21377
|
const session = linkPopoverSessionRef.current;
|
|
19872
21378
|
if (!session) return;
|
|
@@ -19932,19 +21438,30 @@ function OhhwellsBridge() {
|
|
|
19932
21438
|
const showEditLink = toolbarShowEditLink;
|
|
19933
21439
|
const currentSections = sectionsByPath[pathname] ?? [];
|
|
19934
21440
|
linkPopoverOpenRef.current = linkPopover !== null;
|
|
19935
|
-
const
|
|
21441
|
+
const handleMediaSelect = useCallback8((key) => {
|
|
21442
|
+
const el = hoveredImageRef.current?.dataset.ohwKey === key ? hoveredImageRef.current : Array.from(document.querySelectorAll(MEDIA_SELECTOR)).find(
|
|
21443
|
+
(m) => (m.dataset.ohwKey ?? "") === key
|
|
21444
|
+
) ?? null;
|
|
21445
|
+
if (!el) return;
|
|
21446
|
+
selectMediaElementRef.current(el);
|
|
21447
|
+
}, []);
|
|
21448
|
+
const handleMediaReplace = useCallback8(
|
|
19936
21449
|
(key) => {
|
|
19937
|
-
postToParent2({
|
|
21450
|
+
postToParent2({
|
|
21451
|
+
type: "ow:image-pick",
|
|
21452
|
+
key,
|
|
21453
|
+
elementType: mediaHover?.elementType ?? selectedMedia?.elementType ?? "image"
|
|
21454
|
+
});
|
|
19938
21455
|
},
|
|
19939
|
-
[postToParent2, mediaHover?.elementType]
|
|
21456
|
+
[postToParent2, mediaHover?.elementType, selectedMedia?.elementType]
|
|
19940
21457
|
);
|
|
19941
|
-
const handleEditCarousel =
|
|
21458
|
+
const handleEditCarousel = useCallback8(
|
|
19942
21459
|
(key) => {
|
|
19943
21460
|
postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
|
|
19944
21461
|
},
|
|
19945
21462
|
[postToParent2]
|
|
19946
21463
|
);
|
|
19947
|
-
const handleMediaFadeOutComplete =
|
|
21464
|
+
const handleMediaFadeOutComplete = useCallback8((key) => {
|
|
19948
21465
|
setUploadingRects((prev) => {
|
|
19949
21466
|
if (!(key in prev)) return prev;
|
|
19950
21467
|
const next = { ...prev };
|
|
@@ -19952,7 +21469,7 @@ function OhhwellsBridge() {
|
|
|
19952
21469
|
return next;
|
|
19953
21470
|
});
|
|
19954
21471
|
}, []);
|
|
19955
|
-
const handleVideoSettingsChange =
|
|
21472
|
+
const handleVideoSettingsChange = useCallback8(
|
|
19956
21473
|
(key, settings) => {
|
|
19957
21474
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
19958
21475
|
const video = getVideoEl2(el);
|
|
@@ -19974,430 +21491,516 @@ function OhhwellsBridge() {
|
|
|
19974
21491
|
},
|
|
19975
21492
|
[postToParent2]
|
|
19976
21493
|
);
|
|
19977
|
-
return
|
|
19978
|
-
/* @__PURE__ */
|
|
19979
|
-
|
|
19980
|
-
|
|
19981
|
-
|
|
19982
|
-
|
|
19983
|
-
{
|
|
19984
|
-
|
|
19985
|
-
|
|
19986
|
-
|
|
19987
|
-
|
|
19988
|
-
|
|
19989
|
-
|
|
19990
|
-
|
|
19991
|
-
|
|
19992
|
-
|
|
19993
|
-
|
|
19994
|
-
|
|
19995
|
-
|
|
19996
|
-
|
|
19997
|
-
onReplace: handleMediaReplace,
|
|
19998
|
-
onVideoSettingsChange: handleVideoSettingsChange
|
|
19999
|
-
}
|
|
20000
|
-
),
|
|
20001
|
-
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
|
|
20002
|
-
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
20003
|
-
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
20004
|
-
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
20005
|
-
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
20006
|
-
"div",
|
|
20007
|
-
{
|
|
20008
|
-
className: "pointer-events-none fixed z-2147483646",
|
|
20009
|
-
style: {
|
|
20010
|
-
left: slot.left,
|
|
20011
|
-
top: slot.top,
|
|
20012
|
-
width: slot.width,
|
|
20013
|
-
height: slot.height
|
|
21494
|
+
return /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
21495
|
+
/* @__PURE__ */ jsx33("div", { id: "ohw-loader", suppressHydrationWarning: true, style: { ...OHW_LOADER_STYLE, display: "none" }, children: /* @__PURE__ */ jsx33(OhwLoaderSpinner, {}) }),
|
|
21496
|
+
/* @__PURE__ */ jsx33("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: OHW_LOADER_PREHYDRATE_SCRIPT } }),
|
|
21497
|
+
bridgeRoot ? createPortal2(
|
|
21498
|
+
/* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
21499
|
+
/* @__PURE__ */ jsx33("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
21500
|
+
isEditMode && /* @__PURE__ */ jsx33(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
|
|
21501
|
+
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
21502
|
+
"div",
|
|
21503
|
+
{
|
|
21504
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
21505
|
+
style: { left: slot.left, top: slot.y, width: slot.width, height: 3, transform: "translateY(-50%)" },
|
|
21506
|
+
children: /* @__PURE__ */ jsx33(
|
|
21507
|
+
DropIndicator,
|
|
21508
|
+
{
|
|
21509
|
+
direction: "horizontal",
|
|
21510
|
+
state: activeSectionDropIndex === i ? "dragActive" : "dragIdle",
|
|
21511
|
+
className: "!h-full !w-full"
|
|
21512
|
+
}
|
|
21513
|
+
)
|
|
20014
21514
|
},
|
|
20015
|
-
|
|
20016
|
-
|
|
20017
|
-
|
|
20018
|
-
|
|
20019
|
-
|
|
20020
|
-
|
|
20021
|
-
|
|
20022
|
-
|
|
20023
|
-
|
|
20024
|
-
|
|
20025
|
-
)),
|
|
20026
|
-
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
20027
|
-
"div",
|
|
20028
|
-
{
|
|
20029
|
-
className: "pointer-events-none fixed z-2147483646",
|
|
20030
|
-
style: {
|
|
20031
|
-
left: slot.left,
|
|
20032
|
-
top: slot.top,
|
|
20033
|
-
width: slot.width,
|
|
20034
|
-
height: slot.height
|
|
21515
|
+
`section-drop-${slot.insertIndex}-${i}`
|
|
21516
|
+
)),
|
|
21517
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx33(
|
|
21518
|
+
MediaOverlay,
|
|
21519
|
+
{
|
|
21520
|
+
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
21521
|
+
isUploading: true,
|
|
21522
|
+
fadingOut,
|
|
21523
|
+
onFadeOutComplete: handleMediaFadeOutComplete,
|
|
21524
|
+
onReplace: handleMediaReplace
|
|
20035
21525
|
},
|
|
20036
|
-
|
|
20037
|
-
|
|
20038
|
-
|
|
20039
|
-
|
|
20040
|
-
|
|
20041
|
-
|
|
20042
|
-
|
|
20043
|
-
|
|
20044
|
-
|
|
20045
|
-
|
|
20046
|
-
|
|
20047
|
-
|
|
20048
|
-
|
|
20049
|
-
|
|
20050
|
-
|
|
20051
|
-
|
|
20052
|
-
|
|
20053
|
-
|
|
20054
|
-
|
|
20055
|
-
|
|
20056
|
-
|
|
20057
|
-
|
|
20058
|
-
|
|
21526
|
+
`uploading-${key}`
|
|
21527
|
+
)),
|
|
21528
|
+
mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */ jsx33(
|
|
21529
|
+
MediaOverlay,
|
|
21530
|
+
{
|
|
21531
|
+
hover: mediaHover,
|
|
21532
|
+
isUploading: false,
|
|
21533
|
+
onReplace: handleMediaReplace,
|
|
21534
|
+
onSelect: handleMediaSelect,
|
|
21535
|
+
onVideoSettingsChange: handleVideoSettingsChange
|
|
21536
|
+
}
|
|
21537
|
+
),
|
|
21538
|
+
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ jsx33(
|
|
21539
|
+
MediaOverlay,
|
|
21540
|
+
{
|
|
21541
|
+
hover: selectedMedia,
|
|
21542
|
+
selected: true,
|
|
21543
|
+
hovered: mediaHover?.key === selectedMedia.key,
|
|
21544
|
+
isUploading: false,
|
|
21545
|
+
onReplace: handleMediaReplace,
|
|
21546
|
+
onSelect: handleMediaSelect,
|
|
21547
|
+
onVideoSettingsChange: handleVideoSettingsChange
|
|
21548
|
+
}
|
|
21549
|
+
),
|
|
21550
|
+
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
|
|
21551
|
+
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
21552
|
+
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
21553
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
21554
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
21555
|
+
"div",
|
|
21556
|
+
{
|
|
21557
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
21558
|
+
style: {
|
|
21559
|
+
left: slot.left,
|
|
21560
|
+
top: slot.top,
|
|
21561
|
+
width: slot.width,
|
|
21562
|
+
height: slot.height
|
|
21563
|
+
},
|
|
21564
|
+
children: /* @__PURE__ */ jsx33(
|
|
21565
|
+
DropIndicator,
|
|
21566
|
+
{
|
|
21567
|
+
direction: slot.direction,
|
|
21568
|
+
state: activeFooterDropIndex === i ? "dragActive" : "dragIdle",
|
|
21569
|
+
className: "!h-full !w-full"
|
|
21570
|
+
}
|
|
21571
|
+
)
|
|
21572
|
+
},
|
|
21573
|
+
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
21574
|
+
)),
|
|
21575
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
21576
|
+
"div",
|
|
21577
|
+
{
|
|
21578
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
21579
|
+
style: {
|
|
21580
|
+
left: slot.left,
|
|
21581
|
+
top: slot.top,
|
|
21582
|
+
width: slot.width,
|
|
21583
|
+
height: slot.height
|
|
21584
|
+
},
|
|
21585
|
+
children: /* @__PURE__ */ jsx33(
|
|
21586
|
+
DropIndicator,
|
|
21587
|
+
{
|
|
21588
|
+
direction: slot.direction,
|
|
21589
|
+
state: activeNavDropIndex === i ? "dragActive" : "dragIdle",
|
|
21590
|
+
className: "!h-full !w-full"
|
|
21591
|
+
}
|
|
21592
|
+
)
|
|
21593
|
+
},
|
|
21594
|
+
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
21595
|
+
)),
|
|
21596
|
+
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
21597
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
21598
|
+
hoveredTextRect && !hoveredNavContainerRect && !hoveredItemRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
|
|
21599
|
+
formPickRect && !isItemDragging && /* @__PURE__ */ jsx33(
|
|
21600
|
+
ItemInteractionLayer,
|
|
21601
|
+
{
|
|
21602
|
+
rect: formPickRect,
|
|
21603
|
+
state: "active-top",
|
|
21604
|
+
itemDragSurface: false,
|
|
21605
|
+
toolbarAlign: "left",
|
|
21606
|
+
chromeGap: 24,
|
|
21607
|
+
toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ jsxs20(
|
|
21608
|
+
"div",
|
|
21609
|
+
{
|
|
21610
|
+
"data-ohw-form-toolbar": "",
|
|
21611
|
+
className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
|
|
21612
|
+
children: [
|
|
21613
|
+
/* @__PURE__ */ jsx33(
|
|
21614
|
+
"button",
|
|
21615
|
+
{
|
|
21616
|
+
type: "button",
|
|
21617
|
+
"aria-label": "Add field",
|
|
21618
|
+
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
21619
|
+
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
21620
|
+
"data-ohw-add-field": "",
|
|
21621
|
+
children: /* @__PURE__ */ jsx33(Plus4, { size: 15, "aria-hidden": true })
|
|
21622
|
+
}
|
|
21623
|
+
),
|
|
21624
|
+
/* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
21625
|
+
/* @__PURE__ */ jsxs20(
|
|
21626
|
+
"button",
|
|
21627
|
+
{
|
|
21628
|
+
type: "button",
|
|
21629
|
+
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",
|
|
21630
|
+
onClick: () => {
|
|
21631
|
+
setFieldTypePickerOpen(false);
|
|
21632
|
+
const form = formPickElRef.current;
|
|
21633
|
+
if (!form) return;
|
|
21634
|
+
postToParent2({
|
|
21635
|
+
type: "ow:form-pick",
|
|
21636
|
+
formKey: formKeyOf(form),
|
|
21637
|
+
hasLongText: formHasLongText(form)
|
|
21638
|
+
});
|
|
21639
|
+
},
|
|
21640
|
+
children: [
|
|
21641
|
+
/* @__PURE__ */ jsx33(Settings, { size: 14, "aria-hidden": true }),
|
|
21642
|
+
"Form settings",
|
|
21643
|
+
formPickCount ? (
|
|
21644
|
+
// Counter pill, per the design — not a text suffix.
|
|
21645
|
+
/* @__PURE__ */ jsx33(
|
|
21646
|
+
"span",
|
|
21647
|
+
{
|
|
21648
|
+
"data-ohw-form-count": "",
|
|
21649
|
+
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",
|
|
21650
|
+
children: formPickCount
|
|
21651
|
+
}
|
|
21652
|
+
)
|
|
21653
|
+
) : null
|
|
21654
|
+
]
|
|
21655
|
+
}
|
|
21656
|
+
),
|
|
21657
|
+
/* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
21658
|
+
/* @__PURE__ */ jsx33("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ jsx33(
|
|
21659
|
+
"button",
|
|
21660
|
+
{
|
|
21661
|
+
type: "button",
|
|
21662
|
+
"aria-pressed": formViewState === state,
|
|
21663
|
+
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"),
|
|
21664
|
+
onClick: () => {
|
|
21665
|
+
setFieldTypePickerOpen(false);
|
|
21666
|
+
const form = formPickElRef.current;
|
|
21667
|
+
const key = form ? formKeyOf(form) : null;
|
|
21668
|
+
if (!form || !key) return;
|
|
21669
|
+
const initial = successInitialFor(form, key, editContentRef.current);
|
|
21670
|
+
setFormViewState(form, key, state, initial);
|
|
21671
|
+
setFormViewStateUi(state);
|
|
21672
|
+
setFormPickRect(form.getBoundingClientRect());
|
|
21673
|
+
if (state === "success") {
|
|
21674
|
+
const successEl = form.querySelector(`[${SUCCESS_TEXT_ATTR}]`);
|
|
21675
|
+
if (successEl) requestAnimationFrame(() => activateRef.current(successEl));
|
|
21676
|
+
} else {
|
|
21677
|
+
deactivateRef.current();
|
|
21678
|
+
}
|
|
21679
|
+
},
|
|
21680
|
+
children: state
|
|
21681
|
+
},
|
|
21682
|
+
state
|
|
21683
|
+
)) })
|
|
21684
|
+
]
|
|
21685
|
+
}
|
|
21686
|
+
)
|
|
21687
|
+
}
|
|
21688
|
+
),
|
|
21689
|
+
formHoverRect && !isItemDragging && /* @__PURE__ */ jsx33(
|
|
21690
|
+
ItemInteractionLayer,
|
|
21691
|
+
{
|
|
21692
|
+
rect: formHoverRect,
|
|
21693
|
+
state: "hover",
|
|
21694
|
+
chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
|
|
21695
|
+
}
|
|
21696
|
+
),
|
|
21697
|
+
fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx33(
|
|
21698
|
+
ItemInteractionLayer,
|
|
21699
|
+
{
|
|
21700
|
+
rect: fieldPickRect,
|
|
21701
|
+
state: fieldDragging ? "dragging" : "active-top",
|
|
21702
|
+
itemDragSurface: false,
|
|
21703
|
+
toolbarAlign: "left",
|
|
21704
|
+
chromeGap: 10,
|
|
21705
|
+
showHandle: true,
|
|
21706
|
+
dragHandleLabel: "Reorder field",
|
|
21707
|
+
onDragHandleDragStart: handleFieldDragStart,
|
|
21708
|
+
onDragHandleDragEnd: handleFieldDragEnd,
|
|
21709
|
+
toolbar: /* @__PURE__ */ jsx33(
|
|
21710
|
+
FormFieldToolbar,
|
|
21711
|
+
{
|
|
21712
|
+
type: fieldPickState.type,
|
|
21713
|
+
required: fieldPickState.required,
|
|
21714
|
+
onTypeChange: handleFieldTypeChange,
|
|
21715
|
+
onRequiredToggle: handleFieldRequiredToggle,
|
|
21716
|
+
onDuplicate: handleFieldDuplicate,
|
|
21717
|
+
onDelete: handleFieldDelete
|
|
21718
|
+
}
|
|
21719
|
+
)
|
|
21720
|
+
}
|
|
21721
|
+
),
|
|
21722
|
+
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
21723
|
+
"div",
|
|
21724
|
+
{
|
|
21725
|
+
className: "pointer-events-none fixed z-[2147483644]",
|
|
21726
|
+
style: { top: slot.top, left: slot.left, width: slot.width },
|
|
21727
|
+
children: /* @__PURE__ */ jsx33(
|
|
21728
|
+
DropIndicator,
|
|
21729
|
+
{
|
|
21730
|
+
direction: "horizontal",
|
|
21731
|
+
state: fieldDropIndex === i ? "dragActive" : "dragIdle",
|
|
21732
|
+
className: "!w-full"
|
|
21733
|
+
}
|
|
21734
|
+
)
|
|
21735
|
+
},
|
|
21736
|
+
`field-drop-${i}`
|
|
21737
|
+
)) : null,
|
|
21738
|
+
fieldTypePickerOpen && formPickRect ? (() => {
|
|
21739
|
+
const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
|
|
21740
|
+
return /* @__PURE__ */ jsx33(
|
|
20059
21741
|
"div",
|
|
20060
21742
|
{
|
|
20061
|
-
"
|
|
20062
|
-
|
|
20063
|
-
|
|
20064
|
-
|
|
20065
|
-
|
|
20066
|
-
|
|
20067
|
-
type: "button",
|
|
20068
|
-
"aria-label": "Add field",
|
|
20069
|
-
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
20070
|
-
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
20071
|
-
"data-ohw-add-field": "",
|
|
20072
|
-
children: /* @__PURE__ */ jsx33(Plus4, { size: 15, "aria-hidden": true })
|
|
20073
|
-
}
|
|
20074
|
-
),
|
|
20075
|
-
/* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
20076
|
-
/* @__PURE__ */ jsxs20(
|
|
20077
|
-
"button",
|
|
20078
|
-
{
|
|
20079
|
-
type: "button",
|
|
20080
|
-
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",
|
|
20081
|
-
onClick: () => {
|
|
20082
|
-
setFieldTypePickerOpen(false);
|
|
20083
|
-
const form = formPickElRef.current;
|
|
20084
|
-
if (!form) return;
|
|
20085
|
-
postToParent2({
|
|
20086
|
-
type: "ow:form-pick",
|
|
20087
|
-
formKey: formKeyOf(form),
|
|
20088
|
-
hasLongText: formHasLongText(form)
|
|
20089
|
-
});
|
|
20090
|
-
},
|
|
20091
|
-
children: [
|
|
20092
|
-
/* @__PURE__ */ jsx33(Settings, { size: 14, "aria-hidden": true }),
|
|
20093
|
-
"Form settings",
|
|
20094
|
-
formPickCount ? (
|
|
20095
|
-
// Counter pill, per the design — not a text suffix.
|
|
20096
|
-
/* @__PURE__ */ jsx33(
|
|
20097
|
-
"span",
|
|
20098
|
-
{
|
|
20099
|
-
"data-ohw-form-count": "",
|
|
20100
|
-
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",
|
|
20101
|
-
children: formPickCount
|
|
20102
|
-
}
|
|
20103
|
-
)
|
|
20104
|
-
) : null
|
|
20105
|
-
]
|
|
20106
|
-
}
|
|
20107
|
-
),
|
|
20108
|
-
/* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
20109
|
-
/* @__PURE__ */ jsx33("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ jsx33(
|
|
20110
|
-
"button",
|
|
20111
|
-
{
|
|
20112
|
-
type: "button",
|
|
20113
|
-
"aria-pressed": formViewState === state,
|
|
20114
|
-
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"),
|
|
20115
|
-
onClick: () => {
|
|
20116
|
-
setFieldTypePickerOpen(false);
|
|
20117
|
-
const form = formPickElRef.current;
|
|
20118
|
-
const key = form ? formKeyOf(form) : null;
|
|
20119
|
-
if (!form || !key) return;
|
|
20120
|
-
const initial = successInitialFor(form, key, editContentRef.current);
|
|
20121
|
-
setFormViewState(form, key, state, initial);
|
|
20122
|
-
setFormViewStateUi(state);
|
|
20123
|
-
setFormPickRect(form.getBoundingClientRect());
|
|
20124
|
-
if (state === "success") {
|
|
20125
|
-
const successEl = form.querySelector(`[${SUCCESS_TEXT_ATTR}]`);
|
|
20126
|
-
if (successEl) requestAnimationFrame(() => activateRef.current(successEl));
|
|
20127
|
-
} else {
|
|
20128
|
-
deactivateRef.current();
|
|
20129
|
-
}
|
|
20130
|
-
},
|
|
20131
|
-
children: state
|
|
20132
|
-
},
|
|
20133
|
-
state
|
|
20134
|
-
)) })
|
|
20135
|
-
]
|
|
21743
|
+
className: "pointer-events-none fixed z-[2147483645]",
|
|
21744
|
+
style: {
|
|
21745
|
+
top: toolbar ? toolbar.bottom + 6 : formPickRect.top + 16,
|
|
21746
|
+
left: toolbar ? toolbar.left : formPickRect.left + 24
|
|
21747
|
+
},
|
|
21748
|
+
children: /* @__PURE__ */ jsx33(FieldTypePicker, { onPick: handleAddField })
|
|
20136
21749
|
}
|
|
20137
|
-
)
|
|
20138
|
-
}
|
|
20139
|
-
|
|
20140
|
-
|
|
20141
|
-
|
|
20142
|
-
|
|
20143
|
-
|
|
20144
|
-
|
|
20145
|
-
|
|
20146
|
-
|
|
20147
|
-
|
|
20148
|
-
|
|
20149
|
-
|
|
20150
|
-
|
|
20151
|
-
|
|
20152
|
-
|
|
20153
|
-
|
|
20154
|
-
|
|
20155
|
-
|
|
20156
|
-
|
|
20157
|
-
|
|
20158
|
-
|
|
20159
|
-
|
|
20160
|
-
|
|
20161
|
-
|
|
21750
|
+
);
|
|
21751
|
+
})() : null,
|
|
21752
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ jsx33(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
21753
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx33(
|
|
21754
|
+
FooterContainerChrome,
|
|
21755
|
+
{
|
|
21756
|
+
rect: toolbarRect,
|
|
21757
|
+
onAdd: handleAddFooterColumn,
|
|
21758
|
+
addDisabled: !canAddFooterColumn()
|
|
21759
|
+
}
|
|
21760
|
+
),
|
|
21761
|
+
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ jsx33(
|
|
21762
|
+
ItemInteractionLayer,
|
|
21763
|
+
{
|
|
21764
|
+
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
21765
|
+
toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
|
|
21766
|
+
elRef: glowElRef,
|
|
21767
|
+
state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanelRect(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
21768
|
+
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
21769
|
+
dragDisabled: reorderDragDisabled,
|
|
21770
|
+
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
21771
|
+
onDragHandleDragStart: handleItemDragStart,
|
|
21772
|
+
onDragHandleDragEnd: handleItemDragEnd,
|
|
21773
|
+
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
21774
|
+
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
21775
|
+
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection && !selectedIsSocialsRow,
|
|
21776
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ jsx33(
|
|
21777
|
+
ItemActionToolbar,
|
|
21778
|
+
{
|
|
21779
|
+
onEditLink: openLinkPopoverForSelected,
|
|
21780
|
+
onStyle: () => {
|
|
21781
|
+
const row = selectedElRef.current;
|
|
21782
|
+
if (!row) return;
|
|
21783
|
+
if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
|
|
21784
|
+
else openSocialsDisplayPanel(row);
|
|
21785
|
+
},
|
|
21786
|
+
showStyle: selectedIsSocialsRow,
|
|
21787
|
+
styleActive: floatingPanel?.kind === "socials-display",
|
|
21788
|
+
onAddItem: handleAddChildItem,
|
|
21789
|
+
onSelectParent: handleSelectParent,
|
|
21790
|
+
onDuplicate: handleDuplicateSelected,
|
|
21791
|
+
onDelete: handleDeleteSelected,
|
|
21792
|
+
addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
21793
|
+
const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
|
|
21794
|
+
return row ? !canAddSocialItem(row) : false;
|
|
21795
|
+
})(),
|
|
21796
|
+
editLinkDisabled: false,
|
|
21797
|
+
moreDisabled: false,
|
|
21798
|
+
deleteDisabled: selectedElRef.current !== null && (() => {
|
|
21799
|
+
const social = getSocialItem(selectedElRef.current);
|
|
21800
|
+
return social ? !canRemoveSocialItem(social) : false;
|
|
21801
|
+
})(),
|
|
21802
|
+
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow || selectedElRef.current !== null && (() => {
|
|
21803
|
+
const social = getSocialItem(selectedElRef.current);
|
|
21804
|
+
const row = social ? findSocialsRow(social) : null;
|
|
21805
|
+
return row ? !canAddSocialItem(row) : false;
|
|
21806
|
+
})(),
|
|
21807
|
+
showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
|
|
21808
|
+
showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
|
|
21809
|
+
selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
|
|
21810
|
+
),
|
|
21811
|
+
showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
|
|
21812
|
+
dropdownOpen: navDropdownPreviewOpen,
|
|
21813
|
+
onDropdownOpenChange: handleNavDropdownOpenChange,
|
|
21814
|
+
headingVisible: footerHeadingVisible,
|
|
21815
|
+
onHeadingVisibleChange: handleFooterHeadingVisibleChange
|
|
21816
|
+
}
|
|
21817
|
+
) : void 0
|
|
21818
|
+
}
|
|
21819
|
+
),
|
|
21820
|
+
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
21821
|
+
/* @__PURE__ */ jsx33(
|
|
21822
|
+
EditGlowChrome,
|
|
20162
21823
|
{
|
|
20163
|
-
|
|
20164
|
-
|
|
20165
|
-
|
|
20166
|
-
|
|
20167
|
-
|
|
20168
|
-
onDelete: handleFieldDelete
|
|
21824
|
+
rect: toolbarRect,
|
|
21825
|
+
elRef: glowElRef,
|
|
21826
|
+
reorderHrefKey,
|
|
21827
|
+
dragDisabled: reorderDragDisabled,
|
|
21828
|
+
hideHandle: isItemDragging
|
|
20169
21829
|
}
|
|
20170
|
-
)
|
|
20171
|
-
|
|
20172
|
-
|
|
20173
|
-
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
20174
|
-
"div",
|
|
20175
|
-
{
|
|
20176
|
-
className: "pointer-events-none fixed z-[2147483644]",
|
|
20177
|
-
style: { top: slot.top, left: slot.left, width: slot.width },
|
|
20178
|
-
children: /* @__PURE__ */ jsx33(
|
|
20179
|
-
DropIndicator,
|
|
21830
|
+
),
|
|
21831
|
+
/* @__PURE__ */ jsx33(
|
|
21832
|
+
FloatingToolbar,
|
|
20180
21833
|
{
|
|
20181
|
-
|
|
20182
|
-
|
|
20183
|
-
|
|
21834
|
+
rect: toolbarRect,
|
|
21835
|
+
parentScroll: parentScrollRef.current,
|
|
21836
|
+
elRef: toolbarElRef,
|
|
21837
|
+
onCommand: handleCommand,
|
|
21838
|
+
activeCommands,
|
|
21839
|
+
showEditLink,
|
|
21840
|
+
onEditLink: openLinkPopoverForActive
|
|
20184
21841
|
}
|
|
20185
21842
|
)
|
|
20186
|
-
},
|
|
20187
|
-
|
|
20188
|
-
)) : null,
|
|
20189
|
-
fieldTypePickerOpen && formPickRect ? (() => {
|
|
20190
|
-
const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
|
|
20191
|
-
return /* @__PURE__ */ jsx33(
|
|
21843
|
+
] }),
|
|
21844
|
+
maxBadge && /* @__PURE__ */ jsxs20(
|
|
20192
21845
|
"div",
|
|
20193
21846
|
{
|
|
20194
|
-
|
|
21847
|
+
"data-ohw-max-badge": "",
|
|
20195
21848
|
style: {
|
|
20196
|
-
|
|
20197
|
-
|
|
21849
|
+
position: "fixed",
|
|
21850
|
+
top: maxBadge.rect.bottom + 4,
|
|
21851
|
+
left: maxBadge.rect.right,
|
|
21852
|
+
transform: "translateX(-100%)",
|
|
21853
|
+
zIndex: 2147483647,
|
|
21854
|
+
background: maxBadge.current > maxBadge.max ? "#FEF2F2" : "#F5F5F4",
|
|
21855
|
+
color: maxBadge.current > maxBadge.max ? "#DC2626" : "#78716C",
|
|
21856
|
+
border: `1px solid ${maxBadge.current > maxBadge.max ? "#FECACA" : "#E7E5E4"}`,
|
|
21857
|
+
borderRadius: 4,
|
|
21858
|
+
padding: "2px 6px",
|
|
21859
|
+
fontSize: 11,
|
|
21860
|
+
fontWeight: 500,
|
|
21861
|
+
pointerEvents: "none"
|
|
20198
21862
|
},
|
|
20199
|
-
children:
|
|
21863
|
+
children: [
|
|
21864
|
+
maxBadge.current,
|
|
21865
|
+
"/",
|
|
21866
|
+
maxBadge.max
|
|
21867
|
+
]
|
|
20200
21868
|
}
|
|
20201
|
-
)
|
|
20202
|
-
|
|
20203
|
-
|
|
20204
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx33(
|
|
20205
|
-
FooterContainerChrome,
|
|
20206
|
-
{
|
|
20207
|
-
rect: toolbarRect,
|
|
20208
|
-
onAdd: handleAddFooterColumn,
|
|
20209
|
-
addDisabled: !canAddFooterColumn()
|
|
20210
|
-
}
|
|
20211
|
-
),
|
|
20212
|
-
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ jsx33(
|
|
20213
|
-
ItemInteractionLayer,
|
|
20214
|
-
{
|
|
20215
|
-
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
20216
|
-
toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
|
|
20217
|
-
elRef: glowElRef,
|
|
20218
|
-
state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanelRect(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
20219
|
-
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
20220
|
-
dragDisabled: reorderDragDisabled,
|
|
20221
|
-
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
20222
|
-
onDragHandleDragStart: handleItemDragStart,
|
|
20223
|
-
onDragHandleDragEnd: handleItemDragEnd,
|
|
20224
|
-
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
20225
|
-
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
20226
|
-
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection && !selectedIsSocialsRow,
|
|
20227
|
-
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ jsx33(
|
|
20228
|
-
ItemActionToolbar,
|
|
20229
|
-
{
|
|
20230
|
-
onEditLink: openLinkPopoverForSelected,
|
|
20231
|
-
onStyle: () => {
|
|
20232
|
-
const row = selectedElRef.current;
|
|
20233
|
-
if (!row) return;
|
|
20234
|
-
if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
|
|
20235
|
-
else openSocialsDisplayPanel(row);
|
|
20236
|
-
},
|
|
20237
|
-
showStyle: selectedIsSocialsRow,
|
|
20238
|
-
styleActive: floatingPanel?.kind === "socials-display",
|
|
20239
|
-
onAddItem: handleAddChildItem,
|
|
20240
|
-
onSelectParent: handleSelectParent,
|
|
20241
|
-
onDuplicate: handleDuplicateSelected,
|
|
20242
|
-
onDelete: handleDeleteSelected,
|
|
20243
|
-
addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
20244
|
-
const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
|
|
20245
|
-
return row ? !canAddSocialItem(row) : false;
|
|
20246
|
-
})(),
|
|
20247
|
-
editLinkDisabled: false,
|
|
20248
|
-
moreDisabled: false,
|
|
20249
|
-
deleteDisabled: selectedElRef.current !== null && (() => {
|
|
20250
|
-
const social = getSocialItem(selectedElRef.current);
|
|
20251
|
-
return social ? !canRemoveSocialItem(social) : false;
|
|
20252
|
-
})(),
|
|
20253
|
-
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow || selectedElRef.current !== null && (() => {
|
|
20254
|
-
const social = getSocialItem(selectedElRef.current);
|
|
20255
|
-
const row = social ? findSocialsRow(social) : null;
|
|
20256
|
-
return row ? !canAddSocialItem(row) : false;
|
|
20257
|
-
})(),
|
|
20258
|
-
showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
|
|
20259
|
-
showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
|
|
20260
|
-
selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
|
|
20261
|
-
),
|
|
20262
|
-
showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
|
|
20263
|
-
dropdownOpen: navDropdownPreviewOpen,
|
|
20264
|
-
onDropdownOpenChange: handleNavDropdownOpenChange,
|
|
20265
|
-
headingVisible: footerHeadingVisible,
|
|
20266
|
-
onHeadingVisibleChange: handleFooterHeadingVisibleChange
|
|
20267
|
-
}
|
|
20268
|
-
) : void 0
|
|
20269
|
-
}
|
|
20270
|
-
),
|
|
20271
|
-
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
20272
|
-
/* @__PURE__ */ jsx33(
|
|
20273
|
-
EditGlowChrome,
|
|
21869
|
+
),
|
|
21870
|
+
toggleState && !linkPopover && /* @__PURE__ */ jsx33(
|
|
21871
|
+
StateToggle,
|
|
20274
21872
|
{
|
|
20275
|
-
rect:
|
|
20276
|
-
|
|
20277
|
-
|
|
20278
|
-
|
|
20279
|
-
hideHandle: isItemDragging
|
|
21873
|
+
rect: toggleState.rect,
|
|
21874
|
+
activeState: toggleState.activeState,
|
|
21875
|
+
states: toggleState.states,
|
|
21876
|
+
onStateChange: handleStateChange
|
|
20280
21877
|
}
|
|
20281
21878
|
),
|
|
20282
|
-
/* @__PURE__ */
|
|
20283
|
-
|
|
21879
|
+
sectionGap && !linkPopover && /* @__PURE__ */ jsxs20(
|
|
21880
|
+
"div",
|
|
20284
21881
|
{
|
|
20285
|
-
|
|
20286
|
-
|
|
20287
|
-
|
|
20288
|
-
|
|
20289
|
-
|
|
20290
|
-
|
|
20291
|
-
|
|
21882
|
+
"data-ohw-section-insert-line": "",
|
|
21883
|
+
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
21884
|
+
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
21885
|
+
children: [
|
|
21886
|
+
/* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
21887
|
+
/* @__PURE__ */ jsx33(
|
|
21888
|
+
Badge,
|
|
21889
|
+
{
|
|
21890
|
+
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",
|
|
21891
|
+
onClick: () => {
|
|
21892
|
+
window.parent.postMessage(
|
|
21893
|
+
{
|
|
21894
|
+
type: "ow:add-section",
|
|
21895
|
+
insertAfter: sectionGap.insertAfter,
|
|
21896
|
+
insertBefore: sectionGap.insertBefore
|
|
21897
|
+
},
|
|
21898
|
+
"*"
|
|
21899
|
+
);
|
|
21900
|
+
},
|
|
21901
|
+
children: "Add Section"
|
|
21902
|
+
}
|
|
21903
|
+
),
|
|
21904
|
+
/* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
21905
|
+
]
|
|
20292
21906
|
}
|
|
20293
|
-
)
|
|
20294
|
-
|
|
20295
|
-
|
|
20296
|
-
|
|
20297
|
-
|
|
20298
|
-
|
|
20299
|
-
|
|
20300
|
-
|
|
20301
|
-
|
|
20302
|
-
|
|
20303
|
-
|
|
20304
|
-
|
|
20305
|
-
|
|
20306
|
-
|
|
20307
|
-
|
|
20308
|
-
borderRadius: 4,
|
|
20309
|
-
padding: "2px 6px",
|
|
20310
|
-
fontSize: 11,
|
|
20311
|
-
fontWeight: 500,
|
|
20312
|
-
pointerEvents: "none"
|
|
21907
|
+
),
|
|
21908
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx33(
|
|
21909
|
+
LinkPopover,
|
|
21910
|
+
{
|
|
21911
|
+
panelRef: linkPopoverPanelRef,
|
|
21912
|
+
portalContainer: dialogPortalContainer,
|
|
21913
|
+
open: true,
|
|
21914
|
+
mode: linkPopover.mode ?? "edit",
|
|
21915
|
+
pages: sitePages,
|
|
21916
|
+
sections: currentSections,
|
|
21917
|
+
sectionsByPath,
|
|
21918
|
+
initialTarget: linkPopover.target,
|
|
21919
|
+
existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
|
|
21920
|
+
onClose: closeLinkPopover,
|
|
21921
|
+
onSubmit: handleLinkPopoverSubmit
|
|
20313
21922
|
},
|
|
20314
|
-
|
|
20315
|
-
|
|
20316
|
-
|
|
20317
|
-
|
|
20318
|
-
|
|
20319
|
-
|
|
20320
|
-
|
|
20321
|
-
|
|
20322
|
-
|
|
20323
|
-
|
|
20324
|
-
|
|
20325
|
-
|
|
20326
|
-
|
|
20327
|
-
|
|
20328
|
-
}
|
|
20329
|
-
),
|
|
20330
|
-
sectionGap && !linkPopover && /* @__PURE__ */ jsxs20(
|
|
20331
|
-
"div",
|
|
20332
|
-
{
|
|
20333
|
-
"data-ohw-section-insert-line": "",
|
|
20334
|
-
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
20335
|
-
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
20336
|
-
children: [
|
|
20337
|
-
/* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
20338
|
-
/* @__PURE__ */ jsx33(
|
|
20339
|
-
Badge,
|
|
21923
|
+
linkPopover.key
|
|
21924
|
+
) : null,
|
|
21925
|
+
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ jsx33(
|
|
21926
|
+
FloatingPanel,
|
|
21927
|
+
{
|
|
21928
|
+
open: true,
|
|
21929
|
+
title: floatingPanel.title,
|
|
21930
|
+
context: floatingPanel.context,
|
|
21931
|
+
position: floatingPanelPos,
|
|
21932
|
+
onPositionChange: setFloatingPanelPos,
|
|
21933
|
+
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
21934
|
+
onClose: closeFloatingPanelOnly,
|
|
21935
|
+
children: /* @__PURE__ */ jsx33(
|
|
21936
|
+
SocialsDisplayPanel,
|
|
20340
21937
|
{
|
|
20341
|
-
|
|
20342
|
-
|
|
20343
|
-
|
|
20344
|
-
|
|
20345
|
-
|
|
20346
|
-
insertAfter: sectionGap.insertAfter,
|
|
20347
|
-
insertBefore: sectionGap.insertBefore
|
|
20348
|
-
},
|
|
20349
|
-
"*"
|
|
20350
|
-
);
|
|
20351
|
-
},
|
|
20352
|
-
children: "Add Section"
|
|
21938
|
+
display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
|
|
21939
|
+
onChange: (next) => {
|
|
21940
|
+
changeSocialsDisplay(floatingPanel.row, next);
|
|
21941
|
+
setFloatingPanel({ ...floatingPanel });
|
|
21942
|
+
}
|
|
20353
21943
|
}
|
|
20354
|
-
)
|
|
20355
|
-
|
|
20356
|
-
|
|
20357
|
-
|
|
20358
|
-
|
|
20359
|
-
|
|
20360
|
-
|
|
20361
|
-
|
|
20362
|
-
|
|
20363
|
-
|
|
20364
|
-
|
|
20365
|
-
|
|
20366
|
-
|
|
20367
|
-
|
|
20368
|
-
|
|
20369
|
-
|
|
20370
|
-
|
|
20371
|
-
|
|
20372
|
-
|
|
21944
|
+
)
|
|
21945
|
+
}
|
|
21946
|
+
) : null
|
|
21947
|
+
] }),
|
|
21948
|
+
bridgeRoot
|
|
21949
|
+
) : null
|
|
21950
|
+
] });
|
|
21951
|
+
}
|
|
21952
|
+
|
|
21953
|
+
// src/ui/EmptySection.tsx
|
|
21954
|
+
import Link3 from "next/link";
|
|
21955
|
+
import { Fragment as Fragment9, jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
21956
|
+
function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
|
|
21957
|
+
return /* @__PURE__ */ jsxs21(Fragment9, { children: [
|
|
21958
|
+
/* @__PURE__ */ jsx34(
|
|
21959
|
+
"p",
|
|
21960
|
+
{
|
|
21961
|
+
style: {
|
|
21962
|
+
fontFamily: "var(--brand-font-body)",
|
|
21963
|
+
fontSize: "0.75rem",
|
|
21964
|
+
fontWeight: 500,
|
|
21965
|
+
letterSpacing: "0.15em",
|
|
21966
|
+
textTransform: "uppercase",
|
|
21967
|
+
color: "var(--brand-accent)",
|
|
21968
|
+
marginBottom: "1.5rem"
|
|
20373
21969
|
},
|
|
20374
|
-
|
|
20375
|
-
|
|
20376
|
-
|
|
20377
|
-
|
|
20378
|
-
|
|
20379
|
-
|
|
20380
|
-
|
|
20381
|
-
|
|
20382
|
-
|
|
20383
|
-
|
|
20384
|
-
|
|
20385
|
-
|
|
20386
|
-
|
|
20387
|
-
|
|
20388
|
-
|
|
20389
|
-
|
|
20390
|
-
|
|
20391
|
-
|
|
20392
|
-
|
|
20393
|
-
|
|
20394
|
-
|
|
20395
|
-
|
|
20396
|
-
|
|
20397
|
-
|
|
20398
|
-
|
|
20399
|
-
|
|
20400
|
-
|
|
21970
|
+
children: /* @__PURE__ */ jsx34(Link3, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ jsx34("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
|
|
21971
|
+
}
|
|
21972
|
+
),
|
|
21973
|
+
/* @__PURE__ */ jsx34(
|
|
21974
|
+
"h1",
|
|
21975
|
+
{
|
|
21976
|
+
style: {
|
|
21977
|
+
fontFamily: "var(--brand-font-heading)",
|
|
21978
|
+
fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
|
|
21979
|
+
lineHeight: 1.1,
|
|
21980
|
+
letterSpacing: "-0.025em",
|
|
21981
|
+
color: "var(--brand-text)",
|
|
21982
|
+
marginBottom: "1rem"
|
|
21983
|
+
},
|
|
21984
|
+
...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
|
|
21985
|
+
children: title
|
|
21986
|
+
}
|
|
21987
|
+
),
|
|
21988
|
+
/* @__PURE__ */ jsx34(
|
|
21989
|
+
"p",
|
|
21990
|
+
{
|
|
21991
|
+
style: {
|
|
21992
|
+
fontFamily: "var(--brand-font-body)",
|
|
21993
|
+
fontSize: "1rem",
|
|
21994
|
+
lineHeight: 1.7,
|
|
21995
|
+
fontWeight: 300,
|
|
21996
|
+
color: "var(--brand-text-muted)",
|
|
21997
|
+
maxWidth: "340px"
|
|
21998
|
+
},
|
|
21999
|
+
...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
|
|
22000
|
+
children: "This page doesn't have any content yet."
|
|
22001
|
+
}
|
|
22002
|
+
)
|
|
22003
|
+
] });
|
|
20401
22004
|
}
|
|
20402
22005
|
export {
|
|
20403
22006
|
AI_DEFAULT_BRAND,
|
|
@@ -20415,6 +22018,7 @@ export {
|
|
|
20415
22018
|
DropdownMenuItem,
|
|
20416
22019
|
DropdownMenuSeparator,
|
|
20417
22020
|
DropdownMenuTrigger,
|
|
22021
|
+
EmptySection,
|
|
20418
22022
|
ItemActionToolbar,
|
|
20419
22023
|
ItemInteractionLayer,
|
|
20420
22024
|
LinkEditorPanel,
|