@ohhwells/bridge 0.1.74 → 0.1.76-next.230
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 +2493 -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 +2485 -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,167 @@ 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 findByInstanceId(instanceId) {
|
|
8055
|
+
const escapedId = CSS.escape(instanceId);
|
|
8056
|
+
return document.querySelector(`[data-ohw-instance="${escapedId}"]`) ?? document.querySelector(`[data-ohw-section="${escapedId}"]:not([data-ohw-instance])`);
|
|
8057
|
+
}
|
|
8058
|
+
function planSectionMove(instanceId, targetIndex, currentPath) {
|
|
8059
|
+
const sections = topLevelSections();
|
|
8060
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8061
|
+
if (index === -1) return null;
|
|
8062
|
+
const dragged = sections[index];
|
|
8063
|
+
const others = sections.filter((_, i) => i !== index);
|
|
8064
|
+
const clamped = Math.max(0, Math.min(targetIndex, others.length));
|
|
8065
|
+
const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
|
|
8066
|
+
return reordered.map((el, order) => ({
|
|
8067
|
+
instanceId: instanceIdOf(el),
|
|
8068
|
+
type: el.getAttribute("data-ohw-section") ?? "",
|
|
8069
|
+
order,
|
|
8070
|
+
pagePath: currentPath
|
|
8071
|
+
}));
|
|
8072
|
+
}
|
|
8073
|
+
function moveSectionInstance(instanceId, direction, currentPath) {
|
|
8074
|
+
const sections = topLevelSections();
|
|
8075
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8076
|
+
if (index === -1) return null;
|
|
8077
|
+
const siblingIndex = direction === "up" ? index - 1 : index + 1;
|
|
8078
|
+
if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
|
|
8079
|
+
const entries = planSectionMove(instanceId, siblingIndex, currentPath);
|
|
8080
|
+
if (!entries) return null;
|
|
8081
|
+
applyPersistedOrder(entries);
|
|
8082
|
+
return entries;
|
|
8083
|
+
}
|
|
8084
|
+
function syncRemovedFlags(entries) {
|
|
8085
|
+
const removedIds = new Set(entries.filter((e) => e.removed).map((e) => e.instanceId));
|
|
8086
|
+
document.querySelectorAll(`[${REMOVED_ATTR2}]`).forEach((el) => {
|
|
8087
|
+
if (!removedIds.has(instanceIdOf(el))) {
|
|
8088
|
+
el.style.removeProperty("display");
|
|
8089
|
+
el.removeAttribute(REMOVED_ATTR2);
|
|
8090
|
+
}
|
|
8091
|
+
});
|
|
8092
|
+
for (const id of removedIds) {
|
|
8093
|
+
const el = findByInstanceId(id);
|
|
8094
|
+
if (el) {
|
|
8095
|
+
el.style.display = "none";
|
|
8096
|
+
el.setAttribute(REMOVED_ATTR2, "");
|
|
8097
|
+
}
|
|
8098
|
+
}
|
|
8099
|
+
}
|
|
8100
|
+
function applyPersistedOrder(entries) {
|
|
8101
|
+
syncRemovedFlags(entries);
|
|
8102
|
+
if (entries.length === 0) return;
|
|
8103
|
+
const sections = topLevelSections();
|
|
8104
|
+
if (sections.length === 0) return;
|
|
8105
|
+
const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
|
|
8106
|
+
const ordered = [...sections].sort((a, b) => {
|
|
8107
|
+
const aOrder = orderIndex.get(instanceIdOf(a));
|
|
8108
|
+
const bOrder = orderIndex.get(instanceIdOf(b));
|
|
8109
|
+
if (aOrder === void 0 && bOrder === void 0) return 0;
|
|
8110
|
+
if (aOrder === void 0) return 1;
|
|
8111
|
+
if (bOrder === void 0) return -1;
|
|
8112
|
+
return aOrder - bOrder;
|
|
8113
|
+
});
|
|
8114
|
+
let prev = null;
|
|
8115
|
+
for (const el of ordered) {
|
|
8116
|
+
if (prev) prev.after(el);
|
|
8117
|
+
prev = el;
|
|
8118
|
+
}
|
|
8119
|
+
}
|
|
8120
|
+
function setSectionRemoved(instanceId, currentPath, existingEntries, removed) {
|
|
8121
|
+
if (!findByInstanceId(instanceId)) return null;
|
|
8122
|
+
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
8123
|
+
const allSections = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
8124
|
+
(el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
|
|
8125
|
+
);
|
|
8126
|
+
allSections.forEach((el, order) => {
|
|
8127
|
+
const id = instanceIdOf(el);
|
|
8128
|
+
if (!byId.has(id)) {
|
|
8129
|
+
byId.set(id, { instanceId: id, type: el.getAttribute("data-ohw-section") ?? "", order, pagePath: currentPath });
|
|
8130
|
+
}
|
|
8131
|
+
});
|
|
8132
|
+
const target = byId.get(instanceId);
|
|
8133
|
+
if (!target) return null;
|
|
8134
|
+
byId.set(instanceId, { ...target, removed });
|
|
8135
|
+
const entries = Array.from(byId.values());
|
|
8136
|
+
applyPersistedOrder(entries);
|
|
8137
|
+
return entries;
|
|
8138
|
+
}
|
|
8139
|
+
function deleteSectionInstance(instanceId, currentPath, existingEntries) {
|
|
8140
|
+
return setSectionRemoved(instanceId, currentPath, existingEntries, true);
|
|
8141
|
+
}
|
|
8142
|
+
function restoreSectionInstance(instanceId, currentPath, existingEntries) {
|
|
8143
|
+
return setSectionRemoved(instanceId, currentPath, existingEntries, false);
|
|
8144
|
+
}
|
|
8145
|
+
function newInstanceId() {
|
|
8146
|
+
return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `instance-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
8147
|
+
}
|
|
8148
|
+
function getPageSectionOrderEntries(raw, currentPath) {
|
|
8149
|
+
if (!raw) return [];
|
|
8150
|
+
try {
|
|
8151
|
+
const entries = JSON.parse(raw);
|
|
8152
|
+
return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
|
|
8153
|
+
} catch {
|
|
8154
|
+
return [];
|
|
8155
|
+
}
|
|
8156
|
+
}
|
|
8157
|
+
function rekeySectionSubtree(root, instanceId) {
|
|
8158
|
+
const suffix = `::${instanceId}`;
|
|
8159
|
+
const rekey = (el, attr) => {
|
|
8160
|
+
const current = el.getAttribute(attr);
|
|
8161
|
+
if (current) el.setAttribute(attr, `${current}${suffix}`);
|
|
8162
|
+
};
|
|
8163
|
+
if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
|
|
8164
|
+
if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
|
|
8165
|
+
root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
|
|
8166
|
+
root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
|
|
8167
|
+
}
|
|
8168
|
+
function initSectionInstancesFromContent(content, currentPath) {
|
|
8169
|
+
document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
|
|
8170
|
+
el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
|
|
8171
|
+
});
|
|
8172
|
+
const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
|
|
8173
|
+
for (const entry of entries) {
|
|
8174
|
+
if (entry.instanceId === entry.type) continue;
|
|
8175
|
+
if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
|
|
8176
|
+
const original = document.querySelector(
|
|
8177
|
+
`[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
|
|
8178
|
+
);
|
|
8179
|
+
if (!original) continue;
|
|
8180
|
+
const clone = original.cloneNode(true);
|
|
8181
|
+
clone.setAttribute("data-ohw-instance", entry.instanceId);
|
|
8182
|
+
rekeySectionSubtree(clone, entry.instanceId);
|
|
8183
|
+
original.insertAdjacentElement("afterend", clone);
|
|
8184
|
+
}
|
|
8185
|
+
applyPersistedOrder(entries);
|
|
8186
|
+
}
|
|
8187
|
+
|
|
8188
|
+
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
8189
|
+
import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
8190
|
+
function findSectionElement(instanceId) {
|
|
8191
|
+
const escaped = CSS.escape(instanceId);
|
|
8192
|
+
return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
|
|
8193
|
+
}
|
|
8194
|
+
function readRect(instanceId) {
|
|
8195
|
+
const el = findSectionElement(instanceId);
|
|
8196
|
+
if (!el) return null;
|
|
8197
|
+
const r2 = el.getBoundingClientRect();
|
|
8198
|
+
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
8199
|
+
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
8200
|
+
}
|
|
7354
8201
|
function useLiveSectionRect(sectionId) {
|
|
7355
8202
|
const [rect, setRect] = useState5(null);
|
|
7356
8203
|
useEffect4(() => {
|
|
@@ -7368,7 +8215,7 @@ function useLiveSectionRect(sectionId) {
|
|
|
7368
8215
|
const opts = { capture: true, passive: true };
|
|
7369
8216
|
window.addEventListener("scroll", update, opts);
|
|
7370
8217
|
window.addEventListener("resize", update);
|
|
7371
|
-
const el =
|
|
8218
|
+
const el = findSectionElement(sectionId);
|
|
7372
8219
|
const ro = el ? new ResizeObserver(update) : null;
|
|
7373
8220
|
if (el && ro) ro.observe(el);
|
|
7374
8221
|
const interval = setInterval(update, 500);
|
|
@@ -7381,6 +8228,12 @@ function useLiveSectionRect(sectionId) {
|
|
|
7381
8228
|
}, [sectionId]);
|
|
7382
8229
|
return rect;
|
|
7383
8230
|
}
|
|
8231
|
+
function computeSectionBoundaryFlags(instanceId) {
|
|
8232
|
+
const topLevel = topLevelSections();
|
|
8233
|
+
const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
|
|
8234
|
+
if (index === -1) return { isFirst: true, isLast: true };
|
|
8235
|
+
return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
|
|
8236
|
+
}
|
|
7384
8237
|
var PRIMARY2 = "#0885FE";
|
|
7385
8238
|
function edgeAwareRadius(rect) {
|
|
7386
8239
|
const container = window.innerWidth <= 480 ? 16 : 24;
|
|
@@ -7454,6 +8307,7 @@ function AiSectionOverlay({
|
|
|
7454
8307
|
}) {
|
|
7455
8308
|
const [selectedId, setSelectedId] = useState5(null);
|
|
7456
8309
|
const [reviewId, setReviewId] = useState5(null);
|
|
8310
|
+
const [reviewButtonsHidden, setReviewButtonsHidden] = useState5(false);
|
|
7457
8311
|
const reviewIdRef = useRef4(null);
|
|
7458
8312
|
reviewIdRef.current = reviewId;
|
|
7459
8313
|
const selectedIdRef = useRef4(null);
|
|
@@ -7462,7 +8316,7 @@ function AiSectionOverlay({
|
|
|
7462
8316
|
(el) => {
|
|
7463
8317
|
postToParent2({
|
|
7464
8318
|
type: "ow:section-selected",
|
|
7465
|
-
sectionId: el
|
|
8319
|
+
sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
|
|
7466
8320
|
sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
|
|
7467
8321
|
});
|
|
7468
8322
|
},
|
|
@@ -7471,7 +8325,7 @@ function AiSectionOverlay({
|
|
|
7471
8325
|
const selectFromElement = useCallback2(
|
|
7472
8326
|
(el, options) => {
|
|
7473
8327
|
const sectionEl = el?.closest("[data-ohw-section]") ?? null;
|
|
7474
|
-
const id = sectionEl
|
|
8328
|
+
const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
|
|
7475
8329
|
if (id === selectedIdRef.current) return;
|
|
7476
8330
|
setSelectedId(id);
|
|
7477
8331
|
if (options?.report !== false) report(sectionEl);
|
|
@@ -7492,12 +8346,15 @@ function AiSectionOverlay({
|
|
|
7492
8346
|
selectFromElement(sectionEl);
|
|
7493
8347
|
return sectionEl != null;
|
|
7494
8348
|
},
|
|
7495
|
-
clear: () =>
|
|
8349
|
+
clear: () => {
|
|
8350
|
+
setSelectedId(null);
|
|
8351
|
+
report(null);
|
|
8352
|
+
}
|
|
7496
8353
|
};
|
|
7497
8354
|
return () => {
|
|
7498
8355
|
apiRef.current = null;
|
|
7499
8356
|
};
|
|
7500
|
-
}, [apiRef, selectFromElement]);
|
|
8357
|
+
}, [apiRef, selectFromElement, report]);
|
|
7501
8358
|
useEffect4(() => {
|
|
7502
8359
|
const onMessage = (e) => {
|
|
7503
8360
|
if (e.data?.type === "ow:ai-select" && e.data.sectionId === null) {
|
|
@@ -7512,9 +8369,10 @@ function AiSectionOverlay({
|
|
|
7512
8369
|
}
|
|
7513
8370
|
const found = readRect(sectionId) != null;
|
|
7514
8371
|
setReviewId(found ? sectionId : null);
|
|
8372
|
+
setReviewButtonsHidden(e.data.hideButtons === true);
|
|
7515
8373
|
postToParent2({ type: "ow:ai-review-started", sectionId, found });
|
|
7516
8374
|
if (found) {
|
|
7517
|
-
document.querySelector(`[data-ohw-
|
|
8375
|
+
document.querySelector(`[data-ohw-instance="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
7518
8376
|
}
|
|
7519
8377
|
}
|
|
7520
8378
|
};
|
|
@@ -7533,7 +8391,7 @@ function AiSectionOverlay({
|
|
|
7533
8391
|
return;
|
|
7534
8392
|
}
|
|
7535
8393
|
const sec = t.closest("[data-ohw-section]");
|
|
7536
|
-
setHoveredId(sec
|
|
8394
|
+
setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
|
|
7537
8395
|
};
|
|
7538
8396
|
const onLeave = () => setHoveredId(null);
|
|
7539
8397
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -7565,9 +8423,30 @@ function AiSectionOverlay({
|
|
|
7565
8423
|
},
|
|
7566
8424
|
[postToParent2]
|
|
7567
8425
|
);
|
|
7568
|
-
const
|
|
8426
|
+
const activeSelectionId = reviewId ? null : selectedId;
|
|
8427
|
+
const selectionRect = useLiveSectionRect(activeSelectionId);
|
|
7569
8428
|
const reviewRect = useLiveSectionRect(reviewId);
|
|
7570
8429
|
const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
|
|
8430
|
+
useEffect4(() => {
|
|
8431
|
+
const selectedEl = activeSelectionId ? findSectionElement(activeSelectionId) : null;
|
|
8432
|
+
if (!activeSelectionId || !selectionRect || selectedEl && isChromeSection(selectedEl)) {
|
|
8433
|
+
postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
|
|
8434
|
+
return;
|
|
8435
|
+
}
|
|
8436
|
+
const { isFirst, isLast } = computeSectionBoundaryFlags(activeSelectionId);
|
|
8437
|
+
postToParent2({
|
|
8438
|
+
type: "ow:section-rect",
|
|
8439
|
+
instanceId: activeSelectionId,
|
|
8440
|
+
rect: {
|
|
8441
|
+
top: selectionRect.top + window.scrollY,
|
|
8442
|
+
left: selectionRect.left + window.scrollX,
|
|
8443
|
+
width: selectionRect.width,
|
|
8444
|
+
height: selectionRect.height
|
|
8445
|
+
},
|
|
8446
|
+
isFirst,
|
|
8447
|
+
isLast
|
|
8448
|
+
});
|
|
8449
|
+
}, [activeSelectionId, selectionRect, postToParent2]);
|
|
7571
8450
|
return /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
7572
8451
|
hoverRect && /* @__PURE__ */ jsx17(
|
|
7573
8452
|
"div",
|
|
@@ -7618,13 +8497,16 @@ function AiSectionOverlay({
|
|
|
7618
8497
|
border: `2px solid ${PRIMARY2}`,
|
|
7619
8498
|
borderRadius: edgeAwareRadius(reviewRect),
|
|
7620
8499
|
zIndex: 2147483200,
|
|
7621
|
-
// The veil itself: swallows clicks so the section stays locked until decided.
|
|
8500
|
+
// The veil itself: swallows clicks so the section stays locked until decided. This
|
|
8501
|
+
// stopPropagation only guards the bubble phase; the bridge's capture-phase click
|
|
8502
|
+
// handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
|
|
8503
|
+
// Accept/Discard resolves to the media beneath and opens the file picker.
|
|
7622
8504
|
background: "rgba(8, 133, 254, 0.04)",
|
|
7623
8505
|
pointerEvents: "auto",
|
|
7624
8506
|
cursor: "default"
|
|
7625
8507
|
},
|
|
7626
8508
|
onClick: (e) => e.stopPropagation(),
|
|
7627
|
-
children: /* @__PURE__ */ jsxs9(
|
|
8509
|
+
children: !reviewButtonsHidden && /* @__PURE__ */ jsxs9(
|
|
7628
8510
|
"div",
|
|
7629
8511
|
{
|
|
7630
8512
|
style: {
|
|
@@ -7647,47 +8529,6 @@ function AiSectionOverlay({
|
|
|
7647
8529
|
] });
|
|
7648
8530
|
}
|
|
7649
8531
|
|
|
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
8532
|
// src/OhhwellsBridge.tsx
|
|
7692
8533
|
import { createPortal as createPortal2 } from "react-dom";
|
|
7693
8534
|
import { usePathname as usePathname2, useRouter as useRouter3, useSearchParams } from "next/navigation";
|
|
@@ -10232,8 +11073,13 @@ function referenceBox(slot) {
|
|
|
10232
11073
|
const neighbour = row ? Array.from(row.querySelectorAll('[data-ohw-editable="icon"]')).find(
|
|
10233
11074
|
(el) => el !== slot && !el.hasAttribute("data-ohw-social-icon-placeholder")
|
|
10234
11075
|
) : null;
|
|
10235
|
-
|
|
10236
|
-
|
|
11076
|
+
if (neighbour) {
|
|
11077
|
+
const box2 = neighbour.querySelector(GLYPH_SELECTOR)?.getBoundingClientRect();
|
|
11078
|
+
if (box2?.width && box2.height) return box2;
|
|
11079
|
+
}
|
|
11080
|
+
const own = slot.getBoundingClientRect();
|
|
11081
|
+
if (own.width && own.height) return own;
|
|
11082
|
+
const box = slot.querySelector(GLYPH_SELECTOR)?.getBoundingClientRect() ?? null;
|
|
10237
11083
|
return box?.width && box.height ? box : null;
|
|
10238
11084
|
}
|
|
10239
11085
|
function iconMarkupSizedFor(slot, markup) {
|
|
@@ -12034,6 +12880,7 @@ function readLogoSizeState(content, placement) {
|
|
|
12034
12880
|
function getLogoElement(el) {
|
|
12035
12881
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
12036
12882
|
if (marked) return marked;
|
|
12883
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
12037
12884
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
12038
12885
|
if (!root) return null;
|
|
12039
12886
|
const anchor = el.closest("a");
|
|
@@ -12913,6 +13760,334 @@ function useNavItemDrag({
|
|
|
12913
13760
|
};
|
|
12914
13761
|
}
|
|
12915
13762
|
|
|
13763
|
+
// src/useSectionDrag.ts
|
|
13764
|
+
import { useCallback as useCallback7, useEffect as useEffect11, useRef as useRef9, useState as useState11 } from "react";
|
|
13765
|
+
|
|
13766
|
+
// src/lib/section-dnd.ts
|
|
13767
|
+
function isFooterSection(el) {
|
|
13768
|
+
return el.dataset.ohwSection === "footer";
|
|
13769
|
+
}
|
|
13770
|
+
function buildSectionDropSlots(draggedInstanceId) {
|
|
13771
|
+
const sections = topLevelSections().filter(
|
|
13772
|
+
(el) => instanceIdOf(el) !== draggedInstanceId && !isFooterSection(el)
|
|
13773
|
+
);
|
|
13774
|
+
const slots = [];
|
|
13775
|
+
if (sections.length === 0) return slots;
|
|
13776
|
+
const left = 0;
|
|
13777
|
+
const width = document.documentElement.clientWidth;
|
|
13778
|
+
for (let i = 0; i <= sections.length; i++) {
|
|
13779
|
+
let y;
|
|
13780
|
+
if (i === 0) {
|
|
13781
|
+
y = sections[0].getBoundingClientRect().top;
|
|
13782
|
+
} else if (i === sections.length) {
|
|
13783
|
+
y = sections[sections.length - 1].getBoundingClientRect().bottom;
|
|
13784
|
+
} else {
|
|
13785
|
+
const prev = sections[i - 1].getBoundingClientRect();
|
|
13786
|
+
const next = sections[i].getBoundingClientRect();
|
|
13787
|
+
y = (prev.bottom + next.top) / 2;
|
|
13788
|
+
}
|
|
13789
|
+
slots.push({ insertIndex: i, y, left, width });
|
|
13790
|
+
}
|
|
13791
|
+
return slots;
|
|
13792
|
+
}
|
|
13793
|
+
function hitTestSectionDropSlot(y, slots) {
|
|
13794
|
+
let best = null;
|
|
13795
|
+
for (const slot of slots) {
|
|
13796
|
+
const dist = Math.abs(y - slot.y);
|
|
13797
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
13798
|
+
}
|
|
13799
|
+
return best?.slot ?? null;
|
|
13800
|
+
}
|
|
13801
|
+
|
|
13802
|
+
// src/useSectionDrag.ts
|
|
13803
|
+
var PRESS_THRESHOLD = 10;
|
|
13804
|
+
var EDGE_ZONE = 60;
|
|
13805
|
+
var MAX_AUTO_SCROLL_SPEED = 18;
|
|
13806
|
+
var SECTION_DRAG_EXCLUDED_SELECTOR = [
|
|
13807
|
+
"[data-ohw-toolbar]",
|
|
13808
|
+
"[data-ohw-edit-chrome]",
|
|
13809
|
+
"[data-ohw-item-interaction]",
|
|
13810
|
+
"[data-ohw-drag-handle-container]",
|
|
13811
|
+
'[data-slot="drag-handle"]',
|
|
13812
|
+
"[data-ohw-item-toolbar-anchor]",
|
|
13813
|
+
"[data-ohw-item-drag-surface]",
|
|
13814
|
+
"[data-ohw-more-menu]",
|
|
13815
|
+
'[data-slot="dropdown-menu-content"]',
|
|
13816
|
+
'[data-slot="dropdown-menu-item"]',
|
|
13817
|
+
"[data-ohw-state-toggle]",
|
|
13818
|
+
"[data-ohw-max-badge]",
|
|
13819
|
+
"[data-ohw-floating-panel]",
|
|
13820
|
+
"[data-ohw-section-picker]",
|
|
13821
|
+
"[data-ohw-link-popover-root]",
|
|
13822
|
+
"[data-ohw-link-modal-root]",
|
|
13823
|
+
"[data-ohw-link-page-dropdown]",
|
|
13824
|
+
'[data-slot="popover-content"]',
|
|
13825
|
+
'[data-slot="dialog-content"]',
|
|
13826
|
+
'[data-slot="dialog-overlay"]',
|
|
13827
|
+
"[data-ohw-ai-review]",
|
|
13828
|
+
"[data-ohw-editable]",
|
|
13829
|
+
"[data-ohw-editable-state]",
|
|
13830
|
+
"[contenteditable]",
|
|
13831
|
+
"[data-ohw-href-key]",
|
|
13832
|
+
"[data-ohw-footer-col]",
|
|
13833
|
+
"[data-ohw-social-label]",
|
|
13834
|
+
"a",
|
|
13835
|
+
"button",
|
|
13836
|
+
'[role="button"]',
|
|
13837
|
+
'[data-ohw-role="navbar-button"]',
|
|
13838
|
+
'[data-ohw-role="button"]',
|
|
13839
|
+
"[data-ohw-carousel]",
|
|
13840
|
+
"[data-ohw-carousel-value]",
|
|
13841
|
+
"[data-ohw-carousel-slide]",
|
|
13842
|
+
"[data-ohw-carousel-overlay]",
|
|
13843
|
+
"[data-ohw-media-chrome]",
|
|
13844
|
+
"[data-ohw-media-overlay]",
|
|
13845
|
+
"[data-ohw-media-skeleton]"
|
|
13846
|
+
].join(", ");
|
|
13847
|
+
function visibleClip(ps) {
|
|
13848
|
+
if (!ps) return null;
|
|
13849
|
+
const top = Math.max(0, ps.headerH - ps.iframeOffsetTop);
|
|
13850
|
+
const bottom = Math.min(window.innerHeight, ps.headerH + ps.canvasH - ps.iframeOffsetTop);
|
|
13851
|
+
return { top, bottom: Math.max(top, bottom) };
|
|
13852
|
+
}
|
|
13853
|
+
function useSectionDrag({
|
|
13854
|
+
isEditMode,
|
|
13855
|
+
editContentRef,
|
|
13856
|
+
postToParentRef,
|
|
13857
|
+
parentScrollRef,
|
|
13858
|
+
navDragRef,
|
|
13859
|
+
footerDragRef,
|
|
13860
|
+
suppressNextClickRef,
|
|
13861
|
+
suppressClickUntilRef
|
|
13862
|
+
}) {
|
|
13863
|
+
const sectionDragRef = useRef9(null);
|
|
13864
|
+
const [sectionDropSlots, setSectionDropSlots] = useState11([]);
|
|
13865
|
+
const [activeSectionDropIndex, setActiveSectionDropIndex] = useState11(null);
|
|
13866
|
+
const [isSectionDragging, setIsSectionDragging] = useState11(false);
|
|
13867
|
+
const sectionPointerDragRef = useRef9(null);
|
|
13868
|
+
const autoScrollRafRef = useRef9(null);
|
|
13869
|
+
const autoScrollDeltaRef = useRef9(0);
|
|
13870
|
+
const stopAutoScroll = useCallback7(() => {
|
|
13871
|
+
if (autoScrollRafRef.current != null) {
|
|
13872
|
+
cancelAnimationFrame(autoScrollRafRef.current);
|
|
13873
|
+
autoScrollRafRef.current = null;
|
|
13874
|
+
}
|
|
13875
|
+
autoScrollDeltaRef.current = 0;
|
|
13876
|
+
}, []);
|
|
13877
|
+
const tickAutoScroll = useCallback7(() => {
|
|
13878
|
+
if (!sectionDragRef.current) {
|
|
13879
|
+
stopAutoScroll();
|
|
13880
|
+
return;
|
|
13881
|
+
}
|
|
13882
|
+
if (autoScrollDeltaRef.current !== 0) {
|
|
13883
|
+
postToParentRef.current({ type: "ow:request-scroll", deltaY: autoScrollDeltaRef.current });
|
|
13884
|
+
}
|
|
13885
|
+
autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
|
|
13886
|
+
}, [postToParentRef, stopAutoScroll]);
|
|
13887
|
+
const updateAutoScroll = useCallback7(
|
|
13888
|
+
(clientY) => {
|
|
13889
|
+
const clip = visibleClip(parentScrollRef.current);
|
|
13890
|
+
let delta = 0;
|
|
13891
|
+
if (clip) {
|
|
13892
|
+
const distTop = clientY - clip.top;
|
|
13893
|
+
const distBottom = clip.bottom - clientY;
|
|
13894
|
+
if (distTop >= 0 && distTop < EDGE_ZONE) {
|
|
13895
|
+
delta = -MAX_AUTO_SCROLL_SPEED * (1 - distTop / EDGE_ZONE);
|
|
13896
|
+
} else if (distBottom >= 0 && distBottom < EDGE_ZONE) {
|
|
13897
|
+
delta = MAX_AUTO_SCROLL_SPEED * (1 - distBottom / EDGE_ZONE);
|
|
13898
|
+
}
|
|
13899
|
+
}
|
|
13900
|
+
autoScrollDeltaRef.current = delta;
|
|
13901
|
+
if (delta !== 0 && autoScrollRafRef.current == null) {
|
|
13902
|
+
autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
|
|
13903
|
+
} else if (delta === 0) {
|
|
13904
|
+
stopAutoScroll();
|
|
13905
|
+
}
|
|
13906
|
+
},
|
|
13907
|
+
[parentScrollRef, stopAutoScroll, tickAutoScroll]
|
|
13908
|
+
);
|
|
13909
|
+
const clearSectionDragVisuals = useCallback7(() => {
|
|
13910
|
+
sectionDragRef.current?.draggedEl.removeAttribute("data-ohw-section-dragging");
|
|
13911
|
+
sectionDragRef.current = null;
|
|
13912
|
+
setSectionDropSlots([]);
|
|
13913
|
+
setActiveSectionDropIndex(null);
|
|
13914
|
+
setIsSectionDragging(false);
|
|
13915
|
+
stopAutoScroll();
|
|
13916
|
+
document.documentElement.removeAttribute("data-ohw-section-dragging-root");
|
|
13917
|
+
unlockItemDragInteraction();
|
|
13918
|
+
}, [stopAutoScroll]);
|
|
13919
|
+
const refreshSectionDragVisuals = useCallback7(
|
|
13920
|
+
(session, clientX, clientY) => {
|
|
13921
|
+
session.lastClientX = clientX;
|
|
13922
|
+
session.lastClientY = clientY;
|
|
13923
|
+
const slots = buildSectionDropSlots(session.instanceId);
|
|
13924
|
+
const activeSlot = hitTestSectionDropSlot(clientY, slots);
|
|
13925
|
+
session.activeSlot = activeSlot;
|
|
13926
|
+
setSectionDropSlots(slots);
|
|
13927
|
+
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
13928
|
+
setActiveSectionDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
13929
|
+
updateAutoScroll(clientY);
|
|
13930
|
+
},
|
|
13931
|
+
[updateAutoScroll]
|
|
13932
|
+
);
|
|
13933
|
+
const beginSectionDrag = useCallback7(
|
|
13934
|
+
(session) => {
|
|
13935
|
+
sectionDragRef.current = session;
|
|
13936
|
+
setIsSectionDragging(true);
|
|
13937
|
+
lockItemDuringDrag();
|
|
13938
|
+
document.documentElement.setAttribute("data-ohw-section-dragging-root", "");
|
|
13939
|
+
session.draggedEl.setAttribute("data-ohw-section-dragging", "");
|
|
13940
|
+
refreshSectionDragVisuals(session, session.lastClientX, session.lastClientY);
|
|
13941
|
+
},
|
|
13942
|
+
[refreshSectionDragVisuals]
|
|
13943
|
+
);
|
|
13944
|
+
const commitSectionDrag = useCallback7(() => {
|
|
13945
|
+
const session = sectionDragRef.current;
|
|
13946
|
+
if (!session) {
|
|
13947
|
+
clearSectionDragVisuals();
|
|
13948
|
+
return;
|
|
13949
|
+
}
|
|
13950
|
+
const slot = session.activeSlot ?? hitTestSectionDropSlot(session.lastClientY, buildSectionDropSlots(session.instanceId));
|
|
13951
|
+
const entries = slot ? planSectionMove(session.instanceId, slot.insertIndex, window.location.pathname) : null;
|
|
13952
|
+
if (!entries) {
|
|
13953
|
+
clearSectionDragVisuals();
|
|
13954
|
+
return;
|
|
13955
|
+
}
|
|
13956
|
+
const orderJson = JSON.stringify(entries);
|
|
13957
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
13958
|
+
setAiSectionOrder(orderJson, window.location.pathname);
|
|
13959
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
13960
|
+
applyPersistedOrder(entries);
|
|
13961
|
+
clearSectionDragVisuals();
|
|
13962
|
+
requestAnimationFrame(() => {
|
|
13963
|
+
if (editContentRef.current[SECTION_ORDER_KEY] === orderJson) {
|
|
13964
|
+
applyPersistedOrder(entries);
|
|
13965
|
+
}
|
|
13966
|
+
requestAnimationFrame(() => {
|
|
13967
|
+
window.dispatchEvent(new Event("resize"));
|
|
13968
|
+
});
|
|
13969
|
+
});
|
|
13970
|
+
}, [clearSectionDragVisuals, editContentRef, postToParentRef]);
|
|
13971
|
+
const startSectionPressDrag = useCallback7(
|
|
13972
|
+
(el, clientX, clientY, pointerId) => {
|
|
13973
|
+
if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return false;
|
|
13974
|
+
const instanceId = instanceIdOf(el);
|
|
13975
|
+
if (!instanceId) return false;
|
|
13976
|
+
sectionPointerDragRef.current = {
|
|
13977
|
+
el,
|
|
13978
|
+
instanceId,
|
|
13979
|
+
startX: clientX,
|
|
13980
|
+
startY: clientY,
|
|
13981
|
+
pointerId,
|
|
13982
|
+
started: false
|
|
13983
|
+
};
|
|
13984
|
+
return true;
|
|
13985
|
+
},
|
|
13986
|
+
[footerDragRef, navDragRef]
|
|
13987
|
+
);
|
|
13988
|
+
useEffect11(() => {
|
|
13989
|
+
if (!isEditMode) return;
|
|
13990
|
+
const onPointerDown = (e) => {
|
|
13991
|
+
if (e.button !== 0) return;
|
|
13992
|
+
if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return;
|
|
13993
|
+
if (sectionPointerDragRef.current) return;
|
|
13994
|
+
const target = e.target;
|
|
13995
|
+
if (!(target instanceof HTMLElement)) return;
|
|
13996
|
+
if (target.closest(SECTION_DRAG_EXCLUDED_SELECTOR)) return;
|
|
13997
|
+
const sectionEl = target.closest("[data-ohw-section]");
|
|
13998
|
+
if (!sectionEl || isChromeSection(sectionEl) || sectionEl.dataset.ohwSection === "footer") return;
|
|
13999
|
+
if (!topLevelSections().includes(sectionEl)) return;
|
|
14000
|
+
startSectionPressDrag(sectionEl, e.clientX, e.clientY, e.pointerId);
|
|
14001
|
+
};
|
|
14002
|
+
const onPointerMove = (e) => {
|
|
14003
|
+
const pending = sectionPointerDragRef.current;
|
|
14004
|
+
if (!pending) return;
|
|
14005
|
+
if (pending.started) {
|
|
14006
|
+
e.preventDefault();
|
|
14007
|
+
clearTextSelection();
|
|
14008
|
+
const session = sectionDragRef.current;
|
|
14009
|
+
if (!session) return;
|
|
14010
|
+
refreshSectionDragVisuals(session, e.clientX, e.clientY);
|
|
14011
|
+
return;
|
|
14012
|
+
}
|
|
14013
|
+
const dx = e.clientX - pending.startX;
|
|
14014
|
+
const dy = e.clientY - pending.startY;
|
|
14015
|
+
if (dx * dx + dy * dy < PRESS_THRESHOLD * PRESS_THRESHOLD) return;
|
|
14016
|
+
e.preventDefault();
|
|
14017
|
+
pending.started = true;
|
|
14018
|
+
armItemPressDrag();
|
|
14019
|
+
clearTextSelection();
|
|
14020
|
+
try {
|
|
14021
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
14022
|
+
} catch {
|
|
14023
|
+
}
|
|
14024
|
+
beginSectionDrag({
|
|
14025
|
+
instanceId: pending.instanceId,
|
|
14026
|
+
draggedEl: pending.el,
|
|
14027
|
+
lastClientX: e.clientX,
|
|
14028
|
+
lastClientY: e.clientY,
|
|
14029
|
+
activeSlot: null
|
|
14030
|
+
});
|
|
14031
|
+
};
|
|
14032
|
+
const endPointerDrag = (e) => {
|
|
14033
|
+
const pending = sectionPointerDragRef.current;
|
|
14034
|
+
sectionPointerDragRef.current = null;
|
|
14035
|
+
try {
|
|
14036
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
14037
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
14038
|
+
}
|
|
14039
|
+
} catch {
|
|
14040
|
+
}
|
|
14041
|
+
if (!pending) return;
|
|
14042
|
+
if (!pending.started) {
|
|
14043
|
+
unlockItemDragInteraction();
|
|
14044
|
+
return;
|
|
14045
|
+
}
|
|
14046
|
+
suppressNextClickRef.current = true;
|
|
14047
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
14048
|
+
commitSectionDrag();
|
|
14049
|
+
};
|
|
14050
|
+
const onKeyDown = (e) => {
|
|
14051
|
+
if (e.key !== "Escape") return;
|
|
14052
|
+
if (!sectionDragRef.current && !sectionPointerDragRef.current) return;
|
|
14053
|
+
sectionPointerDragRef.current = null;
|
|
14054
|
+
clearSectionDragVisuals();
|
|
14055
|
+
};
|
|
14056
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
14057
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
14058
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
14059
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
14060
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
14061
|
+
return () => {
|
|
14062
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
14063
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
14064
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
14065
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
14066
|
+
document.removeEventListener("keydown", onKeyDown, true);
|
|
14067
|
+
unlockItemDragInteraction();
|
|
14068
|
+
stopAutoScroll();
|
|
14069
|
+
};
|
|
14070
|
+
}, [
|
|
14071
|
+
beginSectionDrag,
|
|
14072
|
+
clearSectionDragVisuals,
|
|
14073
|
+
commitSectionDrag,
|
|
14074
|
+
footerDragRef,
|
|
14075
|
+
isEditMode,
|
|
14076
|
+
navDragRef,
|
|
14077
|
+
refreshSectionDragVisuals,
|
|
14078
|
+
startSectionPressDrag,
|
|
14079
|
+
stopAutoScroll,
|
|
14080
|
+
suppressClickUntilRef,
|
|
14081
|
+
suppressNextClickRef
|
|
14082
|
+
]);
|
|
14083
|
+
return {
|
|
14084
|
+
sectionDragRef,
|
|
14085
|
+
sectionDropSlots,
|
|
14086
|
+
activeSectionDropIndex,
|
|
14087
|
+
isSectionDragging
|
|
14088
|
+
};
|
|
14089
|
+
}
|
|
14090
|
+
|
|
12916
14091
|
// src/ui/footer-container-chrome.tsx
|
|
12917
14092
|
import { Plus as Plus2 } from "lucide-react";
|
|
12918
14093
|
import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
@@ -12965,7 +14140,7 @@ function FooterContainerChrome({
|
|
|
12965
14140
|
}
|
|
12966
14141
|
|
|
12967
14142
|
// src/lib/carousel.ts
|
|
12968
|
-
import { useEffect as
|
|
14143
|
+
import { useEffect as useEffect12, useState as useState12 } from "react";
|
|
12969
14144
|
var CAROUSEL_ATTR = "data-ohw-carousel";
|
|
12970
14145
|
var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
|
|
12971
14146
|
var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
|
|
@@ -13027,8 +14202,8 @@ function applyCarouselNode(key, val) {
|
|
|
13027
14202
|
return true;
|
|
13028
14203
|
}
|
|
13029
14204
|
function useOhwCarousel(key, initial) {
|
|
13030
|
-
const [images, setImages] =
|
|
13031
|
-
|
|
14205
|
+
const [images, setImages] = useState12(initial);
|
|
14206
|
+
useEffect12(() => {
|
|
13032
14207
|
const el = document.querySelector(
|
|
13033
14208
|
`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
|
|
13034
14209
|
);
|
|
@@ -13110,6 +14285,7 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
13110
14285
|
NAV_ORDER_KEY,
|
|
13111
14286
|
FOOTER_ORDER_KEY,
|
|
13112
14287
|
NAV_COUNT_KEY,
|
|
14288
|
+
SECTION_ORDER_KEY,
|
|
13113
14289
|
// A socials row's order and its icons-vs-words setting live under keys no element carries,
|
|
13114
14290
|
// so collecting the DOM alone left them behind: the draft knew the row was showing icons and
|
|
13115
14291
|
// had gained an item, and the published page went back to the template's own (OHH-736).
|
|
@@ -13574,6 +14750,7 @@ function fadeInImageElement(img, onReady) {
|
|
|
13574
14750
|
function applyEditableImageSrc(img, url) {
|
|
13575
14751
|
img.removeAttribute("srcset");
|
|
13576
14752
|
img.removeAttribute("sizes");
|
|
14753
|
+
if (img.loading === "lazy") img.loading = "eager";
|
|
13577
14754
|
img.src = url;
|
|
13578
14755
|
}
|
|
13579
14756
|
function fadeInBgImage(el, url, onReady) {
|
|
@@ -13638,21 +14815,10 @@ function parseSchedulingInsertAfter(insertAfter) {
|
|
|
13638
14815
|
insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
|
|
13639
14816
|
};
|
|
13640
14817
|
}
|
|
13641
|
-
function
|
|
13642
|
-
|
|
13643
|
-
const
|
|
13644
|
-
|
|
13645
|
-
return { effectiveInsertAfter, insertBefore };
|
|
13646
|
-
}
|
|
13647
|
-
function getSchedulingMountPoint(insertAfter) {
|
|
13648
|
-
const { anchor } = parseSchedulingInsertAfter(insertAfter);
|
|
13649
|
-
let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
|
|
13650
|
-
if (!anchorEl && anchor === "scheduling") {
|
|
13651
|
-
const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
|
|
13652
|
-
anchorEl = widgets.at(-1) ?? null;
|
|
13653
|
-
}
|
|
13654
|
-
if (!anchorEl) return null;
|
|
13655
|
-
return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
14818
|
+
function resolveEntryAnchor(entry) {
|
|
14819
|
+
if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
|
|
14820
|
+
const parsed = parseSchedulingInsertAfter(entry.insertAfter);
|
|
14821
|
+
return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
|
|
13656
14822
|
}
|
|
13657
14823
|
function schedulingMountDepth(insertAfter) {
|
|
13658
14824
|
if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
|
|
@@ -13669,8 +14835,7 @@ function getPageSchedulingEntries(raw) {
|
|
|
13669
14835
|
}
|
|
13670
14836
|
}
|
|
13671
14837
|
function isSchedulingWidgetMissing(entry) {
|
|
13672
|
-
|
|
13673
|
-
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
|
|
14838
|
+
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
|
|
13674
14839
|
}
|
|
13675
14840
|
function hasMissingSchedulingWidgets(entries) {
|
|
13676
14841
|
return entries.some(isSchedulingWidgetMissing);
|
|
@@ -13700,16 +14865,17 @@ function initSectionsFromContent(content, removeExisting = false) {
|
|
|
13700
14865
|
} catch {
|
|
13701
14866
|
}
|
|
13702
14867
|
}
|
|
13703
|
-
function mountSchedulingWidget(
|
|
13704
|
-
const
|
|
13705
|
-
const sectionId = schedulingSectionId(
|
|
14868
|
+
function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
|
|
14869
|
+
const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
|
|
14870
|
+
const sectionId = schedulingSectionId(widgetId);
|
|
13706
14871
|
if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
|
|
13707
|
-
const
|
|
13708
|
-
if (!
|
|
14872
|
+
const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
|
|
14873
|
+
if (!anchorEl) return false;
|
|
14874
|
+
const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
13709
14875
|
const container = document.createElement("div");
|
|
13710
14876
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
13711
|
-
if (
|
|
13712
|
-
const beforeAnchor = document.querySelector(`[data-ohw-section="${
|
|
14877
|
+
if (beforeId) {
|
|
14878
|
+
const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
|
|
13713
14879
|
const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
|
|
13714
14880
|
if (!beforePoint) return false;
|
|
13715
14881
|
beforePoint.insertAdjacentElement("beforebegin", container);
|
|
@@ -13720,19 +14886,25 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
13720
14886
|
}
|
|
13721
14887
|
tail.insertAdjacentElement("afterend", container);
|
|
13722
14888
|
}
|
|
13723
|
-
|
|
13724
|
-
|
|
13725
|
-
|
|
13726
|
-
|
|
13727
|
-
|
|
13728
|
-
|
|
13729
|
-
|
|
13730
|
-
|
|
13731
|
-
|
|
13732
|
-
|
|
13733
|
-
|
|
13734
|
-
|
|
13735
|
-
|
|
14889
|
+
try {
|
|
14890
|
+
const root = createRoot2(container);
|
|
14891
|
+
flushSync2(() => {
|
|
14892
|
+
root.render(
|
|
14893
|
+
/* @__PURE__ */ jsx33(
|
|
14894
|
+
SchedulingWidget,
|
|
14895
|
+
{
|
|
14896
|
+
notifyOnConnect,
|
|
14897
|
+
initialScheduleId: scheduleId,
|
|
14898
|
+
insertAfter: widgetId
|
|
14899
|
+
}
|
|
14900
|
+
)
|
|
14901
|
+
);
|
|
14902
|
+
});
|
|
14903
|
+
} catch (err) {
|
|
14904
|
+
console.error("[ow:scheduling] render threw", err);
|
|
14905
|
+
container.remove();
|
|
14906
|
+
return false;
|
|
14907
|
+
}
|
|
13736
14908
|
const tracker = getSectionsTracker();
|
|
13737
14909
|
let sections = [];
|
|
13738
14910
|
try {
|
|
@@ -13740,10 +14912,12 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
13740
14912
|
} catch {
|
|
13741
14913
|
}
|
|
13742
14914
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
13743
|
-
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter ===
|
|
14915
|
+
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
|
|
13744
14916
|
sections.push({
|
|
13745
14917
|
type: "scheduling",
|
|
13746
|
-
insertAfter:
|
|
14918
|
+
insertAfter: widgetId,
|
|
14919
|
+
anchorId,
|
|
14920
|
+
beforeId: beforeId ?? null,
|
|
13747
14921
|
pagePath: window.location.pathname,
|
|
13748
14922
|
...scheduleId ? { scheduleId } : {}
|
|
13749
14923
|
});
|
|
@@ -13757,7 +14931,8 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
13757
14931
|
for (let i = pending.length - 1; i >= 0; i--) {
|
|
13758
14932
|
const entry = pending[i];
|
|
13759
14933
|
const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
|
|
13760
|
-
|
|
14934
|
+
const { anchorId, beforeId } = resolveEntryAnchor(entry);
|
|
14935
|
+
if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
|
|
13761
14936
|
pending.splice(i, 1);
|
|
13762
14937
|
}
|
|
13763
14938
|
}
|
|
@@ -13915,6 +15090,11 @@ function applyLinkByKey(key, val) {
|
|
|
13915
15090
|
hrefAnchors.forEach((el) => applyLinkHref(el, val));
|
|
13916
15091
|
}
|
|
13917
15092
|
}
|
|
15093
|
+
function isInsideLinkEditor(target) {
|
|
15094
|
+
return Boolean(
|
|
15095
|
+
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"]')
|
|
15096
|
+
);
|
|
15097
|
+
}
|
|
13918
15098
|
function isInsideFloatingPanel(target) {
|
|
13919
15099
|
return Boolean(target.closest("[data-ohw-floating-panel]"));
|
|
13920
15100
|
}
|
|
@@ -13922,11 +15102,6 @@ function isPointOverFloatingPanel(clientX, clientY) {
|
|
|
13922
15102
|
const el = document.elementFromPoint(clientX, clientY);
|
|
13923
15103
|
return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
|
|
13924
15104
|
}
|
|
13925
|
-
function isInsideLinkEditor(target) {
|
|
13926
|
-
return Boolean(
|
|
13927
|
-
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"]')
|
|
13928
|
-
);
|
|
13929
|
-
}
|
|
13930
15105
|
function getHrefKeyFromElement(el) {
|
|
13931
15106
|
if (!el) return null;
|
|
13932
15107
|
const anchor = el.closest("[data-ohw-href-key]");
|
|
@@ -14185,7 +15360,7 @@ function getNavigationSelectionParent(el) {
|
|
|
14185
15360
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
14186
15361
|
return getFooterLinksContainer();
|
|
14187
15362
|
}
|
|
14188
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
15363
|
+
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)) {
|
|
14189
15364
|
return getNavigationRoot(el);
|
|
14190
15365
|
}
|
|
14191
15366
|
return null;
|
|
@@ -14400,7 +15575,6 @@ var ICONS = {
|
|
|
14400
15575
|
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"/>',
|
|
14401
15576
|
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"/>'
|
|
14402
15577
|
};
|
|
14403
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
14404
15578
|
var SELECTION_CHROME_GAP2 = 4;
|
|
14405
15579
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
14406
15580
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -14780,6 +15954,45 @@ function StateToggle({
|
|
|
14780
15954
|
);
|
|
14781
15955
|
}
|
|
14782
15956
|
var contentCache = /* @__PURE__ */ new Map();
|
|
15957
|
+
var fetchedContentPaths = /* @__PURE__ */ new Set();
|
|
15958
|
+
var OHW_LOADER_STYLE = {
|
|
15959
|
+
position: "fixed",
|
|
15960
|
+
inset: 0,
|
|
15961
|
+
background: "#fff",
|
|
15962
|
+
zIndex: 2147483646,
|
|
15963
|
+
display: "flex",
|
|
15964
|
+
alignItems: "center",
|
|
15965
|
+
justifyContent: "center"
|
|
15966
|
+
};
|
|
15967
|
+
function OhwLoaderSpinner() {
|
|
15968
|
+
return /* @__PURE__ */ jsxs20("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", "aria-hidden": true, children: [
|
|
15969
|
+
/* @__PURE__ */ jsx33("circle", { cx: "14", cy: "14", r: "11", stroke: "#E7E5E4", strokeWidth: "3" }),
|
|
15970
|
+
/* @__PURE__ */ jsx33(
|
|
15971
|
+
"circle",
|
|
15972
|
+
{
|
|
15973
|
+
cx: "14",
|
|
15974
|
+
cy: "14",
|
|
15975
|
+
r: "11",
|
|
15976
|
+
stroke: "#1C1917",
|
|
15977
|
+
strokeWidth: "3",
|
|
15978
|
+
strokeDasharray: "17 52",
|
|
15979
|
+
strokeLinecap: "round",
|
|
15980
|
+
children: /* @__PURE__ */ jsx33(
|
|
15981
|
+
"animateTransform",
|
|
15982
|
+
{
|
|
15983
|
+
attributeName: "transform",
|
|
15984
|
+
type: "rotate",
|
|
15985
|
+
from: "0 14 14",
|
|
15986
|
+
to: "360 14 14",
|
|
15987
|
+
dur: "0.7s",
|
|
15988
|
+
repeatCount: "indefinite"
|
|
15989
|
+
}
|
|
15990
|
+
)
|
|
15991
|
+
}
|
|
15992
|
+
)
|
|
15993
|
+
] });
|
|
15994
|
+
}
|
|
15995
|
+
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){}})();`;
|
|
14783
15996
|
function resolveSubdomain(subdomainFromQuery) {
|
|
14784
15997
|
if (subdomainFromQuery) return subdomainFromQuery;
|
|
14785
15998
|
if (typeof window !== "undefined") {
|
|
@@ -14802,8 +16015,8 @@ function OhhwellsBridge() {
|
|
|
14802
16015
|
const router = useRouter3();
|
|
14803
16016
|
const searchParams = useSearchParams();
|
|
14804
16017
|
const isEditMode = isEditSessionActive();
|
|
14805
|
-
const [bridgeRoot, setBridgeRoot] =
|
|
14806
|
-
|
|
16018
|
+
const [bridgeRoot, setBridgeRoot] = useState13(null);
|
|
16019
|
+
useEffect13(() => {
|
|
14807
16020
|
const figtreeFontId = "ohw-figtree-font";
|
|
14808
16021
|
if (!document.getElementById(figtreeFontId)) {
|
|
14809
16022
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -14832,82 +16045,146 @@ function OhhwellsBridge() {
|
|
|
14832
16045
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
14833
16046
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
14834
16047
|
useSavedLinkNavigation(isEditMode);
|
|
14835
|
-
const postToParent2 =
|
|
16048
|
+
const postToParent2 = useCallback8((data) => {
|
|
14836
16049
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
14837
16050
|
window.parent.postMessage(data, "*");
|
|
14838
16051
|
}
|
|
14839
16052
|
}, []);
|
|
14840
|
-
const [fetchState, setFetchState] =
|
|
14841
|
-
const autoSaveTimers =
|
|
14842
|
-
const activeElRef =
|
|
14843
|
-
const pointerHeldRef =
|
|
14844
|
-
const selectedElRef =
|
|
14845
|
-
const selectedHrefKeyRef =
|
|
14846
|
-
const selectedFooterColAttrRef =
|
|
14847
|
-
const originalContentRef =
|
|
14848
|
-
const activeStateElRef =
|
|
14849
|
-
const parentScrollRef =
|
|
14850
|
-
const visibleViewportRef =
|
|
14851
|
-
const [dialogPortalContainer, setDialogPortalContainer] =
|
|
14852
|
-
const attachVisibleViewport =
|
|
16053
|
+
const [fetchState, setFetchState] = useState13("idle");
|
|
16054
|
+
const autoSaveTimers = useRef10(/* @__PURE__ */ new Map());
|
|
16055
|
+
const activeElRef = useRef10(null);
|
|
16056
|
+
const pointerHeldRef = useRef10(false);
|
|
16057
|
+
const selectedElRef = useRef10(null);
|
|
16058
|
+
const selectedHrefKeyRef = useRef10(null);
|
|
16059
|
+
const selectedFooterColAttrRef = useRef10(null);
|
|
16060
|
+
const originalContentRef = useRef10(null);
|
|
16061
|
+
const activeStateElRef = useRef10(null);
|
|
16062
|
+
const parentScrollRef = useRef10(null);
|
|
16063
|
+
const visibleViewportRef = useRef10(null);
|
|
16064
|
+
const [dialogPortalContainer, setDialogPortalContainer] = useState13(null);
|
|
16065
|
+
const attachVisibleViewport = useCallback8((node) => {
|
|
14853
16066
|
visibleViewportRef.current = node;
|
|
14854
16067
|
setDialogPortalContainer(node);
|
|
14855
16068
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
14856
16069
|
}, []);
|
|
14857
|
-
const toolbarElRef =
|
|
14858
|
-
const glowElRef =
|
|
14859
|
-
const hoveredImageRef =
|
|
14860
|
-
const hoveredImageHasTextOverlapRef =
|
|
14861
|
-
const dragOverElRef =
|
|
14862
|
-
const [mediaHover, setMediaHover] =
|
|
14863
|
-
const [
|
|
14864
|
-
const
|
|
14865
|
-
const
|
|
14866
|
-
|
|
14867
|
-
|
|
14868
|
-
|
|
14869
|
-
|
|
16070
|
+
const toolbarElRef = useRef10(null);
|
|
16071
|
+
const glowElRef = useRef10(null);
|
|
16072
|
+
const hoveredImageRef = useRef10(null);
|
|
16073
|
+
const hoveredImageHasTextOverlapRef = useRef10(false);
|
|
16074
|
+
const dragOverElRef = useRef10(null);
|
|
16075
|
+
const [mediaHover, setMediaHover] = useState13(null);
|
|
16076
|
+
const [selectedMedia, setSelectedMedia] = useState13(null);
|
|
16077
|
+
const selectedMediaElRef = useRef10(null);
|
|
16078
|
+
const clearMediaSelection = useCallback8(() => {
|
|
16079
|
+
const prev = selectedMediaElRef.current;
|
|
16080
|
+
selectedMediaElRef.current = null;
|
|
16081
|
+
setSelectedMedia(null);
|
|
16082
|
+
const sectionEl = prev?.closest("[data-ohw-section]") ?? null;
|
|
16083
|
+
if (sectionEl) {
|
|
16084
|
+
postToParentRef.current({
|
|
16085
|
+
type: "ow:section-selected",
|
|
16086
|
+
sectionId: sectionEl.dataset.ohwSection ?? null,
|
|
16087
|
+
sectionLabel: sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? ""),
|
|
16088
|
+
key: null
|
|
16089
|
+
});
|
|
16090
|
+
}
|
|
16091
|
+
}, []);
|
|
16092
|
+
const clearMediaSelectionRef = useRef10(clearMediaSelection);
|
|
16093
|
+
clearMediaSelectionRef.current = clearMediaSelection;
|
|
16094
|
+
const selectMediaElement = useCallback8((el) => {
|
|
16095
|
+
const r2 = el.getBoundingClientRect();
|
|
16096
|
+
const video = el.dataset.ohwEditable === "video" ? el.querySelector("video") : null;
|
|
16097
|
+
selectedMediaElRef.current = el;
|
|
16098
|
+
setSelectedMedia({
|
|
16099
|
+
key: el.dataset.ohwKey ?? "",
|
|
16100
|
+
rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
|
|
16101
|
+
elementType: el.dataset.ohwEditable ?? "image",
|
|
16102
|
+
hasTextOverlap: false,
|
|
16103
|
+
isDragOver: false,
|
|
16104
|
+
...video ? { videoAutoplay: video.autoplay, videoMuted: video.muted } : {}
|
|
16105
|
+
});
|
|
16106
|
+
const sectionEl = el.closest("[data-ohw-section]");
|
|
16107
|
+
aiSectionApiRef.current?.selectFromElement(el, { report: false });
|
|
16108
|
+
postToParentRef.current({
|
|
16109
|
+
type: "ow:section-selected",
|
|
16110
|
+
sectionId: sectionEl?.dataset.ohwSection ?? null,
|
|
16111
|
+
sectionLabel: sectionEl ? sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? "") : null,
|
|
16112
|
+
key: el.dataset.ohwKey ?? null,
|
|
16113
|
+
// Display name for the pill — the raw key prettifies into fragments ("Img"); the
|
|
16114
|
+
// bridge knows what the node IS, so it names it.
|
|
16115
|
+
keyLabel: el.dataset.ohwEditable === "video" ? "Video" : el.dataset.ohwEditable === "bg-image" ? "Background" : "Image"
|
|
16116
|
+
});
|
|
16117
|
+
}, []);
|
|
16118
|
+
const selectMediaElementRef = useRef10(selectMediaElement);
|
|
16119
|
+
selectMediaElementRef.current = selectMediaElement;
|
|
16120
|
+
useEffect13(() => {
|
|
16121
|
+
if (!selectedMedia) return;
|
|
16122
|
+
const update = () => {
|
|
16123
|
+
const el = selectedMediaElRef.current;
|
|
16124
|
+
if (!el || !el.isConnected) {
|
|
16125
|
+
clearMediaSelection();
|
|
16126
|
+
return;
|
|
16127
|
+
}
|
|
16128
|
+
const r2 = el.getBoundingClientRect();
|
|
16129
|
+
setSelectedMedia(
|
|
16130
|
+
(prev) => prev ? { ...prev, rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } } : prev
|
|
16131
|
+
);
|
|
16132
|
+
};
|
|
16133
|
+
window.addEventListener("scroll", update, true);
|
|
16134
|
+
window.addEventListener("resize", update);
|
|
16135
|
+
return () => {
|
|
16136
|
+
window.removeEventListener("scroll", update, true);
|
|
16137
|
+
window.removeEventListener("resize", update);
|
|
16138
|
+
};
|
|
16139
|
+
}, [selectedMedia !== null]);
|
|
16140
|
+
const [carouselHover, setCarouselHover] = useState13(null);
|
|
16141
|
+
const [uploadingRects, setUploadingRects] = useState13({});
|
|
16142
|
+
const hoveredGapRef = useRef10(null);
|
|
16143
|
+
const imageUnhoverTimerRef = useRef10(null);
|
|
16144
|
+
const imageShowTimerRef = useRef10(null);
|
|
16145
|
+
const editStylesRef = useRef10(null);
|
|
16146
|
+
const activateRef = useRef10(() => {
|
|
14870
16147
|
});
|
|
14871
|
-
const deactivateRef =
|
|
16148
|
+
const deactivateRef = useRef10(() => {
|
|
14872
16149
|
});
|
|
14873
|
-
const selectRef =
|
|
16150
|
+
const selectRef = useRef10(() => {
|
|
14874
16151
|
});
|
|
14875
|
-
const selectFrameRef =
|
|
16152
|
+
const selectFrameRef = useRef10(() => {
|
|
14876
16153
|
});
|
|
14877
|
-
const selectLogoRef =
|
|
16154
|
+
const selectLogoRef = useRef10(() => {
|
|
14878
16155
|
});
|
|
14879
|
-
const openLogoSizePanelRef =
|
|
16156
|
+
const openLogoSizePanelRef = useRef10(() => {
|
|
14880
16157
|
});
|
|
14881
|
-
const deselectRef =
|
|
16158
|
+
const deselectRef = useRef10(() => {
|
|
14882
16159
|
});
|
|
14883
|
-
const closeFloatingPanelOnlyRef =
|
|
16160
|
+
const closeFloatingPanelOnlyRef = useRef10(() => {
|
|
14884
16161
|
});
|
|
14885
|
-
const reselectNavigationItemRef =
|
|
16162
|
+
const reselectNavigationItemRef = useRef10(() => {
|
|
14886
16163
|
});
|
|
14887
|
-
const commitNavigationTextEditRef =
|
|
16164
|
+
const commitNavigationTextEditRef = useRef10(() => {
|
|
14888
16165
|
});
|
|
14889
|
-
const handleDeleteSelectedRef =
|
|
14890
|
-
const runPendingDeleteUndoRef =
|
|
14891
|
-
const isFooterFrameSelectionRef =
|
|
14892
|
-
const refreshActiveCommandsRef =
|
|
16166
|
+
const handleDeleteSelectedRef = useRef10(() => false);
|
|
16167
|
+
const runPendingDeleteUndoRef = useRef10(() => false);
|
|
16168
|
+
const isFooterFrameSelectionRef = useRef10(false);
|
|
16169
|
+
const refreshActiveCommandsRef = useRef10(() => {
|
|
14893
16170
|
});
|
|
14894
|
-
const postToParentRef =
|
|
16171
|
+
const postToParentRef = useRef10(postToParent2);
|
|
14895
16172
|
postToParentRef.current = postToParent2;
|
|
14896
|
-
const aiSectionApiRef =
|
|
14897
|
-
const sectionsLoadedRef =
|
|
14898
|
-
const pendingScheduleConfigRequests =
|
|
14899
|
-
const [toolbarRect, setToolbarRect] =
|
|
14900
|
-
const [formPickRect, setFormPickRect] =
|
|
14901
|
-
const formPickElRef =
|
|
14902
|
-
const [formViewState, setFormViewStateUi] =
|
|
14903
|
-
const [formPickCount, setFormPickCount] =
|
|
14904
|
-
const [formHoverRect, setFormHoverRect] =
|
|
14905
|
-
const formHoverElRef =
|
|
14906
|
-
const [fieldPickRect, setFieldPickRect] =
|
|
14907
|
-
const fieldPickElRef =
|
|
14908
|
-
const [fieldPickState, setFieldPickState] =
|
|
14909
|
-
const [fieldTypePickerOpen, setFieldTypePickerOpen] =
|
|
14910
|
-
const clearFormPick =
|
|
16173
|
+
const aiSectionApiRef = useRef10(null);
|
|
16174
|
+
const sectionsLoadedRef = useRef10(false);
|
|
16175
|
+
const pendingScheduleConfigRequests = useRef10([]);
|
|
16176
|
+
const [toolbarRect, setToolbarRect] = useState13(null);
|
|
16177
|
+
const [formPickRect, setFormPickRect] = useState13(null);
|
|
16178
|
+
const formPickElRef = useRef10(null);
|
|
16179
|
+
const [formViewState, setFormViewStateUi] = useState13("default");
|
|
16180
|
+
const [formPickCount, setFormPickCount] = useState13(null);
|
|
16181
|
+
const [formHoverRect, setFormHoverRect] = useState13(null);
|
|
16182
|
+
const formHoverElRef = useRef10(null);
|
|
16183
|
+
const [fieldPickRect, setFieldPickRect] = useState13(null);
|
|
16184
|
+
const fieldPickElRef = useRef10(null);
|
|
16185
|
+
const [fieldPickState, setFieldPickState] = useState13(null);
|
|
16186
|
+
const [fieldTypePickerOpen, setFieldTypePickerOpen] = useState13(false);
|
|
16187
|
+
const clearFormPick = useCallback8(() => {
|
|
14911
16188
|
const form = formPickElRef.current;
|
|
14912
16189
|
const editing = fieldPickElRef.current;
|
|
14913
16190
|
if (commitPlaceholderEdit(editing) && editing) {
|
|
@@ -14927,7 +16204,7 @@ function OhhwellsBridge() {
|
|
|
14927
16204
|
formPickElRef.current = null;
|
|
14928
16205
|
setFormPickRect(null);
|
|
14929
16206
|
}, []);
|
|
14930
|
-
const clearFieldPick =
|
|
16207
|
+
const clearFieldPick = useCallback8(() => {
|
|
14931
16208
|
const wrapper = fieldPickElRef.current;
|
|
14932
16209
|
if (commitPlaceholderEdit(wrapper) && wrapper) {
|
|
14933
16210
|
const form = wrapper.closest('[data-ohw-editable="form"]');
|
|
@@ -14937,9 +16214,9 @@ function OhhwellsBridge() {
|
|
|
14937
16214
|
setFieldPickRect(null);
|
|
14938
16215
|
setFieldPickState(null);
|
|
14939
16216
|
}, []);
|
|
14940
|
-
const persistFieldsRef =
|
|
16217
|
+
const persistFieldsRef = useRef10(() => {
|
|
14941
16218
|
});
|
|
14942
|
-
const persistFields =
|
|
16219
|
+
const persistFields = useCallback8(
|
|
14943
16220
|
(form) => {
|
|
14944
16221
|
const key = formKeyOf(form);
|
|
14945
16222
|
if (!key) return;
|
|
@@ -14950,7 +16227,7 @@ function OhhwellsBridge() {
|
|
|
14950
16227
|
[]
|
|
14951
16228
|
);
|
|
14952
16229
|
persistFieldsRef.current = persistFields;
|
|
14953
|
-
const selectField =
|
|
16230
|
+
const selectField = useCallback8((wrapper) => {
|
|
14954
16231
|
if (fieldPickElRef.current && fieldPickElRef.current !== wrapper) {
|
|
14955
16232
|
commitPlaceholderEdit(fieldPickElRef.current);
|
|
14956
16233
|
}
|
|
@@ -14963,7 +16240,7 @@ function OhhwellsBridge() {
|
|
|
14963
16240
|
setFieldPickState({ type: fieldTypeOf(wrapper), required: isFieldRequired(wrapper) });
|
|
14964
16241
|
setFieldTypePickerOpen(false);
|
|
14965
16242
|
}, []);
|
|
14966
|
-
const withSelectedField =
|
|
16243
|
+
const withSelectedField = useCallback8(
|
|
14967
16244
|
(run) => {
|
|
14968
16245
|
const wrapper = fieldPickElRef.current;
|
|
14969
16246
|
const form = formPickElRef.current;
|
|
@@ -14976,28 +16253,28 @@ function OhhwellsBridge() {
|
|
|
14976
16253
|
},
|
|
14977
16254
|
[persistFields]
|
|
14978
16255
|
);
|
|
14979
|
-
const handleFieldTypeChange =
|
|
16256
|
+
const handleFieldTypeChange = useCallback8(
|
|
14980
16257
|
(type) => withSelectedField((_form, wrapper) => {
|
|
14981
16258
|
applyFieldType(wrapper, type);
|
|
14982
16259
|
selectField(wrapper);
|
|
14983
16260
|
}),
|
|
14984
16261
|
[selectField, withSelectedField]
|
|
14985
16262
|
);
|
|
14986
|
-
const handleFieldRequiredToggle =
|
|
16263
|
+
const handleFieldRequiredToggle = useCallback8(
|
|
14987
16264
|
() => withSelectedField((_form, wrapper) => {
|
|
14988
16265
|
setFieldRequired(wrapper, !isFieldRequired(wrapper));
|
|
14989
16266
|
selectField(wrapper);
|
|
14990
16267
|
}),
|
|
14991
16268
|
[selectField, withSelectedField]
|
|
14992
16269
|
);
|
|
14993
|
-
const handleFieldDuplicate =
|
|
16270
|
+
const handleFieldDuplicate = useCallback8(
|
|
14994
16271
|
() => withSelectedField((form, wrapper) => {
|
|
14995
16272
|
const copy = duplicateField(form, wrapper);
|
|
14996
16273
|
selectField(copy);
|
|
14997
16274
|
}),
|
|
14998
16275
|
[selectField, withSelectedField]
|
|
14999
16276
|
);
|
|
15000
|
-
const handleFieldDelete =
|
|
16277
|
+
const handleFieldDelete = useCallback8(
|
|
15001
16278
|
() => withSelectedField((_form, wrapper) => {
|
|
15002
16279
|
removeField(wrapper);
|
|
15003
16280
|
clearFieldPick();
|
|
@@ -15005,7 +16282,7 @@ function OhhwellsBridge() {
|
|
|
15005
16282
|
}),
|
|
15006
16283
|
[clearFieldPick, withSelectedField]
|
|
15007
16284
|
);
|
|
15008
|
-
const handleAddField =
|
|
16285
|
+
const handleAddField = useCallback8(
|
|
15009
16286
|
(type) => {
|
|
15010
16287
|
const form = formPickElRef.current;
|
|
15011
16288
|
if (!form) return;
|
|
@@ -15021,8 +16298,8 @@ function OhhwellsBridge() {
|
|
|
15021
16298
|
},
|
|
15022
16299
|
[persistFields, selectField]
|
|
15023
16300
|
);
|
|
15024
|
-
const fieldDragRef =
|
|
15025
|
-
const buildFieldDropSlots =
|
|
16301
|
+
const fieldDragRef = useRef10(null);
|
|
16302
|
+
const buildFieldDropSlots = useCallback8((form, draggedKey) => {
|
|
15026
16303
|
const others = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== draggedKey);
|
|
15027
16304
|
const slots = others.map((el) => {
|
|
15028
16305
|
const rect = el.getBoundingClientRect();
|
|
@@ -15035,7 +16312,7 @@ function OhhwellsBridge() {
|
|
|
15035
16312
|
}
|
|
15036
16313
|
return slots;
|
|
15037
16314
|
}, []);
|
|
15038
|
-
const handleFieldDragStart =
|
|
16315
|
+
const handleFieldDragStart = useCallback8(() => {
|
|
15039
16316
|
const wrapper = fieldPickElRef.current;
|
|
15040
16317
|
const form = formPickElRef.current;
|
|
15041
16318
|
if (!wrapper || !form) return;
|
|
@@ -15044,18 +16321,18 @@ function OhhwellsBridge() {
|
|
|
15044
16321
|
setFieldDragging(true);
|
|
15045
16322
|
setFieldDropSlots(buildFieldDropSlots(form, key));
|
|
15046
16323
|
}, [buildFieldDropSlots]);
|
|
15047
|
-
const handleFieldDragEnd =
|
|
16324
|
+
const handleFieldDragEnd = useCallback8(() => {
|
|
15048
16325
|
fieldDragRef.current = null;
|
|
15049
16326
|
setFieldDropIndex(null);
|
|
15050
16327
|
setFieldDropSlots([]);
|
|
15051
16328
|
setFieldDragging(false);
|
|
15052
16329
|
}, []);
|
|
15053
|
-
const [fieldDropIndex, setFieldDropIndex] =
|
|
15054
|
-
const [fieldDropSlots, setFieldDropSlots] =
|
|
15055
|
-
const [fieldDragging, setFieldDragging] =
|
|
15056
|
-
const clearFormPickRef =
|
|
16330
|
+
const [fieldDropIndex, setFieldDropIndex] = useState13(null);
|
|
16331
|
+
const [fieldDropSlots, setFieldDropSlots] = useState13([]);
|
|
16332
|
+
const [fieldDragging, setFieldDragging] = useState13(false);
|
|
16333
|
+
const clearFormPickRef = useRef10(clearFormPick);
|
|
15057
16334
|
clearFormPickRef.current = clearFormPick;
|
|
15058
|
-
|
|
16335
|
+
useEffect13(() => {
|
|
15059
16336
|
const el = fieldPickElRef.current;
|
|
15060
16337
|
if (!el || fieldPickRect === null) return;
|
|
15061
16338
|
const observer = new ResizeObserver(() => {
|
|
@@ -15064,7 +16341,7 @@ function OhhwellsBridge() {
|
|
|
15064
16341
|
observer.observe(el);
|
|
15065
16342
|
return () => observer.disconnect();
|
|
15066
16343
|
}, [fieldPickRect !== null, fieldPickState]);
|
|
15067
|
-
|
|
16344
|
+
useEffect13(() => {
|
|
15068
16345
|
const el = formPickElRef.current;
|
|
15069
16346
|
if (!el || formPickRect === null) return;
|
|
15070
16347
|
const observer = new ResizeObserver(() => {
|
|
@@ -15073,25 +16350,25 @@ function OhhwellsBridge() {
|
|
|
15073
16350
|
observer.observe(el);
|
|
15074
16351
|
return () => observer.disconnect();
|
|
15075
16352
|
}, [formPickRect !== null, formViewState]);
|
|
15076
|
-
const [toolbarVariant, setToolbarVariant] =
|
|
15077
|
-
const toolbarVariantRef =
|
|
16353
|
+
const [toolbarVariant, setToolbarVariant] = useState13("none");
|
|
16354
|
+
const toolbarVariantRef = useRef10("none");
|
|
15078
16355
|
toolbarVariantRef.current = toolbarVariant;
|
|
15079
|
-
const [selectedIsCta, setSelectedIsCta] =
|
|
15080
|
-
const [selectedIsSocial, setSelectedIsSocial] =
|
|
15081
|
-
const [selectedIsSocialsRow, setSelectedIsSocialsRow] =
|
|
15082
|
-
const [reorderHrefKey, setReorderHrefKey] =
|
|
15083
|
-
const [reorderDragDisabled, setReorderDragDisabled] =
|
|
15084
|
-
const [toggleState, setToggleState] =
|
|
15085
|
-
const [maxBadge, setMaxBadge] =
|
|
15086
|
-
const [activeCommands, setActiveCommands] =
|
|
15087
|
-
const [sectionGap, setSectionGap] =
|
|
15088
|
-
const [toolbarShowEditLink, setToolbarShowEditLink] =
|
|
15089
|
-
const hoveredNavContainerRef =
|
|
15090
|
-
const [hoveredNavContainerRect, setHoveredNavContainerRect] =
|
|
15091
|
-
const hoveredItemElRef =
|
|
15092
|
-
const [hoveredItemRect, setHoveredItemRect] =
|
|
15093
|
-
const [hoveredTextRect, setHoveredTextRect] =
|
|
15094
|
-
|
|
16356
|
+
const [selectedIsCta, setSelectedIsCta] = useState13(false);
|
|
16357
|
+
const [selectedIsSocial, setSelectedIsSocial] = useState13(false);
|
|
16358
|
+
const [selectedIsSocialsRow, setSelectedIsSocialsRow] = useState13(false);
|
|
16359
|
+
const [reorderHrefKey, setReorderHrefKey] = useState13(null);
|
|
16360
|
+
const [reorderDragDisabled, setReorderDragDisabled] = useState13(false);
|
|
16361
|
+
const [toggleState, setToggleState] = useState13(null);
|
|
16362
|
+
const [maxBadge, setMaxBadge] = useState13(null);
|
|
16363
|
+
const [activeCommands, setActiveCommands] = useState13(/* @__PURE__ */ new Set());
|
|
16364
|
+
const [sectionGap, setSectionGap] = useState13(null);
|
|
16365
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = useState13(false);
|
|
16366
|
+
const hoveredNavContainerRef = useRef10(null);
|
|
16367
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState13(null);
|
|
16368
|
+
const hoveredItemElRef = useRef10(null);
|
|
16369
|
+
const [hoveredItemRect, setHoveredItemRect] = useState13(null);
|
|
16370
|
+
const [hoveredTextRect, setHoveredTextRect] = useState13(null);
|
|
16371
|
+
useEffect13(() => {
|
|
15095
16372
|
const sync = () => {
|
|
15096
16373
|
const el = document.querySelector(
|
|
15097
16374
|
'[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]):not([data-ohw-editable="form"] *)'
|
|
@@ -15116,43 +16393,56 @@ function OhhwellsBridge() {
|
|
|
15116
16393
|
});
|
|
15117
16394
|
return () => observer.disconnect();
|
|
15118
16395
|
}, []);
|
|
15119
|
-
const siblingHintElRef =
|
|
15120
|
-
const [siblingHintRect, setSiblingHintRect] =
|
|
15121
|
-
const [siblingHintRects, setSiblingHintRects] =
|
|
15122
|
-
const [isItemDragging, setIsItemDragging] =
|
|
15123
|
-
const [isFooterFrameSelection, setIsFooterFrameSelection] =
|
|
16396
|
+
const siblingHintElRef = useRef10(null);
|
|
16397
|
+
const [siblingHintRect, setSiblingHintRect] = useState13(null);
|
|
16398
|
+
const [siblingHintRects, setSiblingHintRects] = useState13([]);
|
|
16399
|
+
const [isItemDragging, setIsItemDragging] = useState13(false);
|
|
16400
|
+
const [isFooterFrameSelection, setIsFooterFrameSelection] = useState13(false);
|
|
15124
16401
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
15125
|
-
const [
|
|
15126
|
-
const
|
|
15127
|
-
|
|
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
|
|
15153
|
-
const
|
|
16402
|
+
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState13(null);
|
|
16403
|
+
const [footerHeadingVisible, setFooterHeadingVisible] = useState13(null);
|
|
16404
|
+
const footerDragRef = useRef10(null);
|
|
16405
|
+
const [footerDropSlots, setFooterDropSlots] = useState13([]);
|
|
16406
|
+
const [activeFooterDropIndex, setActiveFooterDropIndex] = useState13(null);
|
|
16407
|
+
const [draggedItemRect, setDraggedItemRect] = useState13(null);
|
|
16408
|
+
const footerPointerDragRef = useRef10(null);
|
|
16409
|
+
const suppressNextClickRef = useRef10(false);
|
|
16410
|
+
const suppressClickUntilRef = useRef10(0);
|
|
16411
|
+
const [linkPopover, setLinkPopover] = useState13(null);
|
|
16412
|
+
const linkPopoverSessionRef = useRef10(null);
|
|
16413
|
+
const addNavAfterAnchorRef = useRef10(null);
|
|
16414
|
+
const editContentRef = useRef10({});
|
|
16415
|
+
const aiSectionsRef = useRef10("");
|
|
16416
|
+
const brandKitRef = useRef10("");
|
|
16417
|
+
const stylesRef = useRef10("");
|
|
16418
|
+
const pendingDeleteUndoRef = useRef10(null);
|
|
16419
|
+
const [floatingPanel, setFloatingPanel] = useState13(null);
|
|
16420
|
+
const floatingPanelOpenRef = useRef10(false);
|
|
16421
|
+
const setFloatingPanelRef = useRef10(setFloatingPanel);
|
|
16422
|
+
const [floatingPanelPos, setFloatingPanelPos] = useState13(null);
|
|
16423
|
+
const [logoSizeDraft, setLogoSizeDraft] = useState13(null);
|
|
16424
|
+
const [editorViewport, setEditorViewport] = useState13("desktop");
|
|
16425
|
+
const [parentScrollSnap, setParentScrollSnap] = useState13(null);
|
|
16426
|
+
const [sitePages, setSitePages] = useState13([]);
|
|
16427
|
+
const [sectionsByPath, setSectionsByPath] = useState13({});
|
|
16428
|
+
const sectionsPrefetchGenRef = useRef10(0);
|
|
16429
|
+
const setLinkPopoverRef = useRef10(setLinkPopover);
|
|
16430
|
+
const linkPopoverPanelRef = useRef10(null);
|
|
16431
|
+
const linkPopoverOpenRef = useRef10(false);
|
|
16432
|
+
const linkPopoverGraceUntilRef = useRef10(0);
|
|
15154
16433
|
setLinkPopoverRef.current = setLinkPopover;
|
|
16434
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
15155
16435
|
linkPopoverSessionRef.current = linkPopover;
|
|
16436
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
16437
|
+
useEffect13(() => {
|
|
16438
|
+
const syncViewport = () => {
|
|
16439
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
16440
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
16441
|
+
};
|
|
16442
|
+
syncViewport();
|
|
16443
|
+
window.addEventListener("resize", syncViewport);
|
|
16444
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
16445
|
+
}, []);
|
|
15156
16446
|
const {
|
|
15157
16447
|
navDragRef,
|
|
15158
16448
|
navDropSlots,
|
|
@@ -15185,10 +16475,20 @@ function OhhwellsBridge() {
|
|
|
15185
16475
|
getNavigationItemAnchor,
|
|
15186
16476
|
isDragHandleDisabled
|
|
15187
16477
|
});
|
|
16478
|
+
const { sectionDropSlots, activeSectionDropIndex, isSectionDragging } = useSectionDrag({
|
|
16479
|
+
isEditMode,
|
|
16480
|
+
editContentRef,
|
|
16481
|
+
postToParentRef,
|
|
16482
|
+
parentScrollRef,
|
|
16483
|
+
navDragRef,
|
|
16484
|
+
footerDragRef,
|
|
16485
|
+
suppressNextClickRef,
|
|
16486
|
+
suppressClickUntilRef
|
|
16487
|
+
});
|
|
15188
16488
|
const bumpLinkPopoverGrace = () => {
|
|
15189
16489
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
15190
16490
|
};
|
|
15191
|
-
const runSectionsPrefetch =
|
|
16491
|
+
const runSectionsPrefetch = useCallback8((pages) => {
|
|
15192
16492
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
15193
16493
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
15194
16494
|
const paths = pages.map((p) => p.path);
|
|
@@ -15207,9 +16507,9 @@ function OhhwellsBridge() {
|
|
|
15207
16507
|
);
|
|
15208
16508
|
});
|
|
15209
16509
|
}, [isEditMode, pathname]);
|
|
15210
|
-
const runSectionsPrefetchRef =
|
|
16510
|
+
const runSectionsPrefetchRef = useRef10(runSectionsPrefetch);
|
|
15211
16511
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
15212
|
-
|
|
16512
|
+
useEffect13(() => {
|
|
15213
16513
|
if (!linkPopover) {
|
|
15214
16514
|
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
15215
16515
|
return;
|
|
@@ -15237,7 +16537,7 @@ function OhhwellsBridge() {
|
|
|
15237
16537
|
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
15238
16538
|
};
|
|
15239
16539
|
}, [linkPopover, postToParent2]);
|
|
15240
|
-
|
|
16540
|
+
useEffect13(() => {
|
|
15241
16541
|
if (!isEditMode) return;
|
|
15242
16542
|
const useFixtures = shouldUseDevFixtures();
|
|
15243
16543
|
if (useFixtures) {
|
|
@@ -15261,14 +16561,14 @@ function OhhwellsBridge() {
|
|
|
15261
16561
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
15262
16562
|
return () => window.removeEventListener("message", onSitePages);
|
|
15263
16563
|
}, [isEditMode, postToParent2]);
|
|
15264
|
-
|
|
16564
|
+
useEffect13(() => {
|
|
15265
16565
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
15266
16566
|
void loadAllSectionsManifest().then((manifest) => {
|
|
15267
16567
|
if (Object.keys(manifest).length === 0) return;
|
|
15268
16568
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
15269
16569
|
});
|
|
15270
16570
|
}, [isEditMode]);
|
|
15271
|
-
|
|
16571
|
+
useEffect13(() => {
|
|
15272
16572
|
const update = () => {
|
|
15273
16573
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
15274
16574
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -15292,10 +16592,10 @@ function OhhwellsBridge() {
|
|
|
15292
16592
|
vvp.removeEventListener("resize", update);
|
|
15293
16593
|
};
|
|
15294
16594
|
}, []);
|
|
15295
|
-
const refreshStateRules =
|
|
16595
|
+
const refreshStateRules = useCallback8(() => {
|
|
15296
16596
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
15297
16597
|
}, []);
|
|
15298
|
-
const processConfigRequest =
|
|
16598
|
+
const processConfigRequest = useCallback8((insertAfterVal) => {
|
|
15299
16599
|
const tracker = getSectionsTracker();
|
|
15300
16600
|
let entries = [];
|
|
15301
16601
|
try {
|
|
@@ -15318,7 +16618,7 @@ function OhhwellsBridge() {
|
|
|
15318
16618
|
}
|
|
15319
16619
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
15320
16620
|
}, [isEditMode]);
|
|
15321
|
-
const deactivate =
|
|
16621
|
+
const deactivate = useCallback8(() => {
|
|
15322
16622
|
const el = activeElRef.current;
|
|
15323
16623
|
if (!el) return;
|
|
15324
16624
|
const isFormBlock = el.dataset.ohwEditable === "form";
|
|
@@ -15334,7 +16634,7 @@ function OhhwellsBridge() {
|
|
|
15334
16634
|
const original = originalContentRef.current ?? "";
|
|
15335
16635
|
if (html !== sanitizeHtml(original)) {
|
|
15336
16636
|
postToParentRef.current({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
15337
|
-
const h = document.
|
|
16637
|
+
const h = document.body.scrollHeight;
|
|
15338
16638
|
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
15339
16639
|
}
|
|
15340
16640
|
}
|
|
@@ -15359,12 +16659,12 @@ function OhhwellsBridge() {
|
|
|
15359
16659
|
setToolbarShowEditLink(false);
|
|
15360
16660
|
postToParent2({ type: "ow:exit-edit" });
|
|
15361
16661
|
}, [postToParent2]);
|
|
15362
|
-
const clearSelectedAttr =
|
|
16662
|
+
const clearSelectedAttr = useCallback8(() => {
|
|
15363
16663
|
document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
|
|
15364
16664
|
el.removeAttribute("data-ohw-selected");
|
|
15365
16665
|
});
|
|
15366
16666
|
}, []);
|
|
15367
|
-
const deselect =
|
|
16667
|
+
const deselect = useCallback8(() => {
|
|
15368
16668
|
clearSelectedAttr();
|
|
15369
16669
|
selectedElRef.current = null;
|
|
15370
16670
|
selectedHrefKeyRef.current = null;
|
|
@@ -15393,20 +16693,20 @@ function OhhwellsBridge() {
|
|
|
15393
16693
|
setToolbarVariant("none");
|
|
15394
16694
|
}
|
|
15395
16695
|
}, [clearSelectedAttr]);
|
|
15396
|
-
const markSelected =
|
|
16696
|
+
const markSelected = useCallback8((el) => {
|
|
15397
16697
|
clearSelectedAttr();
|
|
15398
16698
|
el.removeAttribute("data-ohw-hovered");
|
|
15399
16699
|
el.setAttribute("data-ohw-selected", "");
|
|
15400
16700
|
}, [clearSelectedAttr]);
|
|
15401
|
-
const isSelectedForHover =
|
|
16701
|
+
const isSelectedForHover = useCallback8((el) => {
|
|
15402
16702
|
if (!el) return false;
|
|
15403
16703
|
return [selectedElRef.current, activeElRef.current].some(
|
|
15404
16704
|
(busy) => busy && (el === busy || busy.contains(el) || el.contains(busy))
|
|
15405
16705
|
);
|
|
15406
16706
|
}, []);
|
|
15407
|
-
const isSelectedForHoverRef =
|
|
16707
|
+
const isSelectedForHoverRef = useRef10(isSelectedForHover);
|
|
15408
16708
|
isSelectedForHoverRef.current = isSelectedForHover;
|
|
15409
|
-
const resolveHrefKeyElement =
|
|
16709
|
+
const resolveHrefKeyElement = useCallback8((hrefKey) => {
|
|
15410
16710
|
if (isFooterHrefKey(hrefKey)) {
|
|
15411
16711
|
return document.querySelector(
|
|
15412
16712
|
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
@@ -15421,7 +16721,7 @@ function OhhwellsBridge() {
|
|
|
15421
16721
|
`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
15422
16722
|
);
|
|
15423
16723
|
}, []);
|
|
15424
|
-
const resyncSelectedNavigationItem =
|
|
16724
|
+
const resyncSelectedNavigationItem = useCallback8(() => {
|
|
15425
16725
|
const hrefKey = selectedHrefKeyRef.current;
|
|
15426
16726
|
if (hrefKey) {
|
|
15427
16727
|
const link = resolveHrefKeyElement(hrefKey);
|
|
@@ -15459,7 +16759,7 @@ function OhhwellsBridge() {
|
|
|
15459
16759
|
);
|
|
15460
16760
|
}
|
|
15461
16761
|
}, [resolveHrefKeyElement]);
|
|
15462
|
-
const reselectNavigationItem =
|
|
16762
|
+
const reselectNavigationItem = useCallback8((navAnchor) => {
|
|
15463
16763
|
selectedElRef.current = navAnchor;
|
|
15464
16764
|
selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
|
|
15465
16765
|
selectedFooterColAttrRef.current = null;
|
|
@@ -15490,7 +16790,7 @@ function OhhwellsBridge() {
|
|
|
15490
16790
|
setToolbarShowEditLink(false);
|
|
15491
16791
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
15492
16792
|
}, [markSelected]);
|
|
15493
|
-
const commitNavigationTextEdit =
|
|
16793
|
+
const commitNavigationTextEdit = useCallback8((navAnchor) => {
|
|
15494
16794
|
const el = activeElRef.current;
|
|
15495
16795
|
if (!el) return;
|
|
15496
16796
|
const key = el.dataset.ohwKey;
|
|
@@ -15504,7 +16804,7 @@ function OhhwellsBridge() {
|
|
|
15504
16804
|
const original = originalContentRef.current ?? "";
|
|
15505
16805
|
if (html !== sanitizeHtml(original)) {
|
|
15506
16806
|
postToParent2({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
15507
|
-
const h = document.
|
|
16807
|
+
const h = document.body.scrollHeight;
|
|
15508
16808
|
if (h > 50) postToParent2({ type: "ow:height", height: h });
|
|
15509
16809
|
}
|
|
15510
16810
|
}
|
|
@@ -15523,7 +16823,7 @@ function OhhwellsBridge() {
|
|
|
15523
16823
|
postToParent2({ type: "ow:exit-edit" });
|
|
15524
16824
|
reselectNavigationItem(navAnchor);
|
|
15525
16825
|
}, [postToParent2, reselectNavigationItem]);
|
|
15526
|
-
const handleAddTopLevelNavItem =
|
|
16826
|
+
const handleAddTopLevelNavItem = useCallback8(() => {
|
|
15527
16827
|
const items = listNavbarRootItems();
|
|
15528
16828
|
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
15529
16829
|
deselectRef.current();
|
|
@@ -15535,7 +16835,7 @@ function OhhwellsBridge() {
|
|
|
15535
16835
|
intent: "add-nav"
|
|
15536
16836
|
});
|
|
15537
16837
|
}, []);
|
|
15538
|
-
const maybeWarnNavLinkDropdownConflict =
|
|
16838
|
+
const maybeWarnNavLinkDropdownConflict = useCallback8(
|
|
15539
16839
|
(anchor) => {
|
|
15540
16840
|
if (!isNavbarHrefKey(anchor.getAttribute("data-ohw-href-key"))) return;
|
|
15541
16841
|
if (!navDropdownsOpenOnClick()) return;
|
|
@@ -15548,7 +16848,7 @@ function OhhwellsBridge() {
|
|
|
15548
16848
|
},
|
|
15549
16849
|
[postToParent2]
|
|
15550
16850
|
);
|
|
15551
|
-
const handleNavDropdownOpenChange =
|
|
16851
|
+
const handleNavDropdownOpenChange = useCallback8((open) => {
|
|
15552
16852
|
const selected = selectedElRef.current;
|
|
15553
16853
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
15554
16854
|
setNavGroupForceOpen(selected, open);
|
|
@@ -15560,7 +16860,7 @@ function OhhwellsBridge() {
|
|
|
15560
16860
|
}
|
|
15561
16861
|
});
|
|
15562
16862
|
}, []);
|
|
15563
|
-
const handleFooterHeadingVisibleChange =
|
|
16863
|
+
const handleFooterHeadingVisibleChange = useCallback8(
|
|
15564
16864
|
(visible) => {
|
|
15565
16865
|
const selected = selectedElRef.current;
|
|
15566
16866
|
if (!selected || !isFooterFrameSelectionRef.current) return;
|
|
@@ -15584,7 +16884,7 @@ function OhhwellsBridge() {
|
|
|
15584
16884
|
},
|
|
15585
16885
|
[postToParent2]
|
|
15586
16886
|
);
|
|
15587
|
-
const enterEditOnNewItem =
|
|
16887
|
+
const enterEditOnNewItem = useCallback8((anchor) => {
|
|
15588
16888
|
const label = anchor.querySelector('[data-ohw-editable="text"]');
|
|
15589
16889
|
if (!label) {
|
|
15590
16890
|
selectRef.current(anchor);
|
|
@@ -15593,8 +16893,8 @@ function OhhwellsBridge() {
|
|
|
15593
16893
|
setNavGroupForceOpen(anchor, true);
|
|
15594
16894
|
activateRef.current(label);
|
|
15595
16895
|
}, []);
|
|
15596
|
-
const pendingSocialAddRef =
|
|
15597
|
-
const handleAddChildItem =
|
|
16896
|
+
const pendingSocialAddRef = useRef10(null);
|
|
16897
|
+
const handleAddChildItem = useCallback8(() => {
|
|
15598
16898
|
const selected = selectedElRef.current;
|
|
15599
16899
|
if (!selected) return;
|
|
15600
16900
|
const socialsRow = isSocialsRow(selected) ? selected : findSocialsRow(selected);
|
|
@@ -15703,7 +17003,7 @@ function OhhwellsBridge() {
|
|
|
15703
17003
|
enterEditOnNewItem(result.anchor);
|
|
15704
17004
|
});
|
|
15705
17005
|
}, [enterEditOnNewItem, isFooterFrameSelection, maybeWarnNavLinkDropdownConflict, postToParent2]);
|
|
15706
|
-
const handleAddFooterColumn =
|
|
17006
|
+
const handleAddFooterColumn = useCallback8(() => {
|
|
15707
17007
|
if (!canAddFooterColumn()) {
|
|
15708
17008
|
postToParent2({
|
|
15709
17009
|
type: "ow:toast",
|
|
@@ -15724,7 +17024,7 @@ function OhhwellsBridge() {
|
|
|
15724
17024
|
selectRef.current(result.firstLink);
|
|
15725
17025
|
});
|
|
15726
17026
|
}, [postToParent2]);
|
|
15727
|
-
const clearFooterDragVisuals =
|
|
17027
|
+
const clearFooterDragVisuals = useCallback8(() => {
|
|
15728
17028
|
footerDragRef.current = null;
|
|
15729
17029
|
setSiblingHintRects([]);
|
|
15730
17030
|
setFooterDropSlots([]);
|
|
@@ -15733,7 +17033,7 @@ function OhhwellsBridge() {
|
|
|
15733
17033
|
setIsItemDragging(false);
|
|
15734
17034
|
unlockFooterDragInteraction();
|
|
15735
17035
|
}, []);
|
|
15736
|
-
const refreshFooterDragVisuals =
|
|
17036
|
+
const refreshFooterDragVisuals = useCallback8((session, activeSlot, clientX, clientY) => {
|
|
15737
17037
|
const dragged = session.draggedEl;
|
|
15738
17038
|
setDraggedItemRect(dragged.getBoundingClientRect());
|
|
15739
17039
|
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
@@ -15765,13 +17065,13 @@ function OhhwellsBridge() {
|
|
|
15765
17065
|
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
15766
17066
|
setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
15767
17067
|
}, []);
|
|
15768
|
-
const refreshFooterDragVisualsRef =
|
|
17068
|
+
const refreshFooterDragVisualsRef = useRef10(refreshFooterDragVisuals);
|
|
15769
17069
|
refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
|
|
15770
|
-
const commitFooterDragRef =
|
|
17070
|
+
const commitFooterDragRef = useRef10(() => {
|
|
15771
17071
|
});
|
|
15772
|
-
const beginFooterDragRef =
|
|
17072
|
+
const beginFooterDragRef = useRef10(() => {
|
|
15773
17073
|
});
|
|
15774
|
-
const beginFooterDrag =
|
|
17074
|
+
const beginFooterDrag = useCallback8(
|
|
15775
17075
|
(session) => {
|
|
15776
17076
|
const rect = session.draggedEl.getBoundingClientRect();
|
|
15777
17077
|
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
@@ -15791,7 +17091,7 @@ function OhhwellsBridge() {
|
|
|
15791
17091
|
[refreshFooterDragVisuals]
|
|
15792
17092
|
);
|
|
15793
17093
|
beginFooterDragRef.current = beginFooterDrag;
|
|
15794
|
-
const commitFooterDrag =
|
|
17094
|
+
const commitFooterDrag = useCallback8(
|
|
15795
17095
|
(clientX, clientY) => {
|
|
15796
17096
|
const session = footerDragRef.current;
|
|
15797
17097
|
if (!session) {
|
|
@@ -15920,7 +17220,7 @@ function OhhwellsBridge() {
|
|
|
15920
17220
|
[clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
|
|
15921
17221
|
);
|
|
15922
17222
|
commitFooterDragRef.current = commitFooterDrag;
|
|
15923
|
-
const startFooterLinkDrag =
|
|
17223
|
+
const startFooterLinkDrag = useCallback8(
|
|
15924
17224
|
(anchor, clientX, clientY, wasSelected) => {
|
|
15925
17225
|
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
15926
17226
|
if (!hrefKey) return false;
|
|
@@ -15956,7 +17256,7 @@ function OhhwellsBridge() {
|
|
|
15956
17256
|
},
|
|
15957
17257
|
[beginFooterDrag]
|
|
15958
17258
|
);
|
|
15959
|
-
const startFooterColumnDrag =
|
|
17259
|
+
const startFooterColumnDrag = useCallback8(
|
|
15960
17260
|
(columnEl, clientX, clientY, wasSelected) => {
|
|
15961
17261
|
const columns = listFooterColumns();
|
|
15962
17262
|
const idx = columns.indexOf(columnEl);
|
|
@@ -15976,7 +17276,7 @@ function OhhwellsBridge() {
|
|
|
15976
17276
|
},
|
|
15977
17277
|
[beginFooterDrag]
|
|
15978
17278
|
);
|
|
15979
|
-
const handleItemDragStart =
|
|
17279
|
+
const handleItemDragStart = useCallback8(
|
|
15980
17280
|
(e) => {
|
|
15981
17281
|
const selected = selectedElRef.current;
|
|
15982
17282
|
if (!selected) {
|
|
@@ -15996,7 +17296,7 @@ function OhhwellsBridge() {
|
|
|
15996
17296
|
},
|
|
15997
17297
|
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
|
|
15998
17298
|
);
|
|
15999
|
-
const handleItemDragEnd =
|
|
17299
|
+
const handleItemDragEnd = useCallback8(
|
|
16000
17300
|
(e) => {
|
|
16001
17301
|
if (footerDragRef.current) {
|
|
16002
17302
|
const x = e?.clientX;
|
|
@@ -16022,7 +17322,7 @@ function OhhwellsBridge() {
|
|
|
16022
17322
|
},
|
|
16023
17323
|
[commitFooterDrag, commitNavDrag, navDragRef]
|
|
16024
17324
|
);
|
|
16025
|
-
const handleItemChromePointerDown =
|
|
17325
|
+
const handleItemChromePointerDown = useCallback8((e) => {
|
|
16026
17326
|
if (e.button !== 0) return;
|
|
16027
17327
|
const selected = selectedElRef.current;
|
|
16028
17328
|
if (!selected) return;
|
|
@@ -16053,7 +17353,7 @@ function OhhwellsBridge() {
|
|
|
16053
17353
|
}
|
|
16054
17354
|
if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
|
|
16055
17355
|
}, [armNavPressFromChrome]);
|
|
16056
|
-
const handleItemChromeClick =
|
|
17356
|
+
const handleItemChromeClick = useCallback8((clientX, clientY) => {
|
|
16057
17357
|
if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
|
|
16058
17358
|
suppressNextClickRef.current = false;
|
|
16059
17359
|
return;
|
|
@@ -16066,7 +17366,7 @@ function OhhwellsBridge() {
|
|
|
16066
17366
|
}, []);
|
|
16067
17367
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
16068
17368
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
16069
|
-
const select =
|
|
17369
|
+
const select = useCallback8((anchor) => {
|
|
16070
17370
|
if (!isNavigationItem2(anchor)) return;
|
|
16071
17371
|
if (activeElRef.current) deactivate();
|
|
16072
17372
|
aiSectionApiRef.current?.selectFromElement(anchor);
|
|
@@ -16109,7 +17409,7 @@ function OhhwellsBridge() {
|
|
|
16109
17409
|
setFloatingPanel(null);
|
|
16110
17410
|
setLogoSizeDraft(null);
|
|
16111
17411
|
}, [deactivate, markSelected]);
|
|
16112
|
-
const selectFrame =
|
|
17412
|
+
const selectFrame = useCallback8((el) => {
|
|
16113
17413
|
if (!isNavigationContainer(el)) return;
|
|
16114
17414
|
if (activeElRef.current) deactivate();
|
|
16115
17415
|
aiSectionApiRef.current?.selectFromElement(el);
|
|
@@ -16160,7 +17460,7 @@ function OhhwellsBridge() {
|
|
|
16160
17460
|
setFloatingPanel(null);
|
|
16161
17461
|
setLogoSizeDraft(null);
|
|
16162
17462
|
}, [deactivate, markSelected, postToParent2]);
|
|
16163
|
-
const selectLogo =
|
|
17463
|
+
const selectLogo = useCallback8(
|
|
16164
17464
|
(logoEl) => {
|
|
16165
17465
|
if (activeElRef.current) deactivate();
|
|
16166
17466
|
selectedElRef.current = logoEl;
|
|
@@ -16189,7 +17489,7 @@ function OhhwellsBridge() {
|
|
|
16189
17489
|
},
|
|
16190
17490
|
[deactivate, markSelected]
|
|
16191
17491
|
);
|
|
16192
|
-
const openLogoSizePanel =
|
|
17492
|
+
const openLogoSizePanel = useCallback8((logoEl) => {
|
|
16193
17493
|
const placement = getLogoPlacement(logoEl);
|
|
16194
17494
|
const draft = readLogoSizeState(editContentRef.current, placement);
|
|
16195
17495
|
setLogoSizeDraft(draft);
|
|
@@ -16202,7 +17502,7 @@ function OhhwellsBridge() {
|
|
|
16202
17502
|
placement
|
|
16203
17503
|
});
|
|
16204
17504
|
}, []);
|
|
16205
|
-
const openSocialsDisplayPanel =
|
|
17505
|
+
const openSocialsDisplayPanel = useCallback8((row) => {
|
|
16206
17506
|
setParentScrollSnap(parentScrollRef.current);
|
|
16207
17507
|
setFloatingPanel({
|
|
16208
17508
|
key: "socials-display",
|
|
@@ -16212,11 +17512,11 @@ function OhhwellsBridge() {
|
|
|
16212
17512
|
row
|
|
16213
17513
|
});
|
|
16214
17514
|
}, []);
|
|
16215
|
-
const isEditModeRef =
|
|
16216
|
-
const requestMissingSocialIconsRef =
|
|
17515
|
+
const isEditModeRef = useRef10(false);
|
|
17516
|
+
const requestMissingSocialIconsRef = useRef10(() => {
|
|
16217
17517
|
});
|
|
16218
|
-
const askedSocialIconsRef =
|
|
16219
|
-
const requestMissingSocialIcons =
|
|
17518
|
+
const askedSocialIconsRef = useRef10(/* @__PURE__ */ new Set());
|
|
17519
|
+
const requestMissingSocialIcons = useCallback8(() => {
|
|
16220
17520
|
const items = Array.from(document.querySelectorAll(`[${SOCIALS_ROW_ATTR}]`)).filter((row) => socialsDisplayFor(row, editContentRef.current).icon).flatMap((row) => {
|
|
16221
17521
|
const missing = socialsMissingIcons(row);
|
|
16222
17522
|
listSocialItems(row).forEach((item) => ensureIconSlot(item));
|
|
@@ -16228,7 +17528,7 @@ function OhhwellsBridge() {
|
|
|
16228
17528
|
}, []);
|
|
16229
17529
|
requestMissingSocialIconsRef.current = requestMissingSocialIcons;
|
|
16230
17530
|
isEditModeRef.current = isEditMode;
|
|
16231
|
-
const changeSocialsDisplay =
|
|
17531
|
+
const changeSocialsDisplay = useCallback8(
|
|
16232
17532
|
(row, next) => {
|
|
16233
17533
|
if (next.icon) {
|
|
16234
17534
|
const missing = socialsMissingIcons(row);
|
|
@@ -16252,17 +17552,17 @@ function OhhwellsBridge() {
|
|
|
16252
17552
|
},
|
|
16253
17553
|
[]
|
|
16254
17554
|
);
|
|
16255
|
-
const closeFloatingPanelOnly =
|
|
17555
|
+
const closeFloatingPanelOnly = useCallback8(() => {
|
|
16256
17556
|
setFloatingPanel(null);
|
|
16257
17557
|
setLogoSizeDraft(null);
|
|
16258
17558
|
}, []);
|
|
16259
17559
|
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
16260
|
-
const closeFloatingPanelAndDeselect =
|
|
17560
|
+
const closeFloatingPanelAndDeselect = useCallback8(() => {
|
|
16261
17561
|
setFloatingPanel(null);
|
|
16262
17562
|
setLogoSizeDraft(null);
|
|
16263
17563
|
deselectRef.current();
|
|
16264
17564
|
}, []);
|
|
16265
|
-
|
|
17565
|
+
useEffect13(() => {
|
|
16266
17566
|
const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
|
|
16267
17567
|
if (!session || !logoSizeDraft) {
|
|
16268
17568
|
postToParentRef.current({ type: "ow:logo-size-panel", open: false });
|
|
@@ -16281,7 +17581,7 @@ function OhhwellsBridge() {
|
|
|
16281
17581
|
max: LOGO_SIZE_MAX
|
|
16282
17582
|
});
|
|
16283
17583
|
}, [floatingPanel, logoSizeDraft, editorViewport]);
|
|
16284
|
-
const persistLogoSizeDraft =
|
|
17584
|
+
const persistLogoSizeDraft = useCallback8(
|
|
16285
17585
|
(placement, draft) => {
|
|
16286
17586
|
const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
|
|
16287
17587
|
const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
|
|
@@ -16321,7 +17621,7 @@ function OhhwellsBridge() {
|
|
|
16321
17621
|
},
|
|
16322
17622
|
[postToParent2]
|
|
16323
17623
|
);
|
|
16324
|
-
const activate =
|
|
17624
|
+
const activate = useCallback8((el, options) => {
|
|
16325
17625
|
if (activeElRef.current === el) return;
|
|
16326
17626
|
document.querySelectorAll("[data-ohw-hovered]").forEach((hovered) => {
|
|
16327
17627
|
hovered.removeAttribute("data-ohw-hovered");
|
|
@@ -16419,8 +17719,8 @@ function OhhwellsBridge() {
|
|
|
16419
17719
|
openLogoSizePanelRef.current = openLogoSizePanel;
|
|
16420
17720
|
deselectRef.current = deselect;
|
|
16421
17721
|
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
16422
|
-
const lastSiteWideScopeRef =
|
|
16423
|
-
|
|
17722
|
+
const lastSiteWideScopeRef = useRef10(null);
|
|
17723
|
+
useEffect13(() => {
|
|
16424
17724
|
if (!isEditMode) {
|
|
16425
17725
|
if (lastSiteWideScopeRef.current !== false) {
|
|
16426
17726
|
lastSiteWideScopeRef.current = false;
|
|
@@ -16453,15 +17753,31 @@ function OhhwellsBridge() {
|
|
|
16453
17753
|
}
|
|
16454
17754
|
const applyContent = (content) => {
|
|
16455
17755
|
const imageLoads = [];
|
|
17756
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
17757
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
17758
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
17759
|
+
} else {
|
|
17760
|
+
brandKitRef.current = "";
|
|
17761
|
+
applyBrandToDom(null);
|
|
17762
|
+
}
|
|
16456
17763
|
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
16457
17764
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
17765
|
+
setAiSectionOrder(content[SECTION_ORDER_KEY], window.location.pathname);
|
|
16458
17766
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
16459
17767
|
}
|
|
17768
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
17769
|
+
stylesRef.current = content[STYLE_STORE_KEY];
|
|
17770
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
17771
|
+
}
|
|
17772
|
+
applyBrandChrome(content);
|
|
16460
17773
|
for (const [key, val] of Object.entries(content)) {
|
|
16461
17774
|
if (key === "__ohw_sections") continue;
|
|
16462
17775
|
if (key === AI_SECTIONS_KEY) continue;
|
|
16463
17776
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
16464
17777
|
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
17778
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
17779
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17780
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
16465
17781
|
if (applyVideoSettingNode(key, val)) continue;
|
|
16466
17782
|
if (applyCarouselNode(key, val)) continue;
|
|
16467
17783
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -16527,7 +17843,9 @@ function OhhwellsBridge() {
|
|
|
16527
17843
|
let cancelled = false;
|
|
16528
17844
|
setFetchState("loading");
|
|
16529
17845
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
16530
|
-
|
|
17846
|
+
const initialPath = pathname;
|
|
17847
|
+
fetchedContentPaths.add(`${subdomain}::${initialPath}`);
|
|
17848
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
16531
17849
|
if (cancelled) return;
|
|
16532
17850
|
const content = data?.content ?? {};
|
|
16533
17851
|
contentCache.set(subdomain, content);
|
|
@@ -16540,7 +17858,7 @@ function OhhwellsBridge() {
|
|
|
16540
17858
|
cancelled = true;
|
|
16541
17859
|
};
|
|
16542
17860
|
}, [subdomain, isEditMode]);
|
|
16543
|
-
|
|
17861
|
+
useEffect13(() => {
|
|
16544
17862
|
if (!isEditMode) return;
|
|
16545
17863
|
const resolveIndex = (form, clientY) => {
|
|
16546
17864
|
const wrappers = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== fieldDragRef.current?.key);
|
|
@@ -16581,7 +17899,7 @@ function OhhwellsBridge() {
|
|
|
16581
17899
|
window.removeEventListener("drop", onDrop, true);
|
|
16582
17900
|
};
|
|
16583
17901
|
}, [buildFieldDropSlots, isEditMode, persistFields, selectField]);
|
|
16584
|
-
|
|
17902
|
+
useEffect13(() => {
|
|
16585
17903
|
if (!isEditMode) return;
|
|
16586
17904
|
const mark = () => document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
16587
17905
|
markFormFields(form);
|
|
@@ -16593,7 +17911,7 @@ function OhhwellsBridge() {
|
|
|
16593
17911
|
});
|
|
16594
17912
|
return () => observer.disconnect();
|
|
16595
17913
|
}, [isEditMode, fetchState, pathname]);
|
|
16596
|
-
|
|
17914
|
+
useEffect13(() => {
|
|
16597
17915
|
if (!isEditMode) return;
|
|
16598
17916
|
let saveTimer = null;
|
|
16599
17917
|
const onInput = (e) => {
|
|
@@ -16615,14 +17933,14 @@ function OhhwellsBridge() {
|
|
|
16615
17933
|
document.addEventListener("input", onInput, true);
|
|
16616
17934
|
return () => document.removeEventListener("input", onInput, true);
|
|
16617
17935
|
}, [isEditMode, persistFields]);
|
|
16618
|
-
|
|
17936
|
+
useEffect13(() => {
|
|
16619
17937
|
if (isEditMode || fetchState !== "done") return;
|
|
16620
17938
|
const content = contentCache.get(subdomain) ?? {};
|
|
16621
17939
|
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
16622
17940
|
reconcileFieldsFromContent(form, content);
|
|
16623
17941
|
});
|
|
16624
17942
|
}, [isEditMode, fetchState, subdomain]);
|
|
16625
|
-
|
|
17943
|
+
useEffect13(() => {
|
|
16626
17944
|
if (!isEditMode) return;
|
|
16627
17945
|
const swallow = (e) => {
|
|
16628
17946
|
const target = e.target;
|
|
@@ -16631,12 +17949,12 @@ function OhhwellsBridge() {
|
|
|
16631
17949
|
document.addEventListener("submit", swallow, true);
|
|
16632
17950
|
return () => document.removeEventListener("submit", swallow, true);
|
|
16633
17951
|
}, [isEditMode]);
|
|
16634
|
-
|
|
17952
|
+
useEffect13(() => {
|
|
16635
17953
|
if (isEditMode || fetchState !== "done") return;
|
|
16636
17954
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
16637
17955
|
bindPublishedForms(apiUrl, subdomain, contentCache.get(subdomain) ?? {});
|
|
16638
17956
|
}, [isEditMode, fetchState, subdomain]);
|
|
16639
|
-
|
|
17957
|
+
useEffect13(() => {
|
|
16640
17958
|
if (!subdomain || isEditMode) return;
|
|
16641
17959
|
let debounceTimer = null;
|
|
16642
17960
|
let observer = null;
|
|
@@ -16647,10 +17965,28 @@ function OhhwellsBridge() {
|
|
|
16647
17965
|
initSectionInstancesFromContent(content, window.location.pathname);
|
|
16648
17966
|
observer?.disconnect();
|
|
16649
17967
|
try {
|
|
17968
|
+
applyBrandChrome(content);
|
|
17969
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
17970
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
17971
|
+
} else {
|
|
17972
|
+
applyBrandToDom(null);
|
|
17973
|
+
}
|
|
17974
|
+
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
17975
|
+
setAiSectionOrder(content[SECTION_ORDER_KEY], window.location.pathname);
|
|
17976
|
+
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
17977
|
+
}
|
|
17978
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
17979
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
17980
|
+
}
|
|
16650
17981
|
for (const [key, val] of Object.entries(content)) {
|
|
16651
17982
|
if (key === "__ohw_sections") continue;
|
|
17983
|
+
if (key === AI_SECTIONS_KEY) continue;
|
|
16652
17984
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
16653
17985
|
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
17986
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
17987
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17988
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17989
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
16654
17990
|
if (applyVideoSettingNode(key, val)) continue;
|
|
16655
17991
|
if (applyCarouselNode(key, val)) continue;
|
|
16656
17992
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -16696,6 +18032,17 @@ function OhhwellsBridge() {
|
|
|
16696
18032
|
debounceTimer = setTimeout(applyFromCache, 150);
|
|
16697
18033
|
};
|
|
16698
18034
|
applyFromCache();
|
|
18035
|
+
const pathCacheKey = `${subdomain}::${pathname}`;
|
|
18036
|
+
if (!fetchedContentPaths.has(pathCacheKey)) {
|
|
18037
|
+
fetchedContentPaths.add(pathCacheKey);
|
|
18038
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
18039
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
18040
|
+
if (!data?.content) return;
|
|
18041
|
+
contentCache.set(subdomain, data.content);
|
|
18042
|
+
applyFromCache();
|
|
18043
|
+
}).catch(() => {
|
|
18044
|
+
});
|
|
18045
|
+
}
|
|
16699
18046
|
observer = new MutationObserver(scheduleApply);
|
|
16700
18047
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
16701
18048
|
return () => {
|
|
@@ -16709,10 +18056,10 @@ function OhhwellsBridge() {
|
|
|
16709
18056
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
16710
18057
|
el.style.display = visible ? "flex" : "none";
|
|
16711
18058
|
}, [subdomain, fetchState]);
|
|
16712
|
-
|
|
18059
|
+
useEffect13(() => {
|
|
16713
18060
|
postToParent2({ type: "ow:navigation", path: pathname });
|
|
16714
18061
|
}, [pathname, postToParent2]);
|
|
16715
|
-
|
|
18062
|
+
useEffect13(() => {
|
|
16716
18063
|
if (!isEditMode) return;
|
|
16717
18064
|
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
16718
18065
|
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
@@ -16720,7 +18067,7 @@ function OhhwellsBridge() {
|
|
|
16720
18067
|
deselectRef.current();
|
|
16721
18068
|
deactivateRef.current();
|
|
16722
18069
|
}, [pathname, isEditMode]);
|
|
16723
|
-
|
|
18070
|
+
useEffect13(() => {
|
|
16724
18071
|
const contentForNav = () => {
|
|
16725
18072
|
if (isEditMode) return editContentRef.current;
|
|
16726
18073
|
if (!subdomain) return {};
|
|
@@ -16789,35 +18136,36 @@ function OhhwellsBridge() {
|
|
|
16789
18136
|
observer?.disconnect();
|
|
16790
18137
|
};
|
|
16791
18138
|
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
16792
|
-
|
|
18139
|
+
useEffect13(() => {
|
|
16793
18140
|
if (!isEditMode) return;
|
|
18141
|
+
let lastPosted = 0;
|
|
16794
18142
|
const measure = () => {
|
|
16795
18143
|
const h = document.body.scrollHeight;
|
|
16796
|
-
if (h > 50
|
|
18144
|
+
if (h > 50 && Math.abs(h - lastPosted) > 1) {
|
|
18145
|
+
lastPosted = h;
|
|
18146
|
+
postToParent2({ type: "ow:height", height: h });
|
|
18147
|
+
}
|
|
18148
|
+
};
|
|
18149
|
+
let raf = null;
|
|
18150
|
+
const schedule = () => {
|
|
18151
|
+
if (raf != null) return;
|
|
18152
|
+
raf = requestAnimationFrame(() => {
|
|
18153
|
+
raf = null;
|
|
18154
|
+
measure();
|
|
18155
|
+
});
|
|
16797
18156
|
};
|
|
16798
18157
|
const t1 = setTimeout(measure, 50);
|
|
16799
18158
|
const t2 = setTimeout(measure, 500);
|
|
16800
|
-
|
|
16801
|
-
|
|
16802
|
-
const clearResizeTimers = () => {
|
|
16803
|
-
resizeTimers.forEach(clearTimeout);
|
|
16804
|
-
resizeTimers = [];
|
|
16805
|
-
};
|
|
16806
|
-
const handleResize = () => {
|
|
16807
|
-
if (window.innerWidth === lastWidth) return;
|
|
16808
|
-
lastWidth = window.innerWidth;
|
|
16809
|
-
clearResizeTimers();
|
|
16810
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
16811
|
-
};
|
|
16812
|
-
window.addEventListener("resize", handleResize);
|
|
18159
|
+
const ro = new ResizeObserver(schedule);
|
|
18160
|
+
ro.observe(document.body);
|
|
16813
18161
|
return () => {
|
|
16814
18162
|
clearTimeout(t1);
|
|
16815
18163
|
clearTimeout(t2);
|
|
16816
|
-
|
|
16817
|
-
|
|
18164
|
+
if (raf != null) cancelAnimationFrame(raf);
|
|
18165
|
+
ro.disconnect();
|
|
16818
18166
|
};
|
|
16819
18167
|
}, [pathname, isEditMode, postToParent2]);
|
|
16820
|
-
|
|
18168
|
+
useEffect13(() => {
|
|
16821
18169
|
if (!subdomainFromQuery || isEditMode) return;
|
|
16822
18170
|
const handleClick = (e) => {
|
|
16823
18171
|
const anchor = e.target.closest("a");
|
|
@@ -16833,7 +18181,7 @@ function OhhwellsBridge() {
|
|
|
16833
18181
|
document.addEventListener("click", handleClick, true);
|
|
16834
18182
|
return () => document.removeEventListener("click", handleClick, true);
|
|
16835
18183
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
16836
|
-
|
|
18184
|
+
useEffect13(() => {
|
|
16837
18185
|
if (!isEditMode) {
|
|
16838
18186
|
editStylesRef.current?.base.remove();
|
|
16839
18187
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -17055,6 +18403,7 @@ function OhhwellsBridge() {
|
|
|
17055
18403
|
return;
|
|
17056
18404
|
}
|
|
17057
18405
|
const target = e.target;
|
|
18406
|
+
if (target.closest("[data-ohw-ai-review]")) return;
|
|
17058
18407
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
17059
18408
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
17060
18409
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
@@ -17066,6 +18415,9 @@ function OhhwellsBridge() {
|
|
|
17066
18415
|
)) {
|
|
17067
18416
|
return;
|
|
17068
18417
|
}
|
|
18418
|
+
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
18419
|
+
clearMediaSelectionRef.current();
|
|
18420
|
+
}
|
|
17069
18421
|
{
|
|
17070
18422
|
const formEl = getFormElement(target);
|
|
17071
18423
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -17220,8 +18572,11 @@ function OhhwellsBridge() {
|
|
|
17220
18572
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
17221
18573
|
e.preventDefault();
|
|
17222
18574
|
e.stopPropagation();
|
|
17223
|
-
|
|
17224
|
-
|
|
18575
|
+
if (selectedMediaElRef.current === editable) {
|
|
18576
|
+
postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
|
|
18577
|
+
} else {
|
|
18578
|
+
selectMediaElementRef.current(editable);
|
|
18579
|
+
}
|
|
17225
18580
|
return;
|
|
17226
18581
|
}
|
|
17227
18582
|
const socialItem = getSocialItem(editable);
|
|
@@ -17357,6 +18712,7 @@ function OhhwellsBridge() {
|
|
|
17357
18712
|
};
|
|
17358
18713
|
const handleDblClick = (e) => {
|
|
17359
18714
|
const target = e.target;
|
|
18715
|
+
if (target.closest("[data-ohw-ai-review]")) return;
|
|
17360
18716
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
17361
18717
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
17362
18718
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
@@ -17408,6 +18764,9 @@ function OhhwellsBridge() {
|
|
|
17408
18764
|
setHoveredItemRect(null);
|
|
17409
18765
|
hoveredNavContainerRef.current = null;
|
|
17410
18766
|
setHoveredNavContainerRect(null);
|
|
18767
|
+
siblingHintElRef.current = null;
|
|
18768
|
+
setSiblingHintRect(null);
|
|
18769
|
+
setSiblingHintRects([]);
|
|
17411
18770
|
return;
|
|
17412
18771
|
}
|
|
17413
18772
|
{
|
|
@@ -17526,7 +18885,6 @@ function OhhwellsBridge() {
|
|
|
17526
18885
|
hoveredNavContainerRef.current = null;
|
|
17527
18886
|
setHoveredNavContainerRect(null);
|
|
17528
18887
|
hoveredItemElRef.current = editable;
|
|
17529
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
17530
18888
|
}
|
|
17531
18889
|
}
|
|
17532
18890
|
}
|
|
@@ -17823,7 +19181,7 @@ function OhhwellsBridge() {
|
|
|
17823
19181
|
}
|
|
17824
19182
|
};
|
|
17825
19183
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
17826
|
-
if (linkPopoverOpenRef.current) {
|
|
19184
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
17827
19185
|
if (hoveredImageRef.current) {
|
|
17828
19186
|
hoveredImageRef.current = null;
|
|
17829
19187
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -18157,7 +19515,9 @@ function OhhwellsBridge() {
|
|
|
18157
19515
|
return;
|
|
18158
19516
|
}
|
|
18159
19517
|
const { y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
18160
|
-
const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).
|
|
19518
|
+
const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
19519
|
+
(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
|
|
19520
|
+
).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
|
|
18161
19521
|
const ZONE = 20;
|
|
18162
19522
|
for (let i = 0; i < sections.length; i++) {
|
|
18163
19523
|
const a = sections[i];
|
|
@@ -18186,8 +19546,7 @@ function OhhwellsBridge() {
|
|
|
18186
19546
|
};
|
|
18187
19547
|
const handleMouseMove = (e) => {
|
|
18188
19548
|
const { clientX, clientY } = e;
|
|
18189
|
-
if (
|
|
18190
|
-
if (isOverEditorChrome(clientX, clientY)) {
|
|
19549
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
|
|
18191
19550
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
18192
19551
|
formHoverElRef.current = null;
|
|
18193
19552
|
setFormHoverRect(null);
|
|
@@ -18195,6 +19554,12 @@ function OhhwellsBridge() {
|
|
|
18195
19554
|
setHoveredItemRect(null);
|
|
18196
19555
|
hoveredNavContainerRef.current = null;
|
|
18197
19556
|
setHoveredNavContainerRect(null);
|
|
19557
|
+
siblingHintElRef.current = null;
|
|
19558
|
+
setSiblingHintRect(null);
|
|
19559
|
+
setSiblingHintRects([]);
|
|
19560
|
+
dismissImageHover();
|
|
19561
|
+
clearImageHover();
|
|
19562
|
+
setSectionGap(null);
|
|
18198
19563
|
return;
|
|
18199
19564
|
}
|
|
18200
19565
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -18206,7 +19571,11 @@ function OhhwellsBridge() {
|
|
|
18206
19571
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
18207
19572
|
const { clientX, clientY } = e.data;
|
|
18208
19573
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
18209
|
-
if (
|
|
19574
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
19575
|
+
dismissImageHover();
|
|
19576
|
+
clearImageHover();
|
|
19577
|
+
return;
|
|
19578
|
+
}
|
|
18210
19579
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
18211
19580
|
probeSectionGapAt(clientX, clientY);
|
|
18212
19581
|
probeImageAt(clientX, clientY);
|
|
@@ -18481,7 +19850,7 @@ function OhhwellsBridge() {
|
|
|
18481
19850
|
timers.set(key, setTimeout(() => {
|
|
18482
19851
|
timers.delete(key);
|
|
18483
19852
|
postToParentRef.current({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
18484
|
-
const h = document.
|
|
19853
|
+
const h = document.body.scrollHeight;
|
|
18485
19854
|
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
18486
19855
|
}, 400));
|
|
18487
19856
|
};
|
|
@@ -18489,10 +19858,23 @@ function OhhwellsBridge() {
|
|
|
18489
19858
|
if (e.data?.type !== "ow:hydrate") return;
|
|
18490
19859
|
const content = e.data.content;
|
|
18491
19860
|
if (!content) return;
|
|
19861
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
19862
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
19863
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
19864
|
+
} else {
|
|
19865
|
+
brandKitRef.current = "";
|
|
19866
|
+
applyBrandToDom(null);
|
|
19867
|
+
}
|
|
18492
19868
|
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
18493
19869
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
19870
|
+
setAiSectionOrder(content[SECTION_ORDER_KEY], window.location.pathname);
|
|
18494
19871
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
18495
19872
|
}
|
|
19873
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
19874
|
+
stylesRef.current = content[STYLE_STORE_KEY];
|
|
19875
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
19876
|
+
}
|
|
19877
|
+
applyBrandChrome(content);
|
|
18496
19878
|
let sectionsJson = null;
|
|
18497
19879
|
for (const [key, val] of Object.entries(content)) {
|
|
18498
19880
|
if (key === "__ohw_sections") {
|
|
@@ -18502,6 +19884,9 @@ function OhhwellsBridge() {
|
|
|
18502
19884
|
if (key === AI_SECTIONS_KEY) continue;
|
|
18503
19885
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
18504
19886
|
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
19887
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
19888
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
19889
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
18505
19890
|
if (applyVideoSettingNode(key, val)) continue;
|
|
18506
19891
|
if (applyCarouselNode(key, val)) continue;
|
|
18507
19892
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -18515,6 +19900,8 @@ function OhhwellsBridge() {
|
|
|
18515
19900
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
18516
19901
|
} else if (el.dataset.ohwEditable === "link") {
|
|
18517
19902
|
applyLinkHref(el, val);
|
|
19903
|
+
} else if (el.dataset.ohwEditable === "icon") {
|
|
19904
|
+
applyIconMarkup(el, val);
|
|
18518
19905
|
} else if (isIconMarkupValue(val)) {
|
|
18519
19906
|
} else {
|
|
18520
19907
|
el.innerHTML = val;
|
|
@@ -18535,7 +19922,7 @@ function OhhwellsBridge() {
|
|
|
18535
19922
|
reconcileFooterOrderFromContent(editContentRef.current);
|
|
18536
19923
|
syncNavigationDragCursorAttrs();
|
|
18537
19924
|
enforceLinkHrefs();
|
|
18538
|
-
const hydratedHeight = document.
|
|
19925
|
+
const hydratedHeight = document.body.scrollHeight;
|
|
18539
19926
|
if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
|
|
18540
19927
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
18541
19928
|
};
|
|
@@ -18599,16 +19986,25 @@ function OhhwellsBridge() {
|
|
|
18599
19986
|
nodes: collectEditableNodes(editContentRef.current)
|
|
18600
19987
|
});
|
|
18601
19988
|
};
|
|
19989
|
+
const clearInteractionChrome = () => {
|
|
19990
|
+
deactivateRef.current();
|
|
19991
|
+
deselectRef.current();
|
|
19992
|
+
clearMediaSelectionRef.current();
|
|
19993
|
+
};
|
|
18602
19994
|
const handleAiApplyTree = (e) => {
|
|
18603
19995
|
if (e.data?.type !== "ow:ai-apply-tree") return;
|
|
18604
19996
|
const payload = e.data.payload;
|
|
18605
19997
|
if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
|
|
19998
|
+
clearInteractionChrome();
|
|
18606
19999
|
const previous = aiSectionsRef.current;
|
|
18607
|
-
const nextState = applyTreeToState(parseAiSectionsState(previous),
|
|
20000
|
+
const nextState = applyTreeToState(parseAiSectionsState(previous), {
|
|
20001
|
+
...payload,
|
|
20002
|
+
path: payload.path ?? window.location.pathname
|
|
20003
|
+
});
|
|
18608
20004
|
const nextValue = serializeAiSectionsState(nextState);
|
|
18609
20005
|
aiSectionsRef.current = nextValue;
|
|
18610
20006
|
applyAiSectionsToDom(nextState);
|
|
18611
|
-
const newHeight = document.
|
|
20007
|
+
const newHeight = document.body.scrollHeight;
|
|
18612
20008
|
if (newHeight > 50) postToParentRef.current({ type: "ow:height", height: newHeight });
|
|
18613
20009
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: nextValue }] });
|
|
18614
20010
|
const appliedEl = document.querySelector(`[data-ohw-section="${CSS.escape(payload.id)}"]`);
|
|
@@ -18625,12 +20021,13 @@ function OhhwellsBridge() {
|
|
|
18625
20021
|
const exists = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
|
|
18626
20022
|
if (!exists) return;
|
|
18627
20023
|
if (isPageFrameSection(exists)) return;
|
|
20024
|
+
clearInteractionChrome();
|
|
18628
20025
|
const previous = aiSectionsRef.current;
|
|
18629
20026
|
const nextState = deleteSectionFromState(parseAiSectionsState(previous), sectionId);
|
|
18630
20027
|
const nextValue = serializeAiSectionsState(nextState);
|
|
18631
20028
|
aiSectionsRef.current = nextValue;
|
|
18632
20029
|
applyAiSectionsToDom(nextState);
|
|
18633
|
-
const newHeight = document.
|
|
20030
|
+
const newHeight = document.body.scrollHeight;
|
|
18634
20031
|
if (newHeight > 50) postToParentRef.current({ type: "ow:height", height: newHeight });
|
|
18635
20032
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: nextValue }] });
|
|
18636
20033
|
postToParentRef.current({ type: "ow:ai-section-deleted", sectionId, previous, value: nextValue });
|
|
@@ -18640,20 +20037,107 @@ function OhhwellsBridge() {
|
|
|
18640
20037
|
const handleAiSetSections = (e) => {
|
|
18641
20038
|
if (e.data?.type !== "ow:ai-set-sections") return;
|
|
18642
20039
|
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
20040
|
+
clearInteractionChrome();
|
|
18643
20041
|
aiSectionsRef.current = value;
|
|
18644
20042
|
applyAiSectionsToDom(parseAiSectionsState(value));
|
|
18645
|
-
|
|
20043
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
20044
|
+
const restoredHeight = document.body.scrollHeight;
|
|
18646
20045
|
if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
|
|
18647
20046
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
|
|
18648
20047
|
postAiSectionsChanged();
|
|
18649
20048
|
};
|
|
18650
20049
|
window.addEventListener("message", handleAiSetSections);
|
|
20050
|
+
const handleMoveSection = (e) => {
|
|
20051
|
+
if (e.data?.type !== "ow:move-section") return;
|
|
20052
|
+
const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
|
|
20053
|
+
const direction = e.data.direction === "up" || e.data.direction === "down" ? e.data.direction : null;
|
|
20054
|
+
if (!instanceId || !direction) return;
|
|
20055
|
+
const entries = moveSectionInstance(instanceId, direction, window.location.pathname);
|
|
20056
|
+
if (!entries) return;
|
|
20057
|
+
const orderJson = JSON.stringify(entries);
|
|
20058
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
20059
|
+
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20060
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20061
|
+
window.dispatchEvent(new Event("resize"));
|
|
20062
|
+
};
|
|
20063
|
+
window.addEventListener("message", handleMoveSection);
|
|
20064
|
+
const handleAiSetBrand = (e) => {
|
|
20065
|
+
if (e.data?.type !== "ow:ai-set-brand") return;
|
|
20066
|
+
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
20067
|
+
const previous = brandKitRef.current;
|
|
20068
|
+
brandKitRef.current = value;
|
|
20069
|
+
applyBrandToDom(parseBrandKit(value));
|
|
20070
|
+
if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
|
|
20071
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
20072
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
|
|
20073
|
+
postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
|
|
20074
|
+
};
|
|
20075
|
+
window.addEventListener("message", handleAiSetBrand);
|
|
20076
|
+
const handleAiSetStyles = (e) => {
|
|
20077
|
+
if (e.data?.type !== "ow:ai-set-styles") return;
|
|
20078
|
+
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
20079
|
+
const previous = stylesRef.current;
|
|
20080
|
+
stylesRef.current = value;
|
|
20081
|
+
applyStylesToDom(parseStyleStore(value));
|
|
20082
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
|
|
20083
|
+
postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
|
|
20084
|
+
};
|
|
20085
|
+
window.addEventListener("message", handleAiSetStyles);
|
|
20086
|
+
const handleGetBrand = (e) => {
|
|
20087
|
+
if (e.data?.type !== "ow:get-brand") return;
|
|
20088
|
+
const template = deriveTemplateBrand();
|
|
20089
|
+
const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
|
|
20090
|
+
postToParentRef.current({ type: "ow:brand-value", value });
|
|
20091
|
+
};
|
|
20092
|
+
window.addEventListener("message", handleGetBrand);
|
|
18651
20093
|
const handlePanelDragging = (e) => {
|
|
18652
20094
|
if (e.data?.type !== "ow:panel-dragging") return;
|
|
18653
20095
|
if (e.data.dragging) document.documentElement.setAttribute("data-ohw-panel-dragging", "");
|
|
18654
20096
|
else document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
18655
20097
|
};
|
|
18656
20098
|
window.addEventListener("message", handlePanelDragging);
|
|
20099
|
+
const handleDeleteSection = (e) => {
|
|
20100
|
+
if (e.data?.type !== "ow:delete-section") return;
|
|
20101
|
+
const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
|
|
20102
|
+
if (!instanceId) return;
|
|
20103
|
+
const currentEntries = getPageSectionOrderEntries(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname);
|
|
20104
|
+
const entries = deleteSectionInstance(instanceId, window.location.pathname, currentEntries);
|
|
20105
|
+
if (!entries) return;
|
|
20106
|
+
const orderJson = JSON.stringify(entries);
|
|
20107
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
20108
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20109
|
+
aiSectionApiRef.current?.clear();
|
|
20110
|
+
window.dispatchEvent(new Event("resize"));
|
|
20111
|
+
const deleteHeight = document.body.scrollHeight;
|
|
20112
|
+
if (deleteHeight > 50) postToParentRef.current({ type: "ow:height", height: deleteHeight });
|
|
20113
|
+
const actionId = newInstanceId();
|
|
20114
|
+
pendingDeleteUndoRef.current = {
|
|
20115
|
+
actionId,
|
|
20116
|
+
restore: () => {
|
|
20117
|
+
const restoredEntries = getPageSectionOrderEntries(
|
|
20118
|
+
editContentRef.current[SECTION_ORDER_KEY],
|
|
20119
|
+
window.location.pathname
|
|
20120
|
+
);
|
|
20121
|
+
const restored = restoreSectionInstance(instanceId, window.location.pathname, restoredEntries);
|
|
20122
|
+
if (!restored) return;
|
|
20123
|
+
const restoredJson = JSON.stringify(restored);
|
|
20124
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: restoredJson };
|
|
20125
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: restoredJson }] });
|
|
20126
|
+
window.dispatchEvent(new Event("resize"));
|
|
20127
|
+
const restoreHeight = document.body.scrollHeight;
|
|
20128
|
+
if (restoreHeight > 50) postToParentRef.current({ type: "ow:height", height: restoreHeight });
|
|
20129
|
+
}
|
|
20130
|
+
};
|
|
20131
|
+
postToParentRef.current({
|
|
20132
|
+
type: "ow:toast",
|
|
20133
|
+
title: "Section deleted",
|
|
20134
|
+
toastType: "success",
|
|
20135
|
+
actionLabel: "Undo",
|
|
20136
|
+
actionId,
|
|
20137
|
+
duration: 6e3
|
|
20138
|
+
});
|
|
20139
|
+
};
|
|
20140
|
+
window.addEventListener("message", handleDeleteSection);
|
|
18657
20141
|
const handleDeactivate = (e) => {
|
|
18658
20142
|
if (e.data?.type !== "ow:deactivate") return;
|
|
18659
20143
|
if (document.documentElement.hasAttribute("data-ohw-panel-dragging")) return;
|
|
@@ -18663,8 +20147,15 @@ function OhhwellsBridge() {
|
|
|
18663
20147
|
closeLinkPopoverRef.current();
|
|
18664
20148
|
return;
|
|
18665
20149
|
}
|
|
20150
|
+
if (floatingPanelOpenRef.current) {
|
|
20151
|
+
setFloatingPanelRef.current(null);
|
|
20152
|
+
deselectRef.current();
|
|
20153
|
+
deactivateRef.current();
|
|
20154
|
+
return;
|
|
20155
|
+
}
|
|
18666
20156
|
deselectRef.current();
|
|
18667
20157
|
deactivateRef.current();
|
|
20158
|
+
clearMediaSelectionRef.current();
|
|
18668
20159
|
};
|
|
18669
20160
|
window.addEventListener("message", handleDeactivate);
|
|
18670
20161
|
const handleToastAction = (e) => {
|
|
@@ -18750,6 +20241,10 @@ function OhhwellsBridge() {
|
|
|
18750
20241
|
const handleKeyDown = (e) => {
|
|
18751
20242
|
if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
|
|
18752
20243
|
if (e.key === "Escape" && document.querySelector("[data-ohw-more-menu]")) return;
|
|
20244
|
+
if (e.key === "Escape" && selectedMediaElRef.current) {
|
|
20245
|
+
clearMediaSelectionRef.current();
|
|
20246
|
+
return;
|
|
20247
|
+
}
|
|
18753
20248
|
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
|
|
18754
20249
|
e.preventDefault();
|
|
18755
20250
|
selectAllTextInEditable(activeElRef.current);
|
|
@@ -18909,6 +20404,12 @@ function OhhwellsBridge() {
|
|
|
18909
20404
|
if (aiSectionsRef.current) {
|
|
18910
20405
|
nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
|
|
18911
20406
|
}
|
|
20407
|
+
if (stylesRef.current) {
|
|
20408
|
+
nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
|
|
20409
|
+
}
|
|
20410
|
+
if (brandKitRef.current) {
|
|
20411
|
+
nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
|
|
20412
|
+
}
|
|
18912
20413
|
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
18913
20414
|
const formKey = formKeyOf(form);
|
|
18914
20415
|
if (!formKey) return;
|
|
@@ -18926,8 +20427,12 @@ function OhhwellsBridge() {
|
|
|
18926
20427
|
if (inserted) {
|
|
18927
20428
|
const tracker = getSectionsTracker();
|
|
18928
20429
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
18929
|
-
const
|
|
18930
|
-
|
|
20430
|
+
const reportHeight = () => {
|
|
20431
|
+
const h = document.body.scrollHeight;
|
|
20432
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
20433
|
+
};
|
|
20434
|
+
reportHeight();
|
|
20435
|
+
setTimeout(reportHeight, 500);
|
|
18931
20436
|
}
|
|
18932
20437
|
};
|
|
18933
20438
|
const handleSwitchSchedule = (e) => {
|
|
@@ -18968,7 +20473,7 @@ function OhhwellsBridge() {
|
|
|
18968
20473
|
const updated = sections.filter((s) => !(s.type === "scheduling" && s.pagePath === currentPath));
|
|
18969
20474
|
tracker.textContent = JSON.stringify(updated);
|
|
18970
20475
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent }] });
|
|
18971
|
-
const h = document.
|
|
20476
|
+
const h = document.body.scrollHeight;
|
|
18972
20477
|
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
18973
20478
|
};
|
|
18974
20479
|
const handleCollectSection = (e) => {
|
|
@@ -19323,19 +20828,24 @@ function OhhwellsBridge() {
|
|
|
19323
20828
|
window.removeEventListener("message", handleAiApplyTree);
|
|
19324
20829
|
window.removeEventListener("message", handleAiDeleteSection);
|
|
19325
20830
|
window.removeEventListener("message", handleAiSetSections);
|
|
20831
|
+
window.removeEventListener("message", handleMoveSection);
|
|
20832
|
+
window.removeEventListener("message", handleAiSetBrand);
|
|
20833
|
+
window.removeEventListener("message", handleAiSetStyles);
|
|
20834
|
+
window.removeEventListener("message", handleGetBrand);
|
|
19326
20835
|
window.removeEventListener("message", handlePanelDragging);
|
|
20836
|
+
window.removeEventListener("message", handleDeleteSection);
|
|
19327
20837
|
window.removeEventListener("message", handleDeactivate);
|
|
19328
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
19329
20838
|
window.removeEventListener("message", handleToastAction);
|
|
19330
20839
|
window.removeEventListener("message", handleFormCount);
|
|
19331
20840
|
window.removeEventListener("message", handleUiEscape);
|
|
20841
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
19332
20842
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
19333
20843
|
autoSaveTimers.current.clear();
|
|
19334
20844
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
19335
20845
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
19336
20846
|
};
|
|
19337
20847
|
}, [isEditMode, refreshStateRules]);
|
|
19338
|
-
|
|
20848
|
+
useEffect13(() => {
|
|
19339
20849
|
if (!isEditMode) return;
|
|
19340
20850
|
const THRESHOLD = 10;
|
|
19341
20851
|
const resolveWasSelected = (el) => {
|
|
@@ -19491,7 +21001,7 @@ function OhhwellsBridge() {
|
|
|
19491
21001
|
unlockFooterDragInteraction();
|
|
19492
21002
|
};
|
|
19493
21003
|
}, [isEditMode]);
|
|
19494
|
-
|
|
21004
|
+
useEffect13(() => {
|
|
19495
21005
|
const handler = (e) => {
|
|
19496
21006
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
19497
21007
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -19507,7 +21017,7 @@ function OhhwellsBridge() {
|
|
|
19507
21017
|
window.addEventListener("message", handler);
|
|
19508
21018
|
return () => window.removeEventListener("message", handler);
|
|
19509
21019
|
}, [processConfigRequest]);
|
|
19510
|
-
|
|
21020
|
+
useEffect13(() => {
|
|
19511
21021
|
if (!isEditMode) return;
|
|
19512
21022
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
19513
21023
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -19531,7 +21041,7 @@ function OhhwellsBridge() {
|
|
|
19531
21041
|
postToParent2({
|
|
19532
21042
|
type: "ow:ready",
|
|
19533
21043
|
version: "1",
|
|
19534
|
-
bridgeVersion: "0.1.
|
|
21044
|
+
bridgeVersion: "0.1.76",
|
|
19535
21045
|
path: pathname,
|
|
19536
21046
|
nodes: collectEditableNodes(editContentRef.current),
|
|
19537
21047
|
sections
|
|
@@ -19543,13 +21053,13 @@ function OhhwellsBridge() {
|
|
|
19543
21053
|
clearTimeout(timer);
|
|
19544
21054
|
};
|
|
19545
21055
|
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
19546
|
-
|
|
21056
|
+
useEffect13(() => {
|
|
19547
21057
|
scrollToHashSectionWhenReady();
|
|
19548
21058
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
19549
21059
|
window.addEventListener("hashchange", onHashChange);
|
|
19550
21060
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
19551
21061
|
}, [pathname]);
|
|
19552
|
-
const handleCommand =
|
|
21062
|
+
const handleCommand = useCallback8((cmd) => {
|
|
19553
21063
|
const el = activeElRef.current;
|
|
19554
21064
|
const selBefore = window.getSelection();
|
|
19555
21065
|
let savedOffsets = null;
|
|
@@ -19585,7 +21095,7 @@ function OhhwellsBridge() {
|
|
|
19585
21095
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
19586
21096
|
refreshActiveCommandsRef.current();
|
|
19587
21097
|
}, []);
|
|
19588
|
-
|
|
21098
|
+
useEffect13(() => {
|
|
19589
21099
|
const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
|
|
19590
21100
|
if (!session || !logoSizeDraft) return;
|
|
19591
21101
|
const onPanelAction = (e) => {
|
|
@@ -19623,7 +21133,7 @@ function OhhwellsBridge() {
|
|
|
19623
21133
|
window.addEventListener("message", onPanelAction);
|
|
19624
21134
|
return () => window.removeEventListener("message", onPanelAction);
|
|
19625
21135
|
}, [floatingPanel, logoSizeDraft, editorViewport, persistLogoSizeDraft, closeFloatingPanelAndDeselect]);
|
|
19626
|
-
const handleStateChange =
|
|
21136
|
+
const handleStateChange = useCallback8((state) => {
|
|
19627
21137
|
if (!activeStateElRef.current) return;
|
|
19628
21138
|
const el = activeStateElRef.current;
|
|
19629
21139
|
if (state === "Default") {
|
|
@@ -19636,7 +21146,7 @@ function OhhwellsBridge() {
|
|
|
19636
21146
|
}
|
|
19637
21147
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
19638
21148
|
}, [deactivate]);
|
|
19639
|
-
const reselectAfterLinkPopover =
|
|
21149
|
+
const reselectAfterLinkPopover = useCallback8(
|
|
19640
21150
|
(hrefKey) => {
|
|
19641
21151
|
requestAnimationFrame(() => {
|
|
19642
21152
|
const el = resolveHrefKeyElement(hrefKey);
|
|
@@ -19645,7 +21155,7 @@ function OhhwellsBridge() {
|
|
|
19645
21155
|
},
|
|
19646
21156
|
[resolveHrefKeyElement]
|
|
19647
21157
|
);
|
|
19648
|
-
const closeLinkPopover =
|
|
21158
|
+
const closeLinkPopover = useCallback8(() => {
|
|
19649
21159
|
const session = linkPopoverSessionRef.current;
|
|
19650
21160
|
addNavAfterAnchorRef.current = null;
|
|
19651
21161
|
setLinkPopover(null);
|
|
@@ -19653,9 +21163,9 @@ function OhhwellsBridge() {
|
|
|
19653
21163
|
reselectAfterLinkPopover(session.key);
|
|
19654
21164
|
}
|
|
19655
21165
|
}, [reselectAfterLinkPopover]);
|
|
19656
|
-
const closeLinkPopoverRef =
|
|
21166
|
+
const closeLinkPopoverRef = useRef10(closeLinkPopover);
|
|
19657
21167
|
closeLinkPopoverRef.current = closeLinkPopover;
|
|
19658
|
-
const openLinkPopoverForActive =
|
|
21168
|
+
const openLinkPopoverForActive = useCallback8(() => {
|
|
19659
21169
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
19660
21170
|
if (!hrefCtx) return;
|
|
19661
21171
|
bumpLinkPopoverGrace();
|
|
@@ -19666,7 +21176,7 @@ function OhhwellsBridge() {
|
|
|
19666
21176
|
});
|
|
19667
21177
|
deactivate();
|
|
19668
21178
|
}, [deactivate]);
|
|
19669
|
-
const openLinkPopoverForSelected =
|
|
21179
|
+
const openLinkPopoverForSelected = useCallback8(() => {
|
|
19670
21180
|
const anchor = selectedElRef.current;
|
|
19671
21181
|
if (!anchor) return;
|
|
19672
21182
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -19683,7 +21193,7 @@ function OhhwellsBridge() {
|
|
|
19683
21193
|
});
|
|
19684
21194
|
deselect();
|
|
19685
21195
|
}, [deselect]);
|
|
19686
|
-
const handleSelectParent =
|
|
21196
|
+
const handleSelectParent = useCallback8(() => {
|
|
19687
21197
|
const selected = selectedElRef.current;
|
|
19688
21198
|
if (!selected) return;
|
|
19689
21199
|
if (toolbarVariantRef.current === "select-frame") {
|
|
@@ -19710,7 +21220,7 @@ function OhhwellsBridge() {
|
|
|
19710
21220
|
}
|
|
19711
21221
|
deselectRef.current();
|
|
19712
21222
|
}, []);
|
|
19713
|
-
const handleDuplicateSelected =
|
|
21223
|
+
const handleDuplicateSelected = useCallback8(() => {
|
|
19714
21224
|
const selected = selectedElRef.current;
|
|
19715
21225
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
19716
21226
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
@@ -19843,7 +21353,7 @@ function OhhwellsBridge() {
|
|
|
19843
21353
|
});
|
|
19844
21354
|
}
|
|
19845
21355
|
}, [postToParent2]);
|
|
19846
|
-
const runPendingDeleteUndo =
|
|
21356
|
+
const runPendingDeleteUndo = useCallback8(() => {
|
|
19847
21357
|
const pending = pendingDeleteUndoRef.current;
|
|
19848
21358
|
if (!pending) return false;
|
|
19849
21359
|
pendingDeleteUndoRef.current = null;
|
|
@@ -19851,7 +21361,7 @@ function OhhwellsBridge() {
|
|
|
19851
21361
|
enforceLinkHrefs();
|
|
19852
21362
|
return true;
|
|
19853
21363
|
}, []);
|
|
19854
|
-
const handleDeleteSelected =
|
|
21364
|
+
const handleDeleteSelected = useCallback8(() => {
|
|
19855
21365
|
const selected = selectedElRef.current;
|
|
19856
21366
|
if (!selected) return false;
|
|
19857
21367
|
return deleteSelectedNavFooterItem({
|
|
@@ -19872,7 +21382,7 @@ function OhhwellsBridge() {
|
|
|
19872
21382
|
}, [postToParent2]);
|
|
19873
21383
|
handleDeleteSelectedRef.current = handleDeleteSelected;
|
|
19874
21384
|
runPendingDeleteUndoRef.current = runPendingDeleteUndo;
|
|
19875
|
-
const handleLinkPopoverSubmit =
|
|
21385
|
+
const handleLinkPopoverSubmit = useCallback8(
|
|
19876
21386
|
(target) => {
|
|
19877
21387
|
const session = linkPopoverSessionRef.current;
|
|
19878
21388
|
if (!session) return;
|
|
@@ -19938,19 +21448,30 @@ function OhhwellsBridge() {
|
|
|
19938
21448
|
const showEditLink = toolbarShowEditLink;
|
|
19939
21449
|
const currentSections = sectionsByPath[pathname] ?? [];
|
|
19940
21450
|
linkPopoverOpenRef.current = linkPopover !== null;
|
|
19941
|
-
const
|
|
21451
|
+
const handleMediaSelect = useCallback8((key) => {
|
|
21452
|
+
const el = hoveredImageRef.current?.dataset.ohwKey === key ? hoveredImageRef.current : Array.from(document.querySelectorAll(MEDIA_SELECTOR)).find(
|
|
21453
|
+
(m) => (m.dataset.ohwKey ?? "") === key
|
|
21454
|
+
) ?? null;
|
|
21455
|
+
if (!el) return;
|
|
21456
|
+
selectMediaElementRef.current(el);
|
|
21457
|
+
}, []);
|
|
21458
|
+
const handleMediaReplace = useCallback8(
|
|
19942
21459
|
(key) => {
|
|
19943
|
-
postToParent2({
|
|
21460
|
+
postToParent2({
|
|
21461
|
+
type: "ow:image-pick",
|
|
21462
|
+
key,
|
|
21463
|
+
elementType: mediaHover?.elementType ?? selectedMedia?.elementType ?? "image"
|
|
21464
|
+
});
|
|
19944
21465
|
},
|
|
19945
|
-
[postToParent2, mediaHover?.elementType]
|
|
21466
|
+
[postToParent2, mediaHover?.elementType, selectedMedia?.elementType]
|
|
19946
21467
|
);
|
|
19947
|
-
const handleEditCarousel =
|
|
21468
|
+
const handleEditCarousel = useCallback8(
|
|
19948
21469
|
(key) => {
|
|
19949
21470
|
postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
|
|
19950
21471
|
},
|
|
19951
21472
|
[postToParent2]
|
|
19952
21473
|
);
|
|
19953
|
-
const handleMediaFadeOutComplete =
|
|
21474
|
+
const handleMediaFadeOutComplete = useCallback8((key) => {
|
|
19954
21475
|
setUploadingRects((prev) => {
|
|
19955
21476
|
if (!(key in prev)) return prev;
|
|
19956
21477
|
const next = { ...prev };
|
|
@@ -19958,7 +21479,7 @@ function OhhwellsBridge() {
|
|
|
19958
21479
|
return next;
|
|
19959
21480
|
});
|
|
19960
21481
|
}, []);
|
|
19961
|
-
const handleVideoSettingsChange =
|
|
21482
|
+
const handleVideoSettingsChange = useCallback8(
|
|
19962
21483
|
(key, settings) => {
|
|
19963
21484
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
19964
21485
|
const video = getVideoEl2(el);
|
|
@@ -19980,430 +21501,516 @@ function OhhwellsBridge() {
|
|
|
19980
21501
|
},
|
|
19981
21502
|
[postToParent2]
|
|
19982
21503
|
);
|
|
19983
|
-
return
|
|
19984
|
-
/* @__PURE__ */
|
|
19985
|
-
|
|
19986
|
-
|
|
19987
|
-
|
|
19988
|
-
|
|
19989
|
-
{
|
|
19990
|
-
|
|
19991
|
-
|
|
19992
|
-
|
|
19993
|
-
|
|
19994
|
-
|
|
19995
|
-
|
|
19996
|
-
|
|
19997
|
-
|
|
19998
|
-
|
|
19999
|
-
|
|
20000
|
-
|
|
20001
|
-
|
|
20002
|
-
|
|
20003
|
-
onReplace: handleMediaReplace,
|
|
20004
|
-
onVideoSettingsChange: handleVideoSettingsChange
|
|
20005
|
-
}
|
|
20006
|
-
),
|
|
20007
|
-
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
|
|
20008
|
-
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
20009
|
-
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
20010
|
-
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
20011
|
-
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
20012
|
-
"div",
|
|
20013
|
-
{
|
|
20014
|
-
className: "pointer-events-none fixed z-2147483646",
|
|
20015
|
-
style: {
|
|
20016
|
-
left: slot.left,
|
|
20017
|
-
top: slot.top,
|
|
20018
|
-
width: slot.width,
|
|
20019
|
-
height: slot.height
|
|
21504
|
+
return /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
21505
|
+
/* @__PURE__ */ jsx33("div", { id: "ohw-loader", suppressHydrationWarning: true, style: { ...OHW_LOADER_STYLE, display: "none" }, children: /* @__PURE__ */ jsx33(OhwLoaderSpinner, {}) }),
|
|
21506
|
+
/* @__PURE__ */ jsx33("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: OHW_LOADER_PREHYDRATE_SCRIPT } }),
|
|
21507
|
+
bridgeRoot ? createPortal2(
|
|
21508
|
+
/* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
21509
|
+
/* @__PURE__ */ jsx33("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
21510
|
+
isEditMode && /* @__PURE__ */ jsx33(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
|
|
21511
|
+
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
21512
|
+
"div",
|
|
21513
|
+
{
|
|
21514
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
21515
|
+
style: { left: slot.left, top: slot.y, width: slot.width, height: 3, transform: "translateY(-50%)" },
|
|
21516
|
+
children: /* @__PURE__ */ jsx33(
|
|
21517
|
+
DropIndicator,
|
|
21518
|
+
{
|
|
21519
|
+
direction: "horizontal",
|
|
21520
|
+
state: activeSectionDropIndex === i ? "dragActive" : "dragIdle",
|
|
21521
|
+
className: "!h-full !w-full"
|
|
21522
|
+
}
|
|
21523
|
+
)
|
|
20020
21524
|
},
|
|
20021
|
-
|
|
20022
|
-
|
|
20023
|
-
|
|
20024
|
-
|
|
20025
|
-
|
|
20026
|
-
|
|
20027
|
-
|
|
20028
|
-
|
|
20029
|
-
|
|
20030
|
-
|
|
20031
|
-
)),
|
|
20032
|
-
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
20033
|
-
"div",
|
|
20034
|
-
{
|
|
20035
|
-
className: "pointer-events-none fixed z-2147483646",
|
|
20036
|
-
style: {
|
|
20037
|
-
left: slot.left,
|
|
20038
|
-
top: slot.top,
|
|
20039
|
-
width: slot.width,
|
|
20040
|
-
height: slot.height
|
|
21525
|
+
`section-drop-${slot.insertIndex}-${i}`
|
|
21526
|
+
)),
|
|
21527
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx33(
|
|
21528
|
+
MediaOverlay,
|
|
21529
|
+
{
|
|
21530
|
+
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
21531
|
+
isUploading: true,
|
|
21532
|
+
fadingOut,
|
|
21533
|
+
onFadeOutComplete: handleMediaFadeOutComplete,
|
|
21534
|
+
onReplace: handleMediaReplace
|
|
20041
21535
|
},
|
|
20042
|
-
|
|
20043
|
-
|
|
20044
|
-
|
|
20045
|
-
|
|
20046
|
-
|
|
20047
|
-
|
|
20048
|
-
|
|
20049
|
-
|
|
20050
|
-
|
|
20051
|
-
|
|
20052
|
-
|
|
20053
|
-
|
|
20054
|
-
|
|
20055
|
-
|
|
20056
|
-
|
|
20057
|
-
|
|
20058
|
-
|
|
20059
|
-
|
|
20060
|
-
|
|
20061
|
-
|
|
20062
|
-
|
|
20063
|
-
|
|
20064
|
-
|
|
21536
|
+
`uploading-${key}`
|
|
21537
|
+
)),
|
|
21538
|
+
mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */ jsx33(
|
|
21539
|
+
MediaOverlay,
|
|
21540
|
+
{
|
|
21541
|
+
hover: mediaHover,
|
|
21542
|
+
isUploading: false,
|
|
21543
|
+
onReplace: handleMediaReplace,
|
|
21544
|
+
onSelect: handleMediaSelect,
|
|
21545
|
+
onVideoSettingsChange: handleVideoSettingsChange
|
|
21546
|
+
}
|
|
21547
|
+
),
|
|
21548
|
+
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ jsx33(
|
|
21549
|
+
MediaOverlay,
|
|
21550
|
+
{
|
|
21551
|
+
hover: selectedMedia,
|
|
21552
|
+
selected: true,
|
|
21553
|
+
hovered: mediaHover?.key === selectedMedia.key,
|
|
21554
|
+
isUploading: false,
|
|
21555
|
+
onReplace: handleMediaReplace,
|
|
21556
|
+
onSelect: handleMediaSelect,
|
|
21557
|
+
onVideoSettingsChange: handleVideoSettingsChange
|
|
21558
|
+
}
|
|
21559
|
+
),
|
|
21560
|
+
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
|
|
21561
|
+
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
21562
|
+
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
21563
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
21564
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
21565
|
+
"div",
|
|
21566
|
+
{
|
|
21567
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
21568
|
+
style: {
|
|
21569
|
+
left: slot.left,
|
|
21570
|
+
top: slot.top,
|
|
21571
|
+
width: slot.width,
|
|
21572
|
+
height: slot.height
|
|
21573
|
+
},
|
|
21574
|
+
children: /* @__PURE__ */ jsx33(
|
|
21575
|
+
DropIndicator,
|
|
21576
|
+
{
|
|
21577
|
+
direction: slot.direction,
|
|
21578
|
+
state: activeFooterDropIndex === i ? "dragActive" : "dragIdle",
|
|
21579
|
+
className: "!h-full !w-full"
|
|
21580
|
+
}
|
|
21581
|
+
)
|
|
21582
|
+
},
|
|
21583
|
+
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
21584
|
+
)),
|
|
21585
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
21586
|
+
"div",
|
|
21587
|
+
{
|
|
21588
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
21589
|
+
style: {
|
|
21590
|
+
left: slot.left,
|
|
21591
|
+
top: slot.top,
|
|
21592
|
+
width: slot.width,
|
|
21593
|
+
height: slot.height
|
|
21594
|
+
},
|
|
21595
|
+
children: /* @__PURE__ */ jsx33(
|
|
21596
|
+
DropIndicator,
|
|
21597
|
+
{
|
|
21598
|
+
direction: slot.direction,
|
|
21599
|
+
state: activeNavDropIndex === i ? "dragActive" : "dragIdle",
|
|
21600
|
+
className: "!h-full !w-full"
|
|
21601
|
+
}
|
|
21602
|
+
)
|
|
21603
|
+
},
|
|
21604
|
+
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
21605
|
+
)),
|
|
21606
|
+
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
21607
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
21608
|
+
hoveredTextRect && !hoveredNavContainerRect && !hoveredItemRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
|
|
21609
|
+
formPickRect && !isItemDragging && /* @__PURE__ */ jsx33(
|
|
21610
|
+
ItemInteractionLayer,
|
|
21611
|
+
{
|
|
21612
|
+
rect: formPickRect,
|
|
21613
|
+
state: "active-top",
|
|
21614
|
+
itemDragSurface: false,
|
|
21615
|
+
toolbarAlign: "left",
|
|
21616
|
+
chromeGap: 24,
|
|
21617
|
+
toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ jsxs20(
|
|
21618
|
+
"div",
|
|
21619
|
+
{
|
|
21620
|
+
"data-ohw-form-toolbar": "",
|
|
21621
|
+
className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
|
|
21622
|
+
children: [
|
|
21623
|
+
/* @__PURE__ */ jsx33(
|
|
21624
|
+
"button",
|
|
21625
|
+
{
|
|
21626
|
+
type: "button",
|
|
21627
|
+
"aria-label": "Add field",
|
|
21628
|
+
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
21629
|
+
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
21630
|
+
"data-ohw-add-field": "",
|
|
21631
|
+
children: /* @__PURE__ */ jsx33(Plus4, { size: 15, "aria-hidden": true })
|
|
21632
|
+
}
|
|
21633
|
+
),
|
|
21634
|
+
/* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
21635
|
+
/* @__PURE__ */ jsxs20(
|
|
21636
|
+
"button",
|
|
21637
|
+
{
|
|
21638
|
+
type: "button",
|
|
21639
|
+
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",
|
|
21640
|
+
onClick: () => {
|
|
21641
|
+
setFieldTypePickerOpen(false);
|
|
21642
|
+
const form = formPickElRef.current;
|
|
21643
|
+
if (!form) return;
|
|
21644
|
+
postToParent2({
|
|
21645
|
+
type: "ow:form-pick",
|
|
21646
|
+
formKey: formKeyOf(form),
|
|
21647
|
+
hasLongText: formHasLongText(form)
|
|
21648
|
+
});
|
|
21649
|
+
},
|
|
21650
|
+
children: [
|
|
21651
|
+
/* @__PURE__ */ jsx33(Settings, { size: 14, "aria-hidden": true }),
|
|
21652
|
+
"Form settings",
|
|
21653
|
+
formPickCount ? (
|
|
21654
|
+
// Counter pill, per the design — not a text suffix.
|
|
21655
|
+
/* @__PURE__ */ jsx33(
|
|
21656
|
+
"span",
|
|
21657
|
+
{
|
|
21658
|
+
"data-ohw-form-count": "",
|
|
21659
|
+
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",
|
|
21660
|
+
children: formPickCount
|
|
21661
|
+
}
|
|
21662
|
+
)
|
|
21663
|
+
) : null
|
|
21664
|
+
]
|
|
21665
|
+
}
|
|
21666
|
+
),
|
|
21667
|
+
/* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
21668
|
+
/* @__PURE__ */ jsx33("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ jsx33(
|
|
21669
|
+
"button",
|
|
21670
|
+
{
|
|
21671
|
+
type: "button",
|
|
21672
|
+
"aria-pressed": formViewState === state,
|
|
21673
|
+
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"),
|
|
21674
|
+
onClick: () => {
|
|
21675
|
+
setFieldTypePickerOpen(false);
|
|
21676
|
+
const form = formPickElRef.current;
|
|
21677
|
+
const key = form ? formKeyOf(form) : null;
|
|
21678
|
+
if (!form || !key) return;
|
|
21679
|
+
const initial = successInitialFor(form, key, editContentRef.current);
|
|
21680
|
+
setFormViewState(form, key, state, initial);
|
|
21681
|
+
setFormViewStateUi(state);
|
|
21682
|
+
setFormPickRect(form.getBoundingClientRect());
|
|
21683
|
+
if (state === "success") {
|
|
21684
|
+
const successEl = form.querySelector(`[${SUCCESS_TEXT_ATTR}]`);
|
|
21685
|
+
if (successEl) requestAnimationFrame(() => activateRef.current(successEl));
|
|
21686
|
+
} else {
|
|
21687
|
+
deactivateRef.current();
|
|
21688
|
+
}
|
|
21689
|
+
},
|
|
21690
|
+
children: state
|
|
21691
|
+
},
|
|
21692
|
+
state
|
|
21693
|
+
)) })
|
|
21694
|
+
]
|
|
21695
|
+
}
|
|
21696
|
+
)
|
|
21697
|
+
}
|
|
21698
|
+
),
|
|
21699
|
+
formHoverRect && !isItemDragging && /* @__PURE__ */ jsx33(
|
|
21700
|
+
ItemInteractionLayer,
|
|
21701
|
+
{
|
|
21702
|
+
rect: formHoverRect,
|
|
21703
|
+
state: "hover",
|
|
21704
|
+
chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
|
|
21705
|
+
}
|
|
21706
|
+
),
|
|
21707
|
+
fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx33(
|
|
21708
|
+
ItemInteractionLayer,
|
|
21709
|
+
{
|
|
21710
|
+
rect: fieldPickRect,
|
|
21711
|
+
state: fieldDragging ? "dragging" : "active-top",
|
|
21712
|
+
itemDragSurface: false,
|
|
21713
|
+
toolbarAlign: "left",
|
|
21714
|
+
chromeGap: 10,
|
|
21715
|
+
showHandle: true,
|
|
21716
|
+
dragHandleLabel: "Reorder field",
|
|
21717
|
+
onDragHandleDragStart: handleFieldDragStart,
|
|
21718
|
+
onDragHandleDragEnd: handleFieldDragEnd,
|
|
21719
|
+
toolbar: /* @__PURE__ */ jsx33(
|
|
21720
|
+
FormFieldToolbar,
|
|
21721
|
+
{
|
|
21722
|
+
type: fieldPickState.type,
|
|
21723
|
+
required: fieldPickState.required,
|
|
21724
|
+
onTypeChange: handleFieldTypeChange,
|
|
21725
|
+
onRequiredToggle: handleFieldRequiredToggle,
|
|
21726
|
+
onDuplicate: handleFieldDuplicate,
|
|
21727
|
+
onDelete: handleFieldDelete
|
|
21728
|
+
}
|
|
21729
|
+
)
|
|
21730
|
+
}
|
|
21731
|
+
),
|
|
21732
|
+
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
21733
|
+
"div",
|
|
21734
|
+
{
|
|
21735
|
+
className: "pointer-events-none fixed z-[2147483644]",
|
|
21736
|
+
style: { top: slot.top, left: slot.left, width: slot.width },
|
|
21737
|
+
children: /* @__PURE__ */ jsx33(
|
|
21738
|
+
DropIndicator,
|
|
21739
|
+
{
|
|
21740
|
+
direction: "horizontal",
|
|
21741
|
+
state: fieldDropIndex === i ? "dragActive" : "dragIdle",
|
|
21742
|
+
className: "!w-full"
|
|
21743
|
+
}
|
|
21744
|
+
)
|
|
21745
|
+
},
|
|
21746
|
+
`field-drop-${i}`
|
|
21747
|
+
)) : null,
|
|
21748
|
+
fieldTypePickerOpen && formPickRect ? (() => {
|
|
21749
|
+
const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
|
|
21750
|
+
return /* @__PURE__ */ jsx33(
|
|
20065
21751
|
"div",
|
|
20066
21752
|
{
|
|
20067
|
-
"
|
|
20068
|
-
|
|
20069
|
-
|
|
20070
|
-
|
|
20071
|
-
|
|
20072
|
-
|
|
20073
|
-
type: "button",
|
|
20074
|
-
"aria-label": "Add field",
|
|
20075
|
-
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
20076
|
-
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
20077
|
-
"data-ohw-add-field": "",
|
|
20078
|
-
children: /* @__PURE__ */ jsx33(Plus4, { size: 15, "aria-hidden": true })
|
|
20079
|
-
}
|
|
20080
|
-
),
|
|
20081
|
-
/* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
20082
|
-
/* @__PURE__ */ jsxs20(
|
|
20083
|
-
"button",
|
|
20084
|
-
{
|
|
20085
|
-
type: "button",
|
|
20086
|
-
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",
|
|
20087
|
-
onClick: () => {
|
|
20088
|
-
setFieldTypePickerOpen(false);
|
|
20089
|
-
const form = formPickElRef.current;
|
|
20090
|
-
if (!form) return;
|
|
20091
|
-
postToParent2({
|
|
20092
|
-
type: "ow:form-pick",
|
|
20093
|
-
formKey: formKeyOf(form),
|
|
20094
|
-
hasLongText: formHasLongText(form)
|
|
20095
|
-
});
|
|
20096
|
-
},
|
|
20097
|
-
children: [
|
|
20098
|
-
/* @__PURE__ */ jsx33(Settings, { size: 14, "aria-hidden": true }),
|
|
20099
|
-
"Form settings",
|
|
20100
|
-
formPickCount ? (
|
|
20101
|
-
// Counter pill, per the design — not a text suffix.
|
|
20102
|
-
/* @__PURE__ */ jsx33(
|
|
20103
|
-
"span",
|
|
20104
|
-
{
|
|
20105
|
-
"data-ohw-form-count": "",
|
|
20106
|
-
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",
|
|
20107
|
-
children: formPickCount
|
|
20108
|
-
}
|
|
20109
|
-
)
|
|
20110
|
-
) : null
|
|
20111
|
-
]
|
|
20112
|
-
}
|
|
20113
|
-
),
|
|
20114
|
-
/* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
20115
|
-
/* @__PURE__ */ jsx33("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ jsx33(
|
|
20116
|
-
"button",
|
|
20117
|
-
{
|
|
20118
|
-
type: "button",
|
|
20119
|
-
"aria-pressed": formViewState === state,
|
|
20120
|
-
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"),
|
|
20121
|
-
onClick: () => {
|
|
20122
|
-
setFieldTypePickerOpen(false);
|
|
20123
|
-
const form = formPickElRef.current;
|
|
20124
|
-
const key = form ? formKeyOf(form) : null;
|
|
20125
|
-
if (!form || !key) return;
|
|
20126
|
-
const initial = successInitialFor(form, key, editContentRef.current);
|
|
20127
|
-
setFormViewState(form, key, state, initial);
|
|
20128
|
-
setFormViewStateUi(state);
|
|
20129
|
-
setFormPickRect(form.getBoundingClientRect());
|
|
20130
|
-
if (state === "success") {
|
|
20131
|
-
const successEl = form.querySelector(`[${SUCCESS_TEXT_ATTR}]`);
|
|
20132
|
-
if (successEl) requestAnimationFrame(() => activateRef.current(successEl));
|
|
20133
|
-
} else {
|
|
20134
|
-
deactivateRef.current();
|
|
20135
|
-
}
|
|
20136
|
-
},
|
|
20137
|
-
children: state
|
|
20138
|
-
},
|
|
20139
|
-
state
|
|
20140
|
-
)) })
|
|
20141
|
-
]
|
|
21753
|
+
className: "pointer-events-none fixed z-[2147483645]",
|
|
21754
|
+
style: {
|
|
21755
|
+
top: toolbar ? toolbar.bottom + 6 : formPickRect.top + 16,
|
|
21756
|
+
left: toolbar ? toolbar.left : formPickRect.left + 24
|
|
21757
|
+
},
|
|
21758
|
+
children: /* @__PURE__ */ jsx33(FieldTypePicker, { onPick: handleAddField })
|
|
20142
21759
|
}
|
|
20143
|
-
)
|
|
20144
|
-
}
|
|
20145
|
-
|
|
20146
|
-
|
|
20147
|
-
|
|
20148
|
-
|
|
20149
|
-
|
|
20150
|
-
|
|
20151
|
-
|
|
20152
|
-
|
|
20153
|
-
|
|
20154
|
-
|
|
20155
|
-
|
|
20156
|
-
|
|
20157
|
-
|
|
20158
|
-
|
|
20159
|
-
|
|
20160
|
-
|
|
20161
|
-
|
|
20162
|
-
|
|
20163
|
-
|
|
20164
|
-
|
|
20165
|
-
|
|
20166
|
-
|
|
20167
|
-
|
|
21760
|
+
);
|
|
21761
|
+
})() : null,
|
|
21762
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ jsx33(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
21763
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx33(
|
|
21764
|
+
FooterContainerChrome,
|
|
21765
|
+
{
|
|
21766
|
+
rect: toolbarRect,
|
|
21767
|
+
onAdd: handleAddFooterColumn,
|
|
21768
|
+
addDisabled: !canAddFooterColumn()
|
|
21769
|
+
}
|
|
21770
|
+
),
|
|
21771
|
+
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ jsx33(
|
|
21772
|
+
ItemInteractionLayer,
|
|
21773
|
+
{
|
|
21774
|
+
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
21775
|
+
toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
|
|
21776
|
+
elRef: glowElRef,
|
|
21777
|
+
state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanelRect(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
21778
|
+
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
21779
|
+
dragDisabled: reorderDragDisabled,
|
|
21780
|
+
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
21781
|
+
onDragHandleDragStart: handleItemDragStart,
|
|
21782
|
+
onDragHandleDragEnd: handleItemDragEnd,
|
|
21783
|
+
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
21784
|
+
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
21785
|
+
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection && !selectedIsSocialsRow,
|
|
21786
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ jsx33(
|
|
21787
|
+
ItemActionToolbar,
|
|
21788
|
+
{
|
|
21789
|
+
onEditLink: openLinkPopoverForSelected,
|
|
21790
|
+
onStyle: () => {
|
|
21791
|
+
const row = selectedElRef.current;
|
|
21792
|
+
if (!row) return;
|
|
21793
|
+
if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
|
|
21794
|
+
else openSocialsDisplayPanel(row);
|
|
21795
|
+
},
|
|
21796
|
+
showStyle: selectedIsSocialsRow,
|
|
21797
|
+
styleActive: floatingPanel?.kind === "socials-display",
|
|
21798
|
+
onAddItem: handleAddChildItem,
|
|
21799
|
+
onSelectParent: handleSelectParent,
|
|
21800
|
+
onDuplicate: handleDuplicateSelected,
|
|
21801
|
+
onDelete: handleDeleteSelected,
|
|
21802
|
+
addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
21803
|
+
const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
|
|
21804
|
+
return row ? !canAddSocialItem(row) : false;
|
|
21805
|
+
})(),
|
|
21806
|
+
editLinkDisabled: false,
|
|
21807
|
+
moreDisabled: false,
|
|
21808
|
+
deleteDisabled: selectedElRef.current !== null && (() => {
|
|
21809
|
+
const social = getSocialItem(selectedElRef.current);
|
|
21810
|
+
return social ? !canRemoveSocialItem(social) : false;
|
|
21811
|
+
})(),
|
|
21812
|
+
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow || selectedElRef.current !== null && (() => {
|
|
21813
|
+
const social = getSocialItem(selectedElRef.current);
|
|
21814
|
+
const row = social ? findSocialsRow(social) : null;
|
|
21815
|
+
return row ? !canAddSocialItem(row) : false;
|
|
21816
|
+
})(),
|
|
21817
|
+
showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
|
|
21818
|
+
showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
|
|
21819
|
+
selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
|
|
21820
|
+
),
|
|
21821
|
+
showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
|
|
21822
|
+
dropdownOpen: navDropdownPreviewOpen,
|
|
21823
|
+
onDropdownOpenChange: handleNavDropdownOpenChange,
|
|
21824
|
+
headingVisible: footerHeadingVisible,
|
|
21825
|
+
onHeadingVisibleChange: handleFooterHeadingVisibleChange
|
|
21826
|
+
}
|
|
21827
|
+
) : void 0
|
|
21828
|
+
}
|
|
21829
|
+
),
|
|
21830
|
+
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
21831
|
+
/* @__PURE__ */ jsx33(
|
|
21832
|
+
EditGlowChrome,
|
|
20168
21833
|
{
|
|
20169
|
-
|
|
20170
|
-
|
|
20171
|
-
|
|
20172
|
-
|
|
20173
|
-
|
|
20174
|
-
onDelete: handleFieldDelete
|
|
21834
|
+
rect: toolbarRect,
|
|
21835
|
+
elRef: glowElRef,
|
|
21836
|
+
reorderHrefKey,
|
|
21837
|
+
dragDisabled: reorderDragDisabled,
|
|
21838
|
+
hideHandle: isItemDragging
|
|
20175
21839
|
}
|
|
20176
|
-
)
|
|
20177
|
-
|
|
20178
|
-
|
|
20179
|
-
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
20180
|
-
"div",
|
|
20181
|
-
{
|
|
20182
|
-
className: "pointer-events-none fixed z-[2147483644]",
|
|
20183
|
-
style: { top: slot.top, left: slot.left, width: slot.width },
|
|
20184
|
-
children: /* @__PURE__ */ jsx33(
|
|
20185
|
-
DropIndicator,
|
|
21840
|
+
),
|
|
21841
|
+
/* @__PURE__ */ jsx33(
|
|
21842
|
+
FloatingToolbar,
|
|
20186
21843
|
{
|
|
20187
|
-
|
|
20188
|
-
|
|
20189
|
-
|
|
21844
|
+
rect: toolbarRect,
|
|
21845
|
+
parentScroll: parentScrollRef.current,
|
|
21846
|
+
elRef: toolbarElRef,
|
|
21847
|
+
onCommand: handleCommand,
|
|
21848
|
+
activeCommands,
|
|
21849
|
+
showEditLink,
|
|
21850
|
+
onEditLink: openLinkPopoverForActive
|
|
20190
21851
|
}
|
|
20191
21852
|
)
|
|
20192
|
-
},
|
|
20193
|
-
|
|
20194
|
-
)) : null,
|
|
20195
|
-
fieldTypePickerOpen && formPickRect ? (() => {
|
|
20196
|
-
const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
|
|
20197
|
-
return /* @__PURE__ */ jsx33(
|
|
21853
|
+
] }),
|
|
21854
|
+
maxBadge && /* @__PURE__ */ jsxs20(
|
|
20198
21855
|
"div",
|
|
20199
21856
|
{
|
|
20200
|
-
|
|
21857
|
+
"data-ohw-max-badge": "",
|
|
20201
21858
|
style: {
|
|
20202
|
-
|
|
20203
|
-
|
|
21859
|
+
position: "fixed",
|
|
21860
|
+
top: maxBadge.rect.bottom + 4,
|
|
21861
|
+
left: maxBadge.rect.right,
|
|
21862
|
+
transform: "translateX(-100%)",
|
|
21863
|
+
zIndex: 2147483647,
|
|
21864
|
+
background: maxBadge.current > maxBadge.max ? "#FEF2F2" : "#F5F5F4",
|
|
21865
|
+
color: maxBadge.current > maxBadge.max ? "#DC2626" : "#78716C",
|
|
21866
|
+
border: `1px solid ${maxBadge.current > maxBadge.max ? "#FECACA" : "#E7E5E4"}`,
|
|
21867
|
+
borderRadius: 4,
|
|
21868
|
+
padding: "2px 6px",
|
|
21869
|
+
fontSize: 11,
|
|
21870
|
+
fontWeight: 500,
|
|
21871
|
+
pointerEvents: "none"
|
|
20204
21872
|
},
|
|
20205
|
-
children:
|
|
21873
|
+
children: [
|
|
21874
|
+
maxBadge.current,
|
|
21875
|
+
"/",
|
|
21876
|
+
maxBadge.max
|
|
21877
|
+
]
|
|
20206
21878
|
}
|
|
20207
|
-
)
|
|
20208
|
-
|
|
20209
|
-
|
|
20210
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx33(
|
|
20211
|
-
FooterContainerChrome,
|
|
20212
|
-
{
|
|
20213
|
-
rect: toolbarRect,
|
|
20214
|
-
onAdd: handleAddFooterColumn,
|
|
20215
|
-
addDisabled: !canAddFooterColumn()
|
|
20216
|
-
}
|
|
20217
|
-
),
|
|
20218
|
-
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ jsx33(
|
|
20219
|
-
ItemInteractionLayer,
|
|
20220
|
-
{
|
|
20221
|
-
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
20222
|
-
toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
|
|
20223
|
-
elRef: glowElRef,
|
|
20224
|
-
state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanelRect(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
20225
|
-
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
20226
|
-
dragDisabled: reorderDragDisabled,
|
|
20227
|
-
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
20228
|
-
onDragHandleDragStart: handleItemDragStart,
|
|
20229
|
-
onDragHandleDragEnd: handleItemDragEnd,
|
|
20230
|
-
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
20231
|
-
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
20232
|
-
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection && !selectedIsSocialsRow,
|
|
20233
|
-
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ jsx33(
|
|
20234
|
-
ItemActionToolbar,
|
|
20235
|
-
{
|
|
20236
|
-
onEditLink: openLinkPopoverForSelected,
|
|
20237
|
-
onStyle: () => {
|
|
20238
|
-
const row = selectedElRef.current;
|
|
20239
|
-
if (!row) return;
|
|
20240
|
-
if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
|
|
20241
|
-
else openSocialsDisplayPanel(row);
|
|
20242
|
-
},
|
|
20243
|
-
showStyle: selectedIsSocialsRow,
|
|
20244
|
-
styleActive: floatingPanel?.kind === "socials-display",
|
|
20245
|
-
onAddItem: handleAddChildItem,
|
|
20246
|
-
onSelectParent: handleSelectParent,
|
|
20247
|
-
onDuplicate: handleDuplicateSelected,
|
|
20248
|
-
onDelete: handleDeleteSelected,
|
|
20249
|
-
addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
20250
|
-
const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
|
|
20251
|
-
return row ? !canAddSocialItem(row) : false;
|
|
20252
|
-
})(),
|
|
20253
|
-
editLinkDisabled: false,
|
|
20254
|
-
moreDisabled: false,
|
|
20255
|
-
deleteDisabled: selectedElRef.current !== null && (() => {
|
|
20256
|
-
const social = getSocialItem(selectedElRef.current);
|
|
20257
|
-
return social ? !canRemoveSocialItem(social) : false;
|
|
20258
|
-
})(),
|
|
20259
|
-
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow || selectedElRef.current !== null && (() => {
|
|
20260
|
-
const social = getSocialItem(selectedElRef.current);
|
|
20261
|
-
const row = social ? findSocialsRow(social) : null;
|
|
20262
|
-
return row ? !canAddSocialItem(row) : false;
|
|
20263
|
-
})(),
|
|
20264
|
-
showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
|
|
20265
|
-
showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
|
|
20266
|
-
selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
|
|
20267
|
-
),
|
|
20268
|
-
showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
|
|
20269
|
-
dropdownOpen: navDropdownPreviewOpen,
|
|
20270
|
-
onDropdownOpenChange: handleNavDropdownOpenChange,
|
|
20271
|
-
headingVisible: footerHeadingVisible,
|
|
20272
|
-
onHeadingVisibleChange: handleFooterHeadingVisibleChange
|
|
20273
|
-
}
|
|
20274
|
-
) : void 0
|
|
20275
|
-
}
|
|
20276
|
-
),
|
|
20277
|
-
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
20278
|
-
/* @__PURE__ */ jsx33(
|
|
20279
|
-
EditGlowChrome,
|
|
21879
|
+
),
|
|
21880
|
+
toggleState && !linkPopover && /* @__PURE__ */ jsx33(
|
|
21881
|
+
StateToggle,
|
|
20280
21882
|
{
|
|
20281
|
-
rect:
|
|
20282
|
-
|
|
20283
|
-
|
|
20284
|
-
|
|
20285
|
-
hideHandle: isItemDragging
|
|
21883
|
+
rect: toggleState.rect,
|
|
21884
|
+
activeState: toggleState.activeState,
|
|
21885
|
+
states: toggleState.states,
|
|
21886
|
+
onStateChange: handleStateChange
|
|
20286
21887
|
}
|
|
20287
21888
|
),
|
|
20288
|
-
/* @__PURE__ */
|
|
20289
|
-
|
|
21889
|
+
sectionGap && !linkPopover && /* @__PURE__ */ jsxs20(
|
|
21890
|
+
"div",
|
|
20290
21891
|
{
|
|
20291
|
-
|
|
20292
|
-
|
|
20293
|
-
|
|
20294
|
-
|
|
20295
|
-
|
|
20296
|
-
|
|
20297
|
-
|
|
21892
|
+
"data-ohw-section-insert-line": "",
|
|
21893
|
+
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
21894
|
+
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
21895
|
+
children: [
|
|
21896
|
+
/* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
21897
|
+
/* @__PURE__ */ jsx33(
|
|
21898
|
+
Badge,
|
|
21899
|
+
{
|
|
21900
|
+
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",
|
|
21901
|
+
onClick: () => {
|
|
21902
|
+
window.parent.postMessage(
|
|
21903
|
+
{
|
|
21904
|
+
type: "ow:add-section",
|
|
21905
|
+
insertAfter: sectionGap.insertAfter,
|
|
21906
|
+
insertBefore: sectionGap.insertBefore
|
|
21907
|
+
},
|
|
21908
|
+
"*"
|
|
21909
|
+
);
|
|
21910
|
+
},
|
|
21911
|
+
children: "Add Section"
|
|
21912
|
+
}
|
|
21913
|
+
),
|
|
21914
|
+
/* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
21915
|
+
]
|
|
20298
21916
|
}
|
|
20299
|
-
)
|
|
20300
|
-
|
|
20301
|
-
|
|
20302
|
-
|
|
20303
|
-
|
|
20304
|
-
|
|
20305
|
-
|
|
20306
|
-
|
|
20307
|
-
|
|
20308
|
-
|
|
20309
|
-
|
|
20310
|
-
|
|
20311
|
-
|
|
20312
|
-
|
|
20313
|
-
|
|
20314
|
-
borderRadius: 4,
|
|
20315
|
-
padding: "2px 6px",
|
|
20316
|
-
fontSize: 11,
|
|
20317
|
-
fontWeight: 500,
|
|
20318
|
-
pointerEvents: "none"
|
|
21917
|
+
),
|
|
21918
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx33(
|
|
21919
|
+
LinkPopover,
|
|
21920
|
+
{
|
|
21921
|
+
panelRef: linkPopoverPanelRef,
|
|
21922
|
+
portalContainer: dialogPortalContainer,
|
|
21923
|
+
open: true,
|
|
21924
|
+
mode: linkPopover.mode ?? "edit",
|
|
21925
|
+
pages: sitePages,
|
|
21926
|
+
sections: currentSections,
|
|
21927
|
+
sectionsByPath,
|
|
21928
|
+
initialTarget: linkPopover.target,
|
|
21929
|
+
existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
|
|
21930
|
+
onClose: closeLinkPopover,
|
|
21931
|
+
onSubmit: handleLinkPopoverSubmit
|
|
20319
21932
|
},
|
|
20320
|
-
|
|
20321
|
-
|
|
20322
|
-
|
|
20323
|
-
|
|
20324
|
-
|
|
20325
|
-
|
|
20326
|
-
|
|
20327
|
-
|
|
20328
|
-
|
|
20329
|
-
|
|
20330
|
-
|
|
20331
|
-
|
|
20332
|
-
|
|
20333
|
-
|
|
20334
|
-
}
|
|
20335
|
-
),
|
|
20336
|
-
sectionGap && !linkPopover && /* @__PURE__ */ jsxs20(
|
|
20337
|
-
"div",
|
|
20338
|
-
{
|
|
20339
|
-
"data-ohw-section-insert-line": "",
|
|
20340
|
-
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
20341
|
-
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
20342
|
-
children: [
|
|
20343
|
-
/* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
20344
|
-
/* @__PURE__ */ jsx33(
|
|
20345
|
-
Badge,
|
|
21933
|
+
linkPopover.key
|
|
21934
|
+
) : null,
|
|
21935
|
+
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ jsx33(
|
|
21936
|
+
FloatingPanel,
|
|
21937
|
+
{
|
|
21938
|
+
open: true,
|
|
21939
|
+
title: floatingPanel.title,
|
|
21940
|
+
context: floatingPanel.context,
|
|
21941
|
+
position: floatingPanelPos,
|
|
21942
|
+
onPositionChange: setFloatingPanelPos,
|
|
21943
|
+
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
21944
|
+
onClose: closeFloatingPanelOnly,
|
|
21945
|
+
children: /* @__PURE__ */ jsx33(
|
|
21946
|
+
SocialsDisplayPanel,
|
|
20346
21947
|
{
|
|
20347
|
-
|
|
20348
|
-
|
|
20349
|
-
|
|
20350
|
-
|
|
20351
|
-
|
|
20352
|
-
insertAfter: sectionGap.insertAfter,
|
|
20353
|
-
insertBefore: sectionGap.insertBefore
|
|
20354
|
-
},
|
|
20355
|
-
"*"
|
|
20356
|
-
);
|
|
20357
|
-
},
|
|
20358
|
-
children: "Add Section"
|
|
21948
|
+
display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
|
|
21949
|
+
onChange: (next) => {
|
|
21950
|
+
changeSocialsDisplay(floatingPanel.row, next);
|
|
21951
|
+
setFloatingPanel({ ...floatingPanel });
|
|
21952
|
+
}
|
|
20359
21953
|
}
|
|
20360
|
-
)
|
|
20361
|
-
|
|
20362
|
-
|
|
20363
|
-
|
|
20364
|
-
|
|
20365
|
-
|
|
20366
|
-
|
|
20367
|
-
|
|
20368
|
-
|
|
20369
|
-
|
|
20370
|
-
|
|
20371
|
-
|
|
20372
|
-
|
|
20373
|
-
|
|
20374
|
-
|
|
20375
|
-
|
|
20376
|
-
|
|
20377
|
-
|
|
20378
|
-
|
|
21954
|
+
)
|
|
21955
|
+
}
|
|
21956
|
+
) : null
|
|
21957
|
+
] }),
|
|
21958
|
+
bridgeRoot
|
|
21959
|
+
) : null
|
|
21960
|
+
] });
|
|
21961
|
+
}
|
|
21962
|
+
|
|
21963
|
+
// src/ui/EmptySection.tsx
|
|
21964
|
+
import Link3 from "next/link";
|
|
21965
|
+
import { Fragment as Fragment9, jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
21966
|
+
function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
|
|
21967
|
+
return /* @__PURE__ */ jsxs21(Fragment9, { children: [
|
|
21968
|
+
/* @__PURE__ */ jsx34(
|
|
21969
|
+
"p",
|
|
21970
|
+
{
|
|
21971
|
+
style: {
|
|
21972
|
+
fontFamily: "var(--brand-font-body)",
|
|
21973
|
+
fontSize: "0.75rem",
|
|
21974
|
+
fontWeight: 500,
|
|
21975
|
+
letterSpacing: "0.15em",
|
|
21976
|
+
textTransform: "uppercase",
|
|
21977
|
+
color: "var(--brand-accent)",
|
|
21978
|
+
marginBottom: "1.5rem"
|
|
20379
21979
|
},
|
|
20380
|
-
|
|
20381
|
-
|
|
20382
|
-
|
|
20383
|
-
|
|
20384
|
-
|
|
20385
|
-
|
|
20386
|
-
|
|
20387
|
-
|
|
20388
|
-
|
|
20389
|
-
|
|
20390
|
-
|
|
20391
|
-
|
|
20392
|
-
|
|
20393
|
-
|
|
20394
|
-
|
|
20395
|
-
|
|
20396
|
-
|
|
20397
|
-
|
|
20398
|
-
|
|
20399
|
-
|
|
20400
|
-
|
|
20401
|
-
|
|
20402
|
-
|
|
20403
|
-
|
|
20404
|
-
|
|
20405
|
-
|
|
20406
|
-
|
|
21980
|
+
children: /* @__PURE__ */ jsx34(Link3, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ jsx34("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
|
|
21981
|
+
}
|
|
21982
|
+
),
|
|
21983
|
+
/* @__PURE__ */ jsx34(
|
|
21984
|
+
"h1",
|
|
21985
|
+
{
|
|
21986
|
+
style: {
|
|
21987
|
+
fontFamily: "var(--brand-font-heading)",
|
|
21988
|
+
fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
|
|
21989
|
+
lineHeight: 1.1,
|
|
21990
|
+
letterSpacing: "-0.025em",
|
|
21991
|
+
color: "var(--brand-text)",
|
|
21992
|
+
marginBottom: "1rem"
|
|
21993
|
+
},
|
|
21994
|
+
...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
|
|
21995
|
+
children: title
|
|
21996
|
+
}
|
|
21997
|
+
),
|
|
21998
|
+
/* @__PURE__ */ jsx34(
|
|
21999
|
+
"p",
|
|
22000
|
+
{
|
|
22001
|
+
style: {
|
|
22002
|
+
fontFamily: "var(--brand-font-body)",
|
|
22003
|
+
fontSize: "1rem",
|
|
22004
|
+
lineHeight: 1.7,
|
|
22005
|
+
fontWeight: 300,
|
|
22006
|
+
color: "var(--brand-text-muted)",
|
|
22007
|
+
maxWidth: "340px"
|
|
22008
|
+
},
|
|
22009
|
+
...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
|
|
22010
|
+
children: "This page doesn't have any content yet."
|
|
22011
|
+
}
|
|
22012
|
+
)
|
|
22013
|
+
] });
|
|
20407
22014
|
}
|
|
20408
22015
|
export {
|
|
20409
22016
|
AI_DEFAULT_BRAND,
|
|
@@ -20421,6 +22028,7 @@ export {
|
|
|
20421
22028
|
DropdownMenuItem,
|
|
20422
22029
|
DropdownMenuSeparator,
|
|
20423
22030
|
DropdownMenuTrigger,
|
|
22031
|
+
EmptySection,
|
|
20424
22032
|
ItemActionToolbar,
|
|
20425
22033
|
ItemInteractionLayer,
|
|
20426
22034
|
LinkEditorPanel,
|