@ohhwells/bridge 0.1.68 → 0.1.69-next.208
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2228 -836
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -7
- package/dist/index.d.ts +21 -7
- package/dist/index.js +2220 -829
- package/dist/index.js.map +1 -1
- package/dist/pages.cjs +141 -0
- package/dist/pages.cjs.map +1 -0
- package/dist/pages.d.cts +45 -0
- package/dist/pages.d.ts +45 -0
- package/dist/pages.js +107 -0
- package/dist/pages.js.map +1 -0
- package/dist/styles.css +66 -0
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/OhhwellsBridge.tsx
|
|
4
|
-
import React11, { useCallback as
|
|
4
|
+
import React11, { useCallback as useCallback8, useEffect as useEffect13, useLayoutEffect as useLayoutEffect4, useRef as useRef10, useState as useState12 } 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
|
});
|
|
@@ -147,6 +465,36 @@ var FEATURE_LINE_CSS = [
|
|
|
147
465
|
`background-color:currentColor;-webkit-mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px;`,
|
|
148
466
|
`mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px}`
|
|
149
467
|
].join("");
|
|
468
|
+
function hexLuminance(color) {
|
|
469
|
+
const m = /^#([0-9a-f]{6})$/i.exec(color.trim());
|
|
470
|
+
if (!m) return null;
|
|
471
|
+
const [r2, g, b] = [0, 2, 4].map((i) => {
|
|
472
|
+
const c = parseInt(m[1].slice(i, i + 2), 16) / 255;
|
|
473
|
+
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
474
|
+
});
|
|
475
|
+
return 0.2126 * r2 + 0.7152 * g + 0.0722 * b;
|
|
476
|
+
}
|
|
477
|
+
function hexContrast(a, b) {
|
|
478
|
+
const la = hexLuminance(a);
|
|
479
|
+
const lb = hexLuminance(b);
|
|
480
|
+
if (la === null || lb === null) return null;
|
|
481
|
+
const [hi, lo] = la > lb ? [la, lb] : [lb, la];
|
|
482
|
+
return (hi + 0.05) / (lo + 0.05);
|
|
483
|
+
}
|
|
484
|
+
function accentBandContext(brand) {
|
|
485
|
+
const p = brand.palette;
|
|
486
|
+
const lightWins = (hexContrast(p.light, p.primary) ?? 99) >= (hexContrast(p.dark, p.primary) ?? 0);
|
|
487
|
+
if (lightWins) {
|
|
488
|
+
return {
|
|
489
|
+
brand: { ...brand, palette: { dark: p.light, primary: p.light, accent: p.light, light: p.primary } },
|
|
490
|
+
buttonLabel: p.primary
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
return {
|
|
494
|
+
brand: { ...brand, palette: { dark: p.dark, primary: p.dark, accent: p.dark, light: p.light } },
|
|
495
|
+
buttonLabel: p.light
|
|
496
|
+
};
|
|
497
|
+
}
|
|
150
498
|
function textAttrs(ctx, path) {
|
|
151
499
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
152
500
|
}
|
|
@@ -158,7 +506,12 @@ var AI_RESPONSIVE_CSS = [
|
|
|
158
506
|
"@media (max-width: 640px) {",
|
|
159
507
|
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
160
508
|
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
509
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
510
|
+
" [data-ai-responsive] [data-ai-group] { display: flex !important; flex-direction: column !important; }",
|
|
511
|
+
" [data-ai-responsive] [data-ai-group] > * { grid-column: auto !important; }",
|
|
161
512
|
" [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
513
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
514
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
162
515
|
"}"
|
|
163
516
|
].join("\n");
|
|
164
517
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
@@ -236,7 +589,7 @@ function ButtonEl({
|
|
|
236
589
|
}) {
|
|
237
590
|
const secondary = slots.variant === "secondary";
|
|
238
591
|
const href = str(slots.href);
|
|
239
|
-
const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`) } : {};
|
|
592
|
+
const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`), "data-ohw-role": "button" } : {};
|
|
240
593
|
return /* @__PURE__ */ jsx(
|
|
241
594
|
"a",
|
|
242
595
|
{
|
|
@@ -252,7 +605,7 @@ function ButtonEl({
|
|
|
252
605
|
textDecoration: "none",
|
|
253
606
|
cursor: "pointer",
|
|
254
607
|
...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 }
|
|
608
|
+
...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
609
|
},
|
|
257
610
|
children: /* @__PURE__ */ jsx("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
|
|
258
611
|
}
|
|
@@ -758,7 +1111,24 @@ function CardBlock({ node, ctx, path }) {
|
|
|
758
1111
|
minWidth: 0
|
|
759
1112
|
},
|
|
760
1113
|
children: [
|
|
761
|
-
media && (horizontal ? /* @__PURE__ */ jsx(
|
|
1114
|
+
media && (horizontal ? /* @__PURE__ */ jsx(
|
|
1115
|
+
"div",
|
|
1116
|
+
{
|
|
1117
|
+
style: (
|
|
1118
|
+
// An icon hugs its glyph — flex:1 gave a 48px icon half the card and pushed the
|
|
1119
|
+
// text to the far side. Photos keep the half-and-half split. The inset has no
|
|
1120
|
+
// inner padding (the photo split absorbed that), so the icon carries its own gap.
|
|
1121
|
+
/^(lucide|simple):/.test(mediaRef) ? {
|
|
1122
|
+
flexShrink: 0,
|
|
1123
|
+
display: "flex",
|
|
1124
|
+
alignItems: "center",
|
|
1125
|
+
padding: mediaInset,
|
|
1126
|
+
[mediaPosition === "right" ? "marginLeft" : "marginRight"]: 20
|
|
1127
|
+
} : { flex: 1, minWidth: 0, display: "flex", alignItems: "center", padding: mediaInset }
|
|
1128
|
+
),
|
|
1129
|
+
children: media
|
|
1130
|
+
}
|
|
1131
|
+
) : /* @__PURE__ */ jsx(
|
|
762
1132
|
"div",
|
|
763
1133
|
{
|
|
764
1134
|
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" },
|
|
@@ -1022,6 +1392,49 @@ function renderNode(node, ctx, path) {
|
|
|
1022
1392
|
switch (node.type) {
|
|
1023
1393
|
case "text":
|
|
1024
1394
|
return /* @__PURE__ */ jsx(TextBlock, { slots, ctx, path });
|
|
1395
|
+
// Layout container: arranges child blocks, contributes no content of its own. `grid` is a
|
|
1396
|
+
// nested 12-column grid the children span (a collage is 3–5 media on it, bottom-aligned so
|
|
1397
|
+
// mixed aspects read as a composition); `split` is exactly two children at a ratio; `stack`
|
|
1398
|
+
// is a column. Children render through this same dispatcher, so edit markers, media
|
|
1399
|
+
// resolution, and copy paths all work unchanged inside a group.
|
|
1400
|
+
case "group": {
|
|
1401
|
+
const layout = str(slots.layout);
|
|
1402
|
+
const gap = slots.spacing === "tight" ? AI_TREE_TOKENS.spacing3 : slots.spacing === "airy" ? AI_TREE_TOKENS.spacing8 : AI_TREE_TOKENS.spacing6;
|
|
1403
|
+
const kids = (node.children ?? []).map((child, i) => /* @__PURE__ */ jsx(
|
|
1404
|
+
"div",
|
|
1405
|
+
{
|
|
1406
|
+
style: layout === "grid" ? {
|
|
1407
|
+
gridColumn: `span ${typeof child.span === "number" ? Math.min(12, Math.max(1, child.span)) : 12}`,
|
|
1408
|
+
minWidth: 0
|
|
1409
|
+
} : { minWidth: 0 },
|
|
1410
|
+
children: renderNode(child, ctx, `${path}.c${i}`)
|
|
1411
|
+
},
|
|
1412
|
+
i
|
|
1413
|
+
));
|
|
1414
|
+
if (layout === "grid") {
|
|
1415
|
+
return /* @__PURE__ */ jsx(
|
|
1416
|
+
"div",
|
|
1417
|
+
{
|
|
1418
|
+
"data-ai-group": "grid",
|
|
1419
|
+
style: { display: "grid", gridTemplateColumns: "repeat(12, 1fr)", gap, alignItems: "end" },
|
|
1420
|
+
children: kids
|
|
1421
|
+
}
|
|
1422
|
+
);
|
|
1423
|
+
}
|
|
1424
|
+
if (layout === "split") {
|
|
1425
|
+
const ratio = str(slots.ratio);
|
|
1426
|
+
const cols = ratio === "3:5" ? "3fr 5fr" : ratio === "5:3" ? "5fr 3fr" : "1fr 1fr";
|
|
1427
|
+
return /* @__PURE__ */ jsx(
|
|
1428
|
+
"div",
|
|
1429
|
+
{
|
|
1430
|
+
"data-ai-group": "split",
|
|
1431
|
+
style: { display: "grid", gridTemplateColumns: cols, gap, alignItems: "center" },
|
|
1432
|
+
children: kids
|
|
1433
|
+
}
|
|
1434
|
+
);
|
|
1435
|
+
}
|
|
1436
|
+
return /* @__PURE__ */ jsx("div", { "data-ai-group": "stack", style: { display: "flex", flexDirection: "column", gap }, children: kids });
|
|
1437
|
+
}
|
|
1025
1438
|
case "button":
|
|
1026
1439
|
return /* @__PURE__ */ jsx(ButtonEl, { slots, ctx, path });
|
|
1027
1440
|
case "button-row":
|
|
@@ -1154,11 +1567,14 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1154
1567
|
return null;
|
|
1155
1568
|
}
|
|
1156
1569
|
const resolvedBrand = brand ?? AI_DEFAULT_BRAND;
|
|
1570
|
+
const band = (tree.settings ?? {}).sectionBackground === "accent" ? accentBandContext(resolvedBrand) : null;
|
|
1571
|
+
const blockBrand = band?.brand ?? resolvedBrand;
|
|
1157
1572
|
const ctx = {
|
|
1158
|
-
brand:
|
|
1573
|
+
brand: blockBrand,
|
|
1159
1574
|
resolveMedia: resolveMedia ?? (() => null),
|
|
1160
|
-
cardSurface:
|
|
1161
|
-
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null
|
|
1575
|
+
cardSurface: blockBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${blockBrand.palette.light} 90%, ${blockBrand.palette.dark})`,
|
|
1576
|
+
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
|
|
1577
|
+
...band ? { buttonLabel: band.buttonLabel } : {}
|
|
1162
1578
|
};
|
|
1163
1579
|
const settings = tree.settings ?? {};
|
|
1164
1580
|
const pad = AI_TREE_TOKENS.sectionPadding[settings.spacing ?? "balanced"];
|
|
@@ -1166,6 +1582,20 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1166
1582
|
const overlayAlpha = { low: 0.25, medium: 0.45, high: 0.65 }[settings.overlayIntensity ?? "medium"];
|
|
1167
1583
|
const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
|
|
1168
1584
|
const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
|
|
1585
|
+
const toneBackground = (() => {
|
|
1586
|
+
const { dark, primary, light } = resolvedBrand.palette;
|
|
1587
|
+
switch (settings.sectionBackground) {
|
|
1588
|
+
case "surface":
|
|
1589
|
+
return `color-mix(in srgb, ${light} 94%, ${dark})`;
|
|
1590
|
+
case "accent":
|
|
1591
|
+
return primary;
|
|
1592
|
+
case "accent-soft":
|
|
1593
|
+
return `color-mix(in srgb, ${primary} 12%, ${light})`;
|
|
1594
|
+
default:
|
|
1595
|
+
return void 0;
|
|
1596
|
+
}
|
|
1597
|
+
})();
|
|
1598
|
+
const distributed = !isOverlay && settings.textDistribution;
|
|
1169
1599
|
return /* @__PURE__ */ jsxs(
|
|
1170
1600
|
"section",
|
|
1171
1601
|
{
|
|
@@ -1175,10 +1605,11 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1175
1605
|
style: {
|
|
1176
1606
|
position: "relative",
|
|
1177
1607
|
padding: `${pad}px 0`,
|
|
1178
|
-
background: isOverlay && !backgroundUrl ? "#DBEAFE" : void 0,
|
|
1608
|
+
background: toneBackground ?? (isOverlay && !backgroundUrl ? "#DBEAFE" : void 0),
|
|
1179
1609
|
backgroundImage: backgroundUrl ? `url(${backgroundUrl})` : void 0,
|
|
1180
1610
|
backgroundSize: "cover",
|
|
1181
|
-
backgroundPosition: "center"
|
|
1611
|
+
backgroundPosition: "center",
|
|
1612
|
+
color: settings.sectionBackground === "accent" ? blockBrand.palette.dark : void 0
|
|
1182
1613
|
},
|
|
1183
1614
|
children: [
|
|
1184
1615
|
/* @__PURE__ */ jsx("style", { children: AI_RESPONSIVE_CSS }),
|
|
@@ -1202,10 +1633,24 @@ function AiTreeRenderer({ tree, brand, resolveMedia, editKeyPrefix }) {
|
|
|
1202
1633
|
display: "grid",
|
|
1203
1634
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
1204
1635
|
gap: AI_TREE_TOKENS.spacing6,
|
|
1205
|
-
alignItems: settings.verticalPosition === "top" ? "start" : "center",
|
|
1636
|
+
alignItems: distributed === "space-between" ? "stretch" : (distributed ?? settings.verticalPosition) === "top" ? "start" : "center",
|
|
1206
1637
|
marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
|
|
1207
1638
|
},
|
|
1208
|
-
children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ jsx(
|
|
1639
|
+
children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ jsx(
|
|
1640
|
+
"div",
|
|
1641
|
+
{
|
|
1642
|
+
"data-ai-cell": "",
|
|
1643
|
+
style: {
|
|
1644
|
+
gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
|
|
1645
|
+
minWidth: 0,
|
|
1646
|
+
// space-between: each column becomes a flex column whose content spreads over
|
|
1647
|
+
// the full row height instead of clumping at the top.
|
|
1648
|
+
...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
|
|
1649
|
+
},
|
|
1650
|
+
children: renderNode(block, ctx, `r${r2}.b${b}`)
|
|
1651
|
+
},
|
|
1652
|
+
b
|
|
1653
|
+
))
|
|
1209
1654
|
},
|
|
1210
1655
|
r2
|
|
1211
1656
|
))
|
|
@@ -1221,17 +1666,36 @@ import { jsx as jsx2 } from "react/jsx-runtime";
|
|
|
1221
1666
|
var CONTAINER_ATTR = "data-ohw-ai-generated";
|
|
1222
1667
|
var REPLACED_ATTR = "data-ohw-ai-replaced-by";
|
|
1223
1668
|
var REMOVED_ATTR = "data-ohw-ai-removed";
|
|
1669
|
+
var TEMPLATE_HIDDEN_ATTR = "data-ohw-ai-template-hidden";
|
|
1670
|
+
var CHROME_SECTION_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
1671
|
+
function readRootVar(name) {
|
|
1672
|
+
if (typeof document === "undefined") return "";
|
|
1673
|
+
return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
|
1674
|
+
}
|
|
1675
|
+
function deriveBrandOverride() {
|
|
1676
|
+
const dark = readRootVar("--ohw-brand-dark");
|
|
1677
|
+
const primary = readRootVar("--ohw-brand-primary");
|
|
1678
|
+
const light = readRootVar("--ohw-brand-light");
|
|
1679
|
+
if (!dark || !primary || !light) return null;
|
|
1680
|
+
const accent = readRootVar("--ohw-brand-accent");
|
|
1681
|
+
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
1682
|
+
const body = readRootVar("--font-body");
|
|
1683
|
+
return {
|
|
1684
|
+
palette: { dark, primary, accent: accent || dark, light },
|
|
1685
|
+
fonts: {
|
|
1686
|
+
heading: heading || AI_DEFAULT_BRAND.fonts.heading,
|
|
1687
|
+
body: body || AI_DEFAULT_BRAND.fonts.body
|
|
1688
|
+
}
|
|
1689
|
+
};
|
|
1690
|
+
}
|
|
1224
1691
|
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");
|
|
1692
|
+
const dark = readRootVar("--color-dark");
|
|
1693
|
+
const primary = readRootVar("--color-primary");
|
|
1694
|
+
const light = readRootVar("--color-light");
|
|
1231
1695
|
if (!dark || !primary || !light) return null;
|
|
1232
|
-
const accent =
|
|
1233
|
-
const heading =
|
|
1234
|
-
const body =
|
|
1696
|
+
const accent = readRootVar("--color-accent");
|
|
1697
|
+
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
1698
|
+
const body = readRootVar("--font-body");
|
|
1235
1699
|
return {
|
|
1236
1700
|
palette: { dark, primary, accent: accent || dark, light },
|
|
1237
1701
|
fonts: {
|
|
@@ -1303,6 +1767,24 @@ function syncRemovedSections(state) {
|
|
|
1303
1767
|
}
|
|
1304
1768
|
}
|
|
1305
1769
|
}
|
|
1770
|
+
function syncTemplateHidden(state, pageHasSections) {
|
|
1771
|
+
const hide = state.hideTemplate === true && pageHasSections;
|
|
1772
|
+
for (const el of Array.from(document.querySelectorAll(`[${TEMPLATE_HIDDEN_ATTR}]`))) {
|
|
1773
|
+
if (!hide) {
|
|
1774
|
+
el.style.removeProperty("display");
|
|
1775
|
+
el.removeAttribute(TEMPLATE_HIDDEN_ATTR);
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
if (!hide) return;
|
|
1779
|
+
for (const el of Array.from(document.querySelectorAll("[data-ohw-section]"))) {
|
|
1780
|
+
if (el.hasAttribute(CONTAINER_ATTR)) continue;
|
|
1781
|
+
if (CHROME_SECTION_IDS.has(el.getAttribute("data-ohw-section") ?? "")) continue;
|
|
1782
|
+
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
1783
|
+
if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(REMOVED_ATTR)) continue;
|
|
1784
|
+
el.style.display = "none";
|
|
1785
|
+
el.setAttribute(TEMPLATE_HIDDEN_ATTR, "");
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1306
1788
|
function syncReplacedOriginals(state) {
|
|
1307
1789
|
for (const el of document.querySelectorAll(`[${REPLACED_ATTR}]`)) {
|
|
1308
1790
|
const byId = el.getAttribute(REPLACED_ATTR) ?? "";
|
|
@@ -1323,8 +1805,12 @@ function syncReplacedOriginals(state) {
|
|
|
1323
1805
|
}
|
|
1324
1806
|
function applyAiSectionsToDom(state, options) {
|
|
1325
1807
|
if (typeof document === "undefined") return;
|
|
1808
|
+
const brandOverride = deriveBrandOverride();
|
|
1326
1809
|
const templateBrand = deriveTemplateBrand();
|
|
1327
|
-
const
|
|
1810
|
+
const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
|
|
1811
|
+
const pagePath = window.location.pathname;
|
|
1812
|
+
const pageSections = state.sections.filter((entry) => (entry.path ?? "/") === pagePath);
|
|
1813
|
+
const activeIds = new Set(pageSections.map((entry) => entry.id));
|
|
1328
1814
|
for (const [id, section] of mounted) {
|
|
1329
1815
|
if (!activeIds.has(id)) {
|
|
1330
1816
|
section.root.unmount();
|
|
@@ -1332,8 +1818,8 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1332
1818
|
mounted.delete(id);
|
|
1333
1819
|
}
|
|
1334
1820
|
}
|
|
1335
|
-
for (const entry of
|
|
1336
|
-
const serialized = JSON.stringify(entry);
|
|
1821
|
+
for (const entry of pageSections) {
|
|
1822
|
+
const serialized = JSON.stringify(entry) + brandKey;
|
|
1337
1823
|
const existing = mounted.get(entry.id);
|
|
1338
1824
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
1339
1825
|
continue;
|
|
@@ -1347,6 +1833,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1347
1833
|
mounted.delete(entry.id);
|
|
1348
1834
|
}
|
|
1349
1835
|
container.setAttribute("data-ohw-section", entry.id);
|
|
1836
|
+
container.setAttribute("data-ohw-instance", entry.id);
|
|
1350
1837
|
container.setAttribute("data-ohw-section-label", entry.label);
|
|
1351
1838
|
placeContainer(container, entry);
|
|
1352
1839
|
const root = mounted.get(entry.id)?.root ?? createRoot(container);
|
|
@@ -1357,7 +1844,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1357
1844
|
AiTreeRenderer,
|
|
1358
1845
|
{
|
|
1359
1846
|
tree: entry.tree,
|
|
1360
|
-
brand: entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
1847
|
+
brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
1361
1848
|
resolveMedia,
|
|
1362
1849
|
editKeyPrefix: `ai.${entry.id}`
|
|
1363
1850
|
}
|
|
@@ -1368,6 +1855,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
1368
1855
|
}
|
|
1369
1856
|
syncReplacedOriginals(state);
|
|
1370
1857
|
syncRemovedSections(state);
|
|
1858
|
+
syncTemplateHidden(state, pageSections.length > 0);
|
|
1371
1859
|
}
|
|
1372
1860
|
|
|
1373
1861
|
// src/useLinkHrefGuardian.ts
|
|
@@ -1974,7 +2462,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
1974
2462
|
const autoId = useId();
|
|
1975
2463
|
const insertAfter = insertAfterProp ?? autoId;
|
|
1976
2464
|
const [schedule, setSchedule] = useState2(null);
|
|
1977
|
-
const [loading, setLoading] = useState2(
|
|
2465
|
+
const [loading, setLoading] = useState2(initialScheduleId !== null);
|
|
1978
2466
|
const [inEditor, setInEditor] = useState2(false);
|
|
1979
2467
|
const [isHovered, setIsHovered] = useState2(false);
|
|
1980
2468
|
const [modalState, setModalState] = useState2(null);
|
|
@@ -2148,8 +2636,10 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
2148
2636
|
"*"
|
|
2149
2637
|
);
|
|
2150
2638
|
};
|
|
2151
|
-
if (!inEditor && !loading && !schedule) return null;
|
|
2152
2639
|
const sectionId = `scheduling-${insertAfter}`;
|
|
2640
|
+
if (!inEditor && !loading && !schedule) {
|
|
2641
|
+
return /* @__PURE__ */ jsx4("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
|
|
2642
|
+
}
|
|
2153
2643
|
return /* @__PURE__ */ jsxs3(
|
|
2154
2644
|
"section",
|
|
2155
2645
|
{
|
|
@@ -7057,13 +7547,17 @@ function MediaOverlay({
|
|
|
7057
7547
|
hover,
|
|
7058
7548
|
isUploading,
|
|
7059
7549
|
fadingOut = false,
|
|
7550
|
+
selected = false,
|
|
7551
|
+
hovered = false,
|
|
7060
7552
|
onFadeOutComplete,
|
|
7061
7553
|
onReplace,
|
|
7554
|
+
onSelect,
|
|
7062
7555
|
onVideoSettingsChange
|
|
7063
7556
|
}) {
|
|
7064
7557
|
const { rect } = hover;
|
|
7065
7558
|
const skeletonRef = React7.useRef(null);
|
|
7066
7559
|
const isVideo = hover.elementType === "video";
|
|
7560
|
+
const showChrome = !selected || hovered;
|
|
7067
7561
|
const autoplay = hover.videoAutoplay ?? true;
|
|
7068
7562
|
const muted = hover.videoMuted ?? true;
|
|
7069
7563
|
const box = {
|
|
@@ -7098,7 +7592,7 @@ function MediaOverlay({
|
|
|
7098
7592
|
}
|
|
7099
7593
|
);
|
|
7100
7594
|
}
|
|
7101
|
-
const settingsBar = isVideo && !hover.isDragOver ? /* @__PURE__ */ jsxs7(
|
|
7595
|
+
const settingsBar = isVideo && !hover.isDragOver && showChrome ? /* @__PURE__ */ jsxs7(
|
|
7102
7596
|
"div",
|
|
7103
7597
|
{
|
|
7104
7598
|
"data-ohw-bridge": "",
|
|
@@ -7168,11 +7662,13 @@ function MediaOverlay({
|
|
|
7168
7662
|
// in-document, pointer-events does it natively. The button below opts back in, so
|
|
7169
7663
|
// Replace still works.
|
|
7170
7664
|
pointerEvents: hover.hasTextOverlap ? "none" : "auto",
|
|
7171
|
-
|
|
7172
|
-
|
|
7665
|
+
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
7666
|
+
// than hovered. Hover keeps the existing tinted preview.
|
|
7667
|
+
boxShadow: selected ? "inset 0 0 0 2px var(--color-primary)" : "inset 0 0 0 1.5px var(--color-primary)",
|
|
7668
|
+
background: selected ? "transparent" : "color-mix(in srgb, var(--color-primary) 20%, transparent)"
|
|
7173
7669
|
},
|
|
7174
|
-
onClick: () => onReplace(hover.key),
|
|
7175
|
-
children: /* @__PURE__ */ jsxs7(
|
|
7670
|
+
onClick: () => onSelect && !selected ? onSelect(hover.key) : onReplace(hover.key),
|
|
7671
|
+
children: showChrome && /* @__PURE__ */ jsxs7(
|
|
7176
7672
|
Button,
|
|
7177
7673
|
{
|
|
7178
7674
|
"data-ohw-media-overlay": "",
|
|
@@ -7191,7 +7687,7 @@ function MediaOverlay({
|
|
|
7191
7687
|
},
|
|
7192
7688
|
children: [
|
|
7193
7689
|
isVideo ? /* @__PURE__ */ jsx15(Film, { size: 14 }) : /* @__PURE__ */ jsx15(ImageIcon, { size: 14 }),
|
|
7194
|
-
isVideo ? "Replace video" : "Replace image"
|
|
7690
|
+
isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image"
|
|
7195
7691
|
]
|
|
7196
7692
|
}
|
|
7197
7693
|
)
|
|
@@ -7261,6 +7757,9 @@ import { Check, X } from "lucide-react";
|
|
|
7261
7757
|
|
|
7262
7758
|
// src/lib/sections.ts
|
|
7263
7759
|
var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
7760
|
+
function isChromeSection(el) {
|
|
7761
|
+
return el.matches("header, nav, footer, aside");
|
|
7762
|
+
}
|
|
7264
7763
|
function titleCaseSectionId(id) {
|
|
7265
7764
|
return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
7266
7765
|
}
|
|
@@ -7271,6 +7770,8 @@ function parseSectionsFromRoot(root) {
|
|
|
7271
7770
|
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
7272
7771
|
if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
|
|
7273
7772
|
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
7773
|
+
if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
|
|
7774
|
+
continue;
|
|
7274
7775
|
seen.add(id);
|
|
7275
7776
|
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
7276
7777
|
sections.push({ id, label });
|
|
@@ -7288,8 +7789,12 @@ function parseSectionsFromHtml(html) {
|
|
|
7288
7789
|
|
|
7289
7790
|
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
7290
7791
|
import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
7291
|
-
function
|
|
7292
|
-
const
|
|
7792
|
+
function findSectionElement(instanceId) {
|
|
7793
|
+
const escaped = CSS.escape(instanceId);
|
|
7794
|
+
return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
|
|
7795
|
+
}
|
|
7796
|
+
function readRect(instanceId) {
|
|
7797
|
+
const el = findSectionElement(instanceId);
|
|
7293
7798
|
if (!el) return null;
|
|
7294
7799
|
const r2 = el.getBoundingClientRect();
|
|
7295
7800
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
@@ -7312,7 +7817,7 @@ function useLiveSectionRect(sectionId) {
|
|
|
7312
7817
|
const opts = { capture: true, passive: true };
|
|
7313
7818
|
window.addEventListener("scroll", update, opts);
|
|
7314
7819
|
window.addEventListener("resize", update);
|
|
7315
|
-
const el =
|
|
7820
|
+
const el = findSectionElement(sectionId);
|
|
7316
7821
|
const ro = el ? new ResizeObserver(update) : null;
|
|
7317
7822
|
if (el && ro) ro.observe(el);
|
|
7318
7823
|
const interval = setInterval(update, 500);
|
|
@@ -7325,6 +7830,14 @@ function useLiveSectionRect(sectionId) {
|
|
|
7325
7830
|
}, [sectionId]);
|
|
7326
7831
|
return rect;
|
|
7327
7832
|
}
|
|
7833
|
+
function computeSectionBoundaryFlags(instanceId) {
|
|
7834
|
+
const topLevel = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
7835
|
+
(el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
|
|
7836
|
+
);
|
|
7837
|
+
const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
|
|
7838
|
+
if (index === -1) return { isFirst: true, isLast: true };
|
|
7839
|
+
return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
|
|
7840
|
+
}
|
|
7328
7841
|
var PRIMARY2 = "#0885FE";
|
|
7329
7842
|
function edgeAwareRadius(rect) {
|
|
7330
7843
|
const container = window.innerWidth <= 480 ? 16 : 24;
|
|
@@ -7398,6 +7911,7 @@ function AiSectionOverlay({
|
|
|
7398
7911
|
}) {
|
|
7399
7912
|
const [selectedId, setSelectedId] = useState4(null);
|
|
7400
7913
|
const [reviewId, setReviewId] = useState4(null);
|
|
7914
|
+
const [reviewButtonsHidden, setReviewButtonsHidden] = useState4(false);
|
|
7401
7915
|
const reviewIdRef = useRef4(null);
|
|
7402
7916
|
reviewIdRef.current = reviewId;
|
|
7403
7917
|
const selectedIdRef = useRef4(null);
|
|
@@ -7406,7 +7920,7 @@ function AiSectionOverlay({
|
|
|
7406
7920
|
(el) => {
|
|
7407
7921
|
postToParent2({
|
|
7408
7922
|
type: "ow:section-selected",
|
|
7409
|
-
sectionId: el
|
|
7923
|
+
sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
|
|
7410
7924
|
sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
|
|
7411
7925
|
});
|
|
7412
7926
|
},
|
|
@@ -7415,7 +7929,7 @@ function AiSectionOverlay({
|
|
|
7415
7929
|
const selectFromElement = useCallback2(
|
|
7416
7930
|
(el, options) => {
|
|
7417
7931
|
const sectionEl = el?.closest("[data-ohw-section]") ?? null;
|
|
7418
|
-
const id = sectionEl
|
|
7932
|
+
const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
|
|
7419
7933
|
if (id === selectedIdRef.current) return;
|
|
7420
7934
|
setSelectedId(id);
|
|
7421
7935
|
if (options?.report !== false) report(sectionEl);
|
|
@@ -7456,9 +7970,10 @@ function AiSectionOverlay({
|
|
|
7456
7970
|
}
|
|
7457
7971
|
const found = readRect(sectionId) != null;
|
|
7458
7972
|
setReviewId(found ? sectionId : null);
|
|
7973
|
+
setReviewButtonsHidden(e.data.hideButtons === true);
|
|
7459
7974
|
postToParent2({ type: "ow:ai-review-started", sectionId, found });
|
|
7460
7975
|
if (found) {
|
|
7461
|
-
document.querySelector(`[data-ohw-
|
|
7976
|
+
document.querySelector(`[data-ohw-instance="${CSS.escape(sectionId)}"]`)?.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
7462
7977
|
}
|
|
7463
7978
|
}
|
|
7464
7979
|
};
|
|
@@ -7477,7 +7992,7 @@ function AiSectionOverlay({
|
|
|
7477
7992
|
return;
|
|
7478
7993
|
}
|
|
7479
7994
|
const sec = t.closest("[data-ohw-section]");
|
|
7480
|
-
setHoveredId(sec
|
|
7995
|
+
setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
|
|
7481
7996
|
};
|
|
7482
7997
|
const onLeave = () => setHoveredId(null);
|
|
7483
7998
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -7509,9 +8024,30 @@ function AiSectionOverlay({
|
|
|
7509
8024
|
},
|
|
7510
8025
|
[postToParent2]
|
|
7511
8026
|
);
|
|
7512
|
-
const
|
|
8027
|
+
const activeSelectionId = reviewId ? null : selectedId;
|
|
8028
|
+
const selectionRect = useLiveSectionRect(activeSelectionId);
|
|
7513
8029
|
const reviewRect = useLiveSectionRect(reviewId);
|
|
7514
8030
|
const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
|
|
8031
|
+
useEffect4(() => {
|
|
8032
|
+
const selectedEl = activeSelectionId ? findSectionElement(activeSelectionId) : null;
|
|
8033
|
+
if (!activeSelectionId || !selectionRect || selectedEl && isChromeSection(selectedEl)) {
|
|
8034
|
+
postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
|
|
8035
|
+
return;
|
|
8036
|
+
}
|
|
8037
|
+
const { isFirst, isLast } = computeSectionBoundaryFlags(activeSelectionId);
|
|
8038
|
+
postToParent2({
|
|
8039
|
+
type: "ow:section-rect",
|
|
8040
|
+
instanceId: activeSelectionId,
|
|
8041
|
+
rect: {
|
|
8042
|
+
top: selectionRect.top + window.scrollY,
|
|
8043
|
+
left: selectionRect.left + window.scrollX,
|
|
8044
|
+
width: selectionRect.width,
|
|
8045
|
+
height: selectionRect.height
|
|
8046
|
+
},
|
|
8047
|
+
isFirst,
|
|
8048
|
+
isLast
|
|
8049
|
+
});
|
|
8050
|
+
}, [activeSelectionId, selectionRect, postToParent2]);
|
|
7515
8051
|
return /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
7516
8052
|
hoverRect && /* @__PURE__ */ jsx17(
|
|
7517
8053
|
"div",
|
|
@@ -7562,13 +8098,16 @@ function AiSectionOverlay({
|
|
|
7562
8098
|
border: `2px solid ${PRIMARY2}`,
|
|
7563
8099
|
borderRadius: edgeAwareRadius(reviewRect),
|
|
7564
8100
|
zIndex: 2147483200,
|
|
7565
|
-
// The veil itself: swallows clicks so the section stays locked until decided.
|
|
8101
|
+
// The veil itself: swallows clicks so the section stays locked until decided. This
|
|
8102
|
+
// stopPropagation only guards the bubble phase; the bridge's capture-phase click
|
|
8103
|
+
// handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
|
|
8104
|
+
// Accept/Discard resolves to the media beneath and opens the file picker.
|
|
7566
8105
|
background: "rgba(8, 133, 254, 0.04)",
|
|
7567
8106
|
pointerEvents: "auto",
|
|
7568
8107
|
cursor: "default"
|
|
7569
8108
|
},
|
|
7570
8109
|
onClick: (e) => e.stopPropagation(),
|
|
7571
|
-
children: /* @__PURE__ */ jsxs9(
|
|
8110
|
+
children: !reviewButtonsHidden && /* @__PURE__ */ jsxs9(
|
|
7572
8111
|
"div",
|
|
7573
8112
|
{
|
|
7574
8113
|
style: {
|
|
@@ -7593,6 +8132,59 @@ function AiSectionOverlay({
|
|
|
7593
8132
|
|
|
7594
8133
|
// src/lib/section-instances.ts
|
|
7595
8134
|
var SECTION_ORDER_KEY = "__ohw_section_order";
|
|
8135
|
+
function topLevelSections() {
|
|
8136
|
+
return Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
8137
|
+
(el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
|
|
8138
|
+
);
|
|
8139
|
+
}
|
|
8140
|
+
function instanceIdOf(el) {
|
|
8141
|
+
return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
|
|
8142
|
+
}
|
|
8143
|
+
function planSectionMove(instanceId, targetIndex, currentPath) {
|
|
8144
|
+
const sections = topLevelSections();
|
|
8145
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8146
|
+
if (index === -1) return null;
|
|
8147
|
+
const dragged = sections[index];
|
|
8148
|
+
const others = sections.filter((_, i) => i !== index);
|
|
8149
|
+
const clamped = Math.max(0, Math.min(targetIndex, others.length));
|
|
8150
|
+
const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
|
|
8151
|
+
return reordered.map((el, order) => ({
|
|
8152
|
+
instanceId: instanceIdOf(el),
|
|
8153
|
+
type: el.getAttribute("data-ohw-section") ?? "",
|
|
8154
|
+
order,
|
|
8155
|
+
pagePath: currentPath
|
|
8156
|
+
}));
|
|
8157
|
+
}
|
|
8158
|
+
function moveSectionInstance(instanceId, direction, currentPath) {
|
|
8159
|
+
const sections = topLevelSections();
|
|
8160
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8161
|
+
if (index === -1) return null;
|
|
8162
|
+
const siblingIndex = direction === "up" ? index - 1 : index + 1;
|
|
8163
|
+
if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
|
|
8164
|
+
const entries = planSectionMove(instanceId, siblingIndex, currentPath);
|
|
8165
|
+
if (!entries) return null;
|
|
8166
|
+
applyPersistedOrder(entries);
|
|
8167
|
+
return entries;
|
|
8168
|
+
}
|
|
8169
|
+
function applyPersistedOrder(entries) {
|
|
8170
|
+
if (entries.length === 0) return;
|
|
8171
|
+
const sections = topLevelSections();
|
|
8172
|
+
if (sections.length === 0) return;
|
|
8173
|
+
const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
|
|
8174
|
+
const ordered = [...sections].sort((a, b) => {
|
|
8175
|
+
const aOrder = orderIndex.get(instanceIdOf(a));
|
|
8176
|
+
const bOrder = orderIndex.get(instanceIdOf(b));
|
|
8177
|
+
if (aOrder === void 0 && bOrder === void 0) return 0;
|
|
8178
|
+
if (aOrder === void 0) return 1;
|
|
8179
|
+
if (bOrder === void 0) return -1;
|
|
8180
|
+
return aOrder - bOrder;
|
|
8181
|
+
});
|
|
8182
|
+
let prev = null;
|
|
8183
|
+
for (const el of ordered) {
|
|
8184
|
+
if (prev) prev.after(el);
|
|
8185
|
+
prev = el;
|
|
8186
|
+
}
|
|
8187
|
+
}
|
|
7596
8188
|
function getPageSectionOrderEntries(raw, currentPath) {
|
|
7597
8189
|
if (!raw) return [];
|
|
7598
8190
|
try {
|
|
@@ -7630,6 +8222,7 @@ function initSectionInstancesFromContent(content, currentPath) {
|
|
|
7630
8222
|
rekeySectionSubtree(clone, entry.instanceId);
|
|
7631
8223
|
original.insertAdjacentElement("afterend", clone);
|
|
7632
8224
|
}
|
|
8225
|
+
applyPersistedOrder(entries);
|
|
7633
8226
|
}
|
|
7634
8227
|
|
|
7635
8228
|
// src/OhhwellsBridge.tsx
|
|
@@ -10174,8 +10767,13 @@ var GLYPH_SELECTOR = "svg, img";
|
|
|
10174
10767
|
function referenceBox(slot) {
|
|
10175
10768
|
const row = slot.closest("[data-ohw-socials-row]") ?? slot.closest("a")?.parentElement ?? null;
|
|
10176
10769
|
const neighbour = row ? Array.from(row.querySelectorAll('[data-ohw-editable="icon"]')).find((el) => el !== slot) : null;
|
|
10177
|
-
|
|
10178
|
-
|
|
10770
|
+
if (neighbour) {
|
|
10771
|
+
const box2 = neighbour.querySelector(GLYPH_SELECTOR)?.getBoundingClientRect();
|
|
10772
|
+
if (box2?.width && box2.height) return box2;
|
|
10773
|
+
}
|
|
10774
|
+
const own = slot.getBoundingClientRect();
|
|
10775
|
+
if (own.width && own.height) return own;
|
|
10776
|
+
const box = slot.querySelector(GLYPH_SELECTOR)?.getBoundingClientRect() ?? null;
|
|
10179
10777
|
return box?.width && box.height ? box : null;
|
|
10180
10778
|
}
|
|
10181
10779
|
function iconMarkupSizedFor(slot, markup) {
|
|
@@ -10254,7 +10852,8 @@ function findSocialsRow(el) {
|
|
|
10254
10852
|
}
|
|
10255
10853
|
function isSocialsRow(el) {
|
|
10256
10854
|
const anchors = Array.from(el.querySelectorAll("a"));
|
|
10257
|
-
|
|
10855
|
+
if (!anchors.length || !anchors.some((anchor) => isSocialItem(anchor))) return false;
|
|
10856
|
+
return findSocialsRow(anchors[0]) === el;
|
|
10258
10857
|
}
|
|
10259
10858
|
var MAX_SOCIAL_ITEMS_PER_ROW = 7;
|
|
10260
10859
|
function canAddSocialItem(row) {
|
|
@@ -10292,6 +10891,7 @@ function markSocialsRows(root = document) {
|
|
|
10292
10891
|
});
|
|
10293
10892
|
listSocialsRows(root).forEach((row) => {
|
|
10294
10893
|
row.setAttribute(SOCIALS_ROW_ATTR, "");
|
|
10894
|
+
allowRowToWrap(row);
|
|
10295
10895
|
const items = listSocialItems(row);
|
|
10296
10896
|
const firstUnit = items[0] ? socialRowUnit(items[0], row) : null;
|
|
10297
10897
|
if (firstUnit) rowTemplates.set(rowKeyOf(row), firstUnit.outerHTML);
|
|
@@ -10586,7 +11186,29 @@ function applySocialsDisplayToRow(row, display) {
|
|
|
10586
11186
|
const icon = item.querySelector(ICON_SELECTOR);
|
|
10587
11187
|
if (label) label.style.display = display.text ? "" : "none";
|
|
10588
11188
|
if (icon) icon.style.display = display.icon ? "" : "none";
|
|
11189
|
+
layOutIconAndLabel(item, Boolean(display.text && display.icon));
|
|
10589
11190
|
});
|
|
11191
|
+
allowRowToWrap(row);
|
|
11192
|
+
}
|
|
11193
|
+
function layOutIconAndLabel(item, on) {
|
|
11194
|
+
const hasBoth = Boolean(item.querySelector(ICON_SELECTOR)) && Boolean(socialLabelElement(item));
|
|
11195
|
+
if (!hasBoth) {
|
|
11196
|
+
item.style.display = "";
|
|
11197
|
+
item.style.alignItems = "";
|
|
11198
|
+
item.style.gap = "";
|
|
11199
|
+
item.style.whiteSpace = "";
|
|
11200
|
+
item.style.flex = "";
|
|
11201
|
+
return;
|
|
11202
|
+
}
|
|
11203
|
+
item.style.display = on ? "inline-flex" : "";
|
|
11204
|
+
item.style.alignItems = on ? "center" : "";
|
|
11205
|
+
item.style.gap = on ? "8px" : "";
|
|
11206
|
+
item.style.whiteSpace = on ? "nowrap" : "";
|
|
11207
|
+
item.style.flex = on ? "0 0 auto" : "";
|
|
11208
|
+
}
|
|
11209
|
+
function allowRowToWrap(row) {
|
|
11210
|
+
const display = row.ownerDocument.defaultView?.getComputedStyle(row).display ?? "";
|
|
11211
|
+
if (display === "flex" || display === "inline-flex") row.style.flexWrap = "wrap";
|
|
10590
11212
|
}
|
|
10591
11213
|
function applySocialsDisplayFromContent(content, root = document) {
|
|
10592
11214
|
const stored = parseSocialsDisplay(content[SOCIALS_DISPLAY_KEY]);
|
|
@@ -11796,6 +12418,7 @@ function readLogoSizeState(content, placement) {
|
|
|
11796
12418
|
function getLogoElement(el) {
|
|
11797
12419
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
11798
12420
|
if (marked) return marked;
|
|
12421
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
11799
12422
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
11800
12423
|
if (!root) return null;
|
|
11801
12424
|
const anchor = el.closest("a");
|
|
@@ -12675,101 +13298,428 @@ function useNavItemDrag({
|
|
|
12675
13298
|
};
|
|
12676
13299
|
}
|
|
12677
13300
|
|
|
12678
|
-
// src/
|
|
12679
|
-
import {
|
|
12680
|
-
import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
12681
|
-
function FooterContainerChrome({
|
|
12682
|
-
rect,
|
|
12683
|
-
onAdd,
|
|
12684
|
-
addDisabled = false
|
|
12685
|
-
}) {
|
|
12686
|
-
const chromeGap = 6;
|
|
12687
|
-
const buttonMargin = 7;
|
|
12688
|
-
return /* @__PURE__ */ jsx29(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx29(
|
|
12689
|
-
"div",
|
|
12690
|
-
{
|
|
12691
|
-
"data-ohw-footer-container-chrome": "",
|
|
12692
|
-
"data-ohw-bridge": "",
|
|
12693
|
-
className: "pointer-events-none fixed z-[2147483647]",
|
|
12694
|
-
style: {
|
|
12695
|
-
top: rect.top - chromeGap,
|
|
12696
|
-
left: rect.left - chromeGap,
|
|
12697
|
-
width: rect.width + chromeGap * 2,
|
|
12698
|
-
height: rect.height + chromeGap * 2
|
|
12699
|
-
},
|
|
12700
|
-
children: /* @__PURE__ */ jsxs19(Tooltip, { children: [
|
|
12701
|
-
/* @__PURE__ */ jsx29(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx29(
|
|
12702
|
-
"button",
|
|
12703
|
-
{
|
|
12704
|
-
type: "button",
|
|
12705
|
-
"data-ohw-footer-add-button": "",
|
|
12706
|
-
disabled: addDisabled,
|
|
12707
|
-
className: "pointer-events-auto absolute left-1/2 flex size-7 -translate-x-1/2 -translate-y-full items-center justify-center rounded-[10px] border border-border bg-background p-0.5 shadow-sm transition-colors hover:bg-muted/80 disabled:pointer-events-none disabled:opacity-40",
|
|
12708
|
-
style: { top: chromeGap - buttonMargin },
|
|
12709
|
-
"aria-label": "Add item",
|
|
12710
|
-
onMouseDown: (e) => {
|
|
12711
|
-
e.preventDefault();
|
|
12712
|
-
e.stopPropagation();
|
|
12713
|
-
},
|
|
12714
|
-
onClick: (e) => {
|
|
12715
|
-
e.preventDefault();
|
|
12716
|
-
e.stopPropagation();
|
|
12717
|
-
if (addDisabled) return;
|
|
12718
|
-
onAdd();
|
|
12719
|
-
},
|
|
12720
|
-
children: /* @__PURE__ */ jsx29(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
12721
|
-
}
|
|
12722
|
-
) }),
|
|
12723
|
-
/* @__PURE__ */ jsx29(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
12724
|
-
] })
|
|
12725
|
-
}
|
|
12726
|
-
) });
|
|
12727
|
-
}
|
|
13301
|
+
// src/useSectionDrag.ts
|
|
13302
|
+
import { useCallback as useCallback7, useEffect as useEffect11, useRef as useRef9, useState as useState10 } from "react";
|
|
12728
13303
|
|
|
12729
|
-
// src/lib/
|
|
12730
|
-
|
|
12731
|
-
|
|
12732
|
-
var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
|
|
12733
|
-
var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
|
|
12734
|
-
var CAROUSEL_EVENT = "ohw:carousel-change";
|
|
12735
|
-
function listCarouselKeys() {
|
|
12736
|
-
const keys = /* @__PURE__ */ new Set();
|
|
12737
|
-
document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
|
|
12738
|
-
const key = el.getAttribute("data-ohw-key");
|
|
12739
|
-
if (key) keys.add(key);
|
|
12740
|
-
});
|
|
12741
|
-
return [...keys];
|
|
13304
|
+
// src/lib/section-dnd.ts
|
|
13305
|
+
function isFooterSection(el) {
|
|
13306
|
+
return el.dataset.ohwSection === "footer";
|
|
12742
13307
|
}
|
|
12743
|
-
function
|
|
12744
|
-
|
|
12745
|
-
|
|
13308
|
+
function buildSectionDropSlots(draggedInstanceId) {
|
|
13309
|
+
const sections = topLevelSections().filter(
|
|
13310
|
+
(el) => instanceIdOf(el) !== draggedInstanceId && !isFooterSection(el)
|
|
12746
13311
|
);
|
|
13312
|
+
const slots = [];
|
|
13313
|
+
if (sections.length === 0) return slots;
|
|
13314
|
+
const left = 0;
|
|
13315
|
+
const width = document.documentElement.clientWidth;
|
|
13316
|
+
for (let i = 0; i <= sections.length; i++) {
|
|
13317
|
+
let y;
|
|
13318
|
+
if (i === 0) {
|
|
13319
|
+
y = sections[0].getBoundingClientRect().top;
|
|
13320
|
+
} else if (i === sections.length) {
|
|
13321
|
+
y = sections[sections.length - 1].getBoundingClientRect().bottom;
|
|
13322
|
+
} else {
|
|
13323
|
+
const prev = sections[i - 1].getBoundingClientRect();
|
|
13324
|
+
const next = sections[i].getBoundingClientRect();
|
|
13325
|
+
y = (prev.bottom + next.top) / 2;
|
|
13326
|
+
}
|
|
13327
|
+
slots.push({ insertIndex: i, y, left, width });
|
|
13328
|
+
}
|
|
13329
|
+
return slots;
|
|
12747
13330
|
}
|
|
12748
|
-
function
|
|
12749
|
-
|
|
12750
|
-
|
|
12751
|
-
|
|
12752
|
-
|
|
12753
|
-
try {
|
|
12754
|
-
const parsed = JSON.parse(raw);
|
|
12755
|
-
if (!Array.isArray(parsed)) return [];
|
|
12756
|
-
return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
|
|
12757
|
-
} catch {
|
|
12758
|
-
return [];
|
|
13331
|
+
function hitTestSectionDropSlot(y, slots) {
|
|
13332
|
+
let best = null;
|
|
13333
|
+
for (const slot of slots) {
|
|
13334
|
+
const dist = Math.abs(y - slot.y);
|
|
13335
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
12759
13336
|
}
|
|
13337
|
+
return best?.slot ?? null;
|
|
12760
13338
|
}
|
|
12761
|
-
|
|
12762
|
-
|
|
12763
|
-
|
|
12764
|
-
|
|
12765
|
-
|
|
12766
|
-
|
|
12767
|
-
|
|
12768
|
-
|
|
12769
|
-
|
|
13339
|
+
|
|
13340
|
+
// src/useSectionDrag.ts
|
|
13341
|
+
var PRESS_THRESHOLD = 10;
|
|
13342
|
+
var EDGE_ZONE = 60;
|
|
13343
|
+
var MAX_AUTO_SCROLL_SPEED = 18;
|
|
13344
|
+
var SECTION_DRAG_EXCLUDED_SELECTOR = [
|
|
13345
|
+
"[data-ohw-toolbar]",
|
|
13346
|
+
"[data-ohw-edit-chrome]",
|
|
13347
|
+
"[data-ohw-item-interaction]",
|
|
13348
|
+
"[data-ohw-drag-handle-container]",
|
|
13349
|
+
'[data-slot="drag-handle"]',
|
|
13350
|
+
"[data-ohw-item-toolbar-anchor]",
|
|
13351
|
+
"[data-ohw-item-drag-surface]",
|
|
13352
|
+
"[data-ohw-more-menu]",
|
|
13353
|
+
'[data-slot="dropdown-menu-content"]',
|
|
13354
|
+
'[data-slot="dropdown-menu-item"]',
|
|
13355
|
+
"[data-ohw-state-toggle]",
|
|
13356
|
+
"[data-ohw-max-badge]",
|
|
13357
|
+
"[data-ohw-floating-panel]",
|
|
13358
|
+
"[data-ohw-section-picker]",
|
|
13359
|
+
"[data-ohw-link-popover-root]",
|
|
13360
|
+
"[data-ohw-link-modal-root]",
|
|
13361
|
+
"[data-ohw-link-page-dropdown]",
|
|
13362
|
+
'[data-slot="popover-content"]',
|
|
13363
|
+
'[data-slot="dialog-content"]',
|
|
13364
|
+
'[data-slot="dialog-overlay"]',
|
|
13365
|
+
"[data-ohw-ai-review]",
|
|
13366
|
+
"[data-ohw-editable]",
|
|
13367
|
+
"[data-ohw-editable-state]",
|
|
13368
|
+
"[contenteditable]",
|
|
13369
|
+
"[data-ohw-href-key]",
|
|
13370
|
+
"[data-ohw-footer-col]",
|
|
13371
|
+
"[data-ohw-social-label]",
|
|
13372
|
+
"a",
|
|
13373
|
+
"button",
|
|
13374
|
+
'[role="button"]',
|
|
13375
|
+
'[data-ohw-role="navbar-button"]',
|
|
13376
|
+
'[data-ohw-role="button"]',
|
|
13377
|
+
"[data-ohw-carousel]",
|
|
13378
|
+
"[data-ohw-carousel-value]",
|
|
13379
|
+
"[data-ohw-carousel-slide]",
|
|
13380
|
+
"[data-ohw-carousel-overlay]",
|
|
13381
|
+
"[data-ohw-media-chrome]",
|
|
13382
|
+
"[data-ohw-media-overlay]",
|
|
13383
|
+
"[data-ohw-media-skeleton]"
|
|
13384
|
+
].join(", ");
|
|
13385
|
+
function visibleClip(ps) {
|
|
13386
|
+
if (!ps) return null;
|
|
13387
|
+
const top = Math.max(0, ps.headerH - ps.iframeOffsetTop);
|
|
13388
|
+
const bottom = Math.min(window.innerHeight, ps.headerH + ps.canvasH - ps.iframeOffsetTop);
|
|
13389
|
+
return { top, bottom: Math.max(top, bottom) };
|
|
12770
13390
|
}
|
|
12771
|
-
function
|
|
12772
|
-
|
|
13391
|
+
function useSectionDrag({
|
|
13392
|
+
isEditMode,
|
|
13393
|
+
editContentRef,
|
|
13394
|
+
postToParentRef,
|
|
13395
|
+
parentScrollRef,
|
|
13396
|
+
navDragRef,
|
|
13397
|
+
footerDragRef,
|
|
13398
|
+
suppressNextClickRef,
|
|
13399
|
+
suppressClickUntilRef
|
|
13400
|
+
}) {
|
|
13401
|
+
const sectionDragRef = useRef9(null);
|
|
13402
|
+
const [sectionDropSlots, setSectionDropSlots] = useState10([]);
|
|
13403
|
+
const [activeSectionDropIndex, setActiveSectionDropIndex] = useState10(null);
|
|
13404
|
+
const [isSectionDragging, setIsSectionDragging] = useState10(false);
|
|
13405
|
+
const sectionPointerDragRef = useRef9(null);
|
|
13406
|
+
const autoScrollRafRef = useRef9(null);
|
|
13407
|
+
const autoScrollDeltaRef = useRef9(0);
|
|
13408
|
+
const stopAutoScroll = useCallback7(() => {
|
|
13409
|
+
if (autoScrollRafRef.current != null) {
|
|
13410
|
+
cancelAnimationFrame(autoScrollRafRef.current);
|
|
13411
|
+
autoScrollRafRef.current = null;
|
|
13412
|
+
}
|
|
13413
|
+
autoScrollDeltaRef.current = 0;
|
|
13414
|
+
}, []);
|
|
13415
|
+
const tickAutoScroll = useCallback7(() => {
|
|
13416
|
+
if (!sectionDragRef.current) {
|
|
13417
|
+
stopAutoScroll();
|
|
13418
|
+
return;
|
|
13419
|
+
}
|
|
13420
|
+
if (autoScrollDeltaRef.current !== 0) {
|
|
13421
|
+
postToParentRef.current({ type: "ow:request-scroll", deltaY: autoScrollDeltaRef.current });
|
|
13422
|
+
}
|
|
13423
|
+
autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
|
|
13424
|
+
}, [postToParentRef, stopAutoScroll]);
|
|
13425
|
+
const updateAutoScroll = useCallback7(
|
|
13426
|
+
(clientY) => {
|
|
13427
|
+
const clip = visibleClip(parentScrollRef.current);
|
|
13428
|
+
let delta = 0;
|
|
13429
|
+
if (clip) {
|
|
13430
|
+
const distTop = clientY - clip.top;
|
|
13431
|
+
const distBottom = clip.bottom - clientY;
|
|
13432
|
+
if (distTop >= 0 && distTop < EDGE_ZONE) {
|
|
13433
|
+
delta = -MAX_AUTO_SCROLL_SPEED * (1 - distTop / EDGE_ZONE);
|
|
13434
|
+
} else if (distBottom >= 0 && distBottom < EDGE_ZONE) {
|
|
13435
|
+
delta = MAX_AUTO_SCROLL_SPEED * (1 - distBottom / EDGE_ZONE);
|
|
13436
|
+
}
|
|
13437
|
+
}
|
|
13438
|
+
autoScrollDeltaRef.current = delta;
|
|
13439
|
+
if (delta !== 0 && autoScrollRafRef.current == null) {
|
|
13440
|
+
autoScrollRafRef.current = requestAnimationFrame(tickAutoScroll);
|
|
13441
|
+
} else if (delta === 0) {
|
|
13442
|
+
stopAutoScroll();
|
|
13443
|
+
}
|
|
13444
|
+
},
|
|
13445
|
+
[parentScrollRef, stopAutoScroll, tickAutoScroll]
|
|
13446
|
+
);
|
|
13447
|
+
const clearSectionDragVisuals = useCallback7(() => {
|
|
13448
|
+
sectionDragRef.current?.draggedEl.removeAttribute("data-ohw-section-dragging");
|
|
13449
|
+
sectionDragRef.current = null;
|
|
13450
|
+
setSectionDropSlots([]);
|
|
13451
|
+
setActiveSectionDropIndex(null);
|
|
13452
|
+
setIsSectionDragging(false);
|
|
13453
|
+
stopAutoScroll();
|
|
13454
|
+
document.documentElement.removeAttribute("data-ohw-section-dragging-root");
|
|
13455
|
+
unlockItemDragInteraction();
|
|
13456
|
+
}, [stopAutoScroll]);
|
|
13457
|
+
const refreshSectionDragVisuals = useCallback7(
|
|
13458
|
+
(session, clientX, clientY) => {
|
|
13459
|
+
session.lastClientX = clientX;
|
|
13460
|
+
session.lastClientY = clientY;
|
|
13461
|
+
const slots = buildSectionDropSlots(session.instanceId);
|
|
13462
|
+
const activeSlot = hitTestSectionDropSlot(clientY, slots);
|
|
13463
|
+
session.activeSlot = activeSlot;
|
|
13464
|
+
setSectionDropSlots(slots);
|
|
13465
|
+
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
13466
|
+
setActiveSectionDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
13467
|
+
updateAutoScroll(clientY);
|
|
13468
|
+
},
|
|
13469
|
+
[updateAutoScroll]
|
|
13470
|
+
);
|
|
13471
|
+
const beginSectionDrag = useCallback7(
|
|
13472
|
+
(session) => {
|
|
13473
|
+
sectionDragRef.current = session;
|
|
13474
|
+
setIsSectionDragging(true);
|
|
13475
|
+
lockItemDuringDrag();
|
|
13476
|
+
document.documentElement.setAttribute("data-ohw-section-dragging-root", "");
|
|
13477
|
+
session.draggedEl.setAttribute("data-ohw-section-dragging", "");
|
|
13478
|
+
refreshSectionDragVisuals(session, session.lastClientX, session.lastClientY);
|
|
13479
|
+
},
|
|
13480
|
+
[refreshSectionDragVisuals]
|
|
13481
|
+
);
|
|
13482
|
+
const commitSectionDrag = useCallback7(() => {
|
|
13483
|
+
const session = sectionDragRef.current;
|
|
13484
|
+
if (!session) {
|
|
13485
|
+
clearSectionDragVisuals();
|
|
13486
|
+
return;
|
|
13487
|
+
}
|
|
13488
|
+
const slot = session.activeSlot ?? hitTestSectionDropSlot(session.lastClientY, buildSectionDropSlots(session.instanceId));
|
|
13489
|
+
const entries = slot ? planSectionMove(session.instanceId, slot.insertIndex, window.location.pathname) : null;
|
|
13490
|
+
if (!entries) {
|
|
13491
|
+
clearSectionDragVisuals();
|
|
13492
|
+
return;
|
|
13493
|
+
}
|
|
13494
|
+
const orderJson = JSON.stringify(entries);
|
|
13495
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
13496
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
13497
|
+
applyPersistedOrder(entries);
|
|
13498
|
+
clearSectionDragVisuals();
|
|
13499
|
+
requestAnimationFrame(() => {
|
|
13500
|
+
if (editContentRef.current[SECTION_ORDER_KEY] === orderJson) {
|
|
13501
|
+
applyPersistedOrder(entries);
|
|
13502
|
+
}
|
|
13503
|
+
requestAnimationFrame(() => {
|
|
13504
|
+
window.dispatchEvent(new Event("resize"));
|
|
13505
|
+
});
|
|
13506
|
+
});
|
|
13507
|
+
}, [clearSectionDragVisuals, editContentRef, postToParentRef]);
|
|
13508
|
+
const startSectionPressDrag = useCallback7(
|
|
13509
|
+
(el, clientX, clientY, pointerId) => {
|
|
13510
|
+
if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return false;
|
|
13511
|
+
const instanceId = instanceIdOf(el);
|
|
13512
|
+
if (!instanceId) return false;
|
|
13513
|
+
sectionPointerDragRef.current = {
|
|
13514
|
+
el,
|
|
13515
|
+
instanceId,
|
|
13516
|
+
startX: clientX,
|
|
13517
|
+
startY: clientY,
|
|
13518
|
+
pointerId,
|
|
13519
|
+
started: false
|
|
13520
|
+
};
|
|
13521
|
+
return true;
|
|
13522
|
+
},
|
|
13523
|
+
[footerDragRef, navDragRef]
|
|
13524
|
+
);
|
|
13525
|
+
useEffect11(() => {
|
|
13526
|
+
if (!isEditMode) return;
|
|
13527
|
+
const onPointerDown = (e) => {
|
|
13528
|
+
if (e.button !== 0) return;
|
|
13529
|
+
if (navDragRef.current || footerDragRef.current || sectionDragRef.current) return;
|
|
13530
|
+
if (sectionPointerDragRef.current) return;
|
|
13531
|
+
const target = e.target;
|
|
13532
|
+
if (!(target instanceof HTMLElement)) return;
|
|
13533
|
+
if (target.closest(SECTION_DRAG_EXCLUDED_SELECTOR)) return;
|
|
13534
|
+
const sectionEl = target.closest("[data-ohw-section]");
|
|
13535
|
+
if (!sectionEl || isChromeSection(sectionEl) || sectionEl.dataset.ohwSection === "footer") return;
|
|
13536
|
+
if (!topLevelSections().includes(sectionEl)) return;
|
|
13537
|
+
startSectionPressDrag(sectionEl, e.clientX, e.clientY, e.pointerId);
|
|
13538
|
+
};
|
|
13539
|
+
const onPointerMove = (e) => {
|
|
13540
|
+
const pending = sectionPointerDragRef.current;
|
|
13541
|
+
if (!pending) return;
|
|
13542
|
+
if (pending.started) {
|
|
13543
|
+
e.preventDefault();
|
|
13544
|
+
clearTextSelection();
|
|
13545
|
+
const session = sectionDragRef.current;
|
|
13546
|
+
if (!session) return;
|
|
13547
|
+
refreshSectionDragVisuals(session, e.clientX, e.clientY);
|
|
13548
|
+
return;
|
|
13549
|
+
}
|
|
13550
|
+
const dx = e.clientX - pending.startX;
|
|
13551
|
+
const dy = e.clientY - pending.startY;
|
|
13552
|
+
if (dx * dx + dy * dy < PRESS_THRESHOLD * PRESS_THRESHOLD) return;
|
|
13553
|
+
e.preventDefault();
|
|
13554
|
+
pending.started = true;
|
|
13555
|
+
armItemPressDrag();
|
|
13556
|
+
clearTextSelection();
|
|
13557
|
+
try {
|
|
13558
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
13559
|
+
} catch {
|
|
13560
|
+
}
|
|
13561
|
+
beginSectionDrag({
|
|
13562
|
+
instanceId: pending.instanceId,
|
|
13563
|
+
draggedEl: pending.el,
|
|
13564
|
+
lastClientX: e.clientX,
|
|
13565
|
+
lastClientY: e.clientY,
|
|
13566
|
+
activeSlot: null
|
|
13567
|
+
});
|
|
13568
|
+
};
|
|
13569
|
+
const endPointerDrag = (e) => {
|
|
13570
|
+
const pending = sectionPointerDragRef.current;
|
|
13571
|
+
sectionPointerDragRef.current = null;
|
|
13572
|
+
try {
|
|
13573
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
13574
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
13575
|
+
}
|
|
13576
|
+
} catch {
|
|
13577
|
+
}
|
|
13578
|
+
if (!pending) return;
|
|
13579
|
+
if (!pending.started) {
|
|
13580
|
+
unlockItemDragInteraction();
|
|
13581
|
+
return;
|
|
13582
|
+
}
|
|
13583
|
+
suppressNextClickRef.current = true;
|
|
13584
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
13585
|
+
commitSectionDrag();
|
|
13586
|
+
};
|
|
13587
|
+
const onKeyDown = (e) => {
|
|
13588
|
+
if (e.key !== "Escape") return;
|
|
13589
|
+
if (!sectionDragRef.current && !sectionPointerDragRef.current) return;
|
|
13590
|
+
sectionPointerDragRef.current = null;
|
|
13591
|
+
clearSectionDragVisuals();
|
|
13592
|
+
};
|
|
13593
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
13594
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
13595
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
13596
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
13597
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
13598
|
+
return () => {
|
|
13599
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
13600
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
13601
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
13602
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
13603
|
+
document.removeEventListener("keydown", onKeyDown, true);
|
|
13604
|
+
unlockItemDragInteraction();
|
|
13605
|
+
stopAutoScroll();
|
|
13606
|
+
};
|
|
13607
|
+
}, [
|
|
13608
|
+
beginSectionDrag,
|
|
13609
|
+
clearSectionDragVisuals,
|
|
13610
|
+
commitSectionDrag,
|
|
13611
|
+
footerDragRef,
|
|
13612
|
+
isEditMode,
|
|
13613
|
+
navDragRef,
|
|
13614
|
+
refreshSectionDragVisuals,
|
|
13615
|
+
startSectionPressDrag,
|
|
13616
|
+
stopAutoScroll,
|
|
13617
|
+
suppressClickUntilRef,
|
|
13618
|
+
suppressNextClickRef
|
|
13619
|
+
]);
|
|
13620
|
+
return {
|
|
13621
|
+
sectionDragRef,
|
|
13622
|
+
sectionDropSlots,
|
|
13623
|
+
activeSectionDropIndex,
|
|
13624
|
+
isSectionDragging
|
|
13625
|
+
};
|
|
13626
|
+
}
|
|
13627
|
+
|
|
13628
|
+
// src/ui/footer-container-chrome.tsx
|
|
13629
|
+
import { Plus as Plus2 } from "lucide-react";
|
|
13630
|
+
import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
13631
|
+
function FooterContainerChrome({
|
|
13632
|
+
rect,
|
|
13633
|
+
onAdd,
|
|
13634
|
+
addDisabled = false
|
|
13635
|
+
}) {
|
|
13636
|
+
const chromeGap = 6;
|
|
13637
|
+
const buttonMargin = 7;
|
|
13638
|
+
return /* @__PURE__ */ jsx29(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx29(
|
|
13639
|
+
"div",
|
|
13640
|
+
{
|
|
13641
|
+
"data-ohw-footer-container-chrome": "",
|
|
13642
|
+
"data-ohw-bridge": "",
|
|
13643
|
+
className: "pointer-events-none fixed z-[2147483647]",
|
|
13644
|
+
style: {
|
|
13645
|
+
top: rect.top - chromeGap,
|
|
13646
|
+
left: rect.left - chromeGap,
|
|
13647
|
+
width: rect.width + chromeGap * 2,
|
|
13648
|
+
height: rect.height + chromeGap * 2
|
|
13649
|
+
},
|
|
13650
|
+
children: /* @__PURE__ */ jsxs19(Tooltip, { children: [
|
|
13651
|
+
/* @__PURE__ */ jsx29(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx29(
|
|
13652
|
+
"button",
|
|
13653
|
+
{
|
|
13654
|
+
type: "button",
|
|
13655
|
+
"data-ohw-footer-add-button": "",
|
|
13656
|
+
disabled: addDisabled,
|
|
13657
|
+
className: "pointer-events-auto absolute left-1/2 flex size-7 -translate-x-1/2 -translate-y-full items-center justify-center rounded-[10px] border border-border bg-background p-0.5 shadow-sm transition-colors hover:bg-muted/80 disabled:pointer-events-none disabled:opacity-40",
|
|
13658
|
+
style: { top: chromeGap - buttonMargin },
|
|
13659
|
+
"aria-label": "Add item",
|
|
13660
|
+
onMouseDown: (e) => {
|
|
13661
|
+
e.preventDefault();
|
|
13662
|
+
e.stopPropagation();
|
|
13663
|
+
},
|
|
13664
|
+
onClick: (e) => {
|
|
13665
|
+
e.preventDefault();
|
|
13666
|
+
e.stopPropagation();
|
|
13667
|
+
if (addDisabled) return;
|
|
13668
|
+
onAdd();
|
|
13669
|
+
},
|
|
13670
|
+
children: /* @__PURE__ */ jsx29(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
13671
|
+
}
|
|
13672
|
+
) }),
|
|
13673
|
+
/* @__PURE__ */ jsx29(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
13674
|
+
] })
|
|
13675
|
+
}
|
|
13676
|
+
) });
|
|
13677
|
+
}
|
|
13678
|
+
|
|
13679
|
+
// src/lib/carousel.ts
|
|
13680
|
+
import { useEffect as useEffect12, useState as useState11 } from "react";
|
|
13681
|
+
var CAROUSEL_ATTR = "data-ohw-carousel";
|
|
13682
|
+
var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
|
|
13683
|
+
var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
|
|
13684
|
+
var CAROUSEL_EVENT = "ohw:carousel-change";
|
|
13685
|
+
function listCarouselKeys() {
|
|
13686
|
+
const keys = /* @__PURE__ */ new Set();
|
|
13687
|
+
document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
|
|
13688
|
+
const key = el.getAttribute("data-ohw-key");
|
|
13689
|
+
if (key) keys.add(key);
|
|
13690
|
+
});
|
|
13691
|
+
return [...keys];
|
|
13692
|
+
}
|
|
13693
|
+
function containersForKey(key) {
|
|
13694
|
+
return Array.from(
|
|
13695
|
+
document.querySelectorAll(`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`)
|
|
13696
|
+
);
|
|
13697
|
+
}
|
|
13698
|
+
function isCarouselKey(key) {
|
|
13699
|
+
return containersForKey(key).length > 0;
|
|
13700
|
+
}
|
|
13701
|
+
function parseSlides(raw) {
|
|
13702
|
+
if (!raw) return [];
|
|
13703
|
+
try {
|
|
13704
|
+
const parsed = JSON.parse(raw);
|
|
13705
|
+
if (!Array.isArray(parsed)) return [];
|
|
13706
|
+
return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
|
|
13707
|
+
} catch {
|
|
13708
|
+
return [];
|
|
13709
|
+
}
|
|
13710
|
+
}
|
|
13711
|
+
function readCarouselValue(key) {
|
|
13712
|
+
const container = containersForKey(key)[0];
|
|
13713
|
+
if (!container) return [];
|
|
13714
|
+
const fromAttr = parseSlides(container.getAttribute(CAROUSEL_VALUE_ATTR));
|
|
13715
|
+
if (fromAttr.length > 0) return fromAttr;
|
|
13716
|
+
return Array.from(container.querySelectorAll(`[${CAROUSEL_SLIDE_ATTR}]`)).filter((slide) => slide.closest(`[${CAROUSEL_ATTR}]`) === container).sort((a, b) => slideIndex(a) - slideIndex(b)).map((slide) => {
|
|
13717
|
+
const img = slide instanceof HTMLImageElement ? slide : slide.querySelector("img");
|
|
13718
|
+
return { src: img?.src ?? "", alt: img?.alt ?? "" };
|
|
13719
|
+
});
|
|
13720
|
+
}
|
|
13721
|
+
function slideIndex(el) {
|
|
13722
|
+
const raw = el.getAttribute(CAROUSEL_SLIDE_ATTR);
|
|
12773
13723
|
const n = raw ? parseInt(raw, 10) : NaN;
|
|
12774
13724
|
return Number.isFinite(n) ? n : 0;
|
|
12775
13725
|
}
|
|
@@ -12789,8 +13739,8 @@ function applyCarouselNode(key, val) {
|
|
|
12789
13739
|
return true;
|
|
12790
13740
|
}
|
|
12791
13741
|
function useOhwCarousel(key, initial) {
|
|
12792
|
-
const [images, setImages] =
|
|
12793
|
-
|
|
13742
|
+
const [images, setImages] = useState11(initial);
|
|
13743
|
+
useEffect12(() => {
|
|
12794
13744
|
const el = document.querySelector(
|
|
12795
13745
|
`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
|
|
12796
13746
|
);
|
|
@@ -12868,7 +13818,7 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
12868
13818
|
nodes.push({ key, type: "link", text: href });
|
|
12869
13819
|
}
|
|
12870
13820
|
if (extraContent) {
|
|
12871
|
-
for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
|
|
13821
|
+
for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY, SECTION_ORDER_KEY]) {
|
|
12872
13822
|
const text = extraContent[key];
|
|
12873
13823
|
if (typeof text === "string" && text.length > 0) {
|
|
12874
13824
|
nodes.push({ key, type: "meta", text });
|
|
@@ -12905,6 +13855,18 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
12905
13855
|
}
|
|
12906
13856
|
if (extraContent && !isScoped) {
|
|
12907
13857
|
applyNavFooterDeleteOverrides(byKey, extraContent);
|
|
13858
|
+
for (const key of LOGO_IMAGE_KEYS) {
|
|
13859
|
+
if (!(key in extraContent)) continue;
|
|
13860
|
+
byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
|
|
13861
|
+
}
|
|
13862
|
+
for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
|
|
13863
|
+
if (!(key in extraContent)) continue;
|
|
13864
|
+
byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
|
|
13865
|
+
}
|
|
13866
|
+
for (const key of LOGO_SIZE_KEYS) {
|
|
13867
|
+
if (!(key in extraContent)) continue;
|
|
13868
|
+
byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
|
|
13869
|
+
}
|
|
12908
13870
|
}
|
|
12909
13871
|
return Array.from(byKey.values());
|
|
12910
13872
|
}
|
|
@@ -13309,6 +14271,7 @@ function fadeInImageElement(img, onReady) {
|
|
|
13309
14271
|
function applyEditableImageSrc(img, url) {
|
|
13310
14272
|
img.removeAttribute("srcset");
|
|
13311
14273
|
img.removeAttribute("sizes");
|
|
14274
|
+
if (img.loading === "lazy") img.loading = "eager";
|
|
13312
14275
|
img.src = url;
|
|
13313
14276
|
}
|
|
13314
14277
|
function fadeInBgImage(el, url, onReady) {
|
|
@@ -13373,21 +14336,10 @@ function parseSchedulingInsertAfter(insertAfter) {
|
|
|
13373
14336
|
insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
|
|
13374
14337
|
};
|
|
13375
14338
|
}
|
|
13376
|
-
function
|
|
13377
|
-
|
|
13378
|
-
const
|
|
13379
|
-
|
|
13380
|
-
return { effectiveInsertAfter, insertBefore };
|
|
13381
|
-
}
|
|
13382
|
-
function getSchedulingMountPoint(insertAfter) {
|
|
13383
|
-
const { anchor } = parseSchedulingInsertAfter(insertAfter);
|
|
13384
|
-
let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
|
|
13385
|
-
if (!anchorEl && anchor === "scheduling") {
|
|
13386
|
-
const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
|
|
13387
|
-
anchorEl = widgets.at(-1) ?? null;
|
|
13388
|
-
}
|
|
13389
|
-
if (!anchorEl) return null;
|
|
13390
|
-
return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
14339
|
+
function resolveEntryAnchor(entry) {
|
|
14340
|
+
if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
|
|
14341
|
+
const parsed = parseSchedulingInsertAfter(entry.insertAfter);
|
|
14342
|
+
return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
|
|
13391
14343
|
}
|
|
13392
14344
|
function schedulingMountDepth(insertAfter) {
|
|
13393
14345
|
if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
|
|
@@ -13404,8 +14356,7 @@ function getPageSchedulingEntries(raw) {
|
|
|
13404
14356
|
}
|
|
13405
14357
|
}
|
|
13406
14358
|
function isSchedulingWidgetMissing(entry) {
|
|
13407
|
-
|
|
13408
|
-
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
|
|
14359
|
+
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
|
|
13409
14360
|
}
|
|
13410
14361
|
function hasMissingSchedulingWidgets(entries) {
|
|
13411
14362
|
return entries.some(isSchedulingWidgetMissing);
|
|
@@ -13435,16 +14386,17 @@ function initSectionsFromContent(content, removeExisting = false) {
|
|
|
13435
14386
|
} catch {
|
|
13436
14387
|
}
|
|
13437
14388
|
}
|
|
13438
|
-
function mountSchedulingWidget(
|
|
13439
|
-
const
|
|
13440
|
-
const sectionId = schedulingSectionId(
|
|
14389
|
+
function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
|
|
14390
|
+
const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
|
|
14391
|
+
const sectionId = schedulingSectionId(widgetId);
|
|
13441
14392
|
if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
|
|
13442
|
-
const
|
|
13443
|
-
if (!
|
|
14393
|
+
const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
|
|
14394
|
+
if (!anchorEl) return false;
|
|
14395
|
+
const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
13444
14396
|
const container = document.createElement("div");
|
|
13445
14397
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
13446
|
-
if (
|
|
13447
|
-
const beforeAnchor = document.querySelector(`[data-ohw-section="${
|
|
14398
|
+
if (beforeId) {
|
|
14399
|
+
const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
|
|
13448
14400
|
const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
|
|
13449
14401
|
if (!beforePoint) return false;
|
|
13450
14402
|
beforePoint.insertAdjacentElement("beforebegin", container);
|
|
@@ -13455,19 +14407,25 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
13455
14407
|
}
|
|
13456
14408
|
tail.insertAdjacentElement("afterend", container);
|
|
13457
14409
|
}
|
|
13458
|
-
|
|
13459
|
-
|
|
13460
|
-
|
|
13461
|
-
|
|
13462
|
-
|
|
13463
|
-
|
|
13464
|
-
|
|
13465
|
-
|
|
13466
|
-
|
|
13467
|
-
|
|
13468
|
-
|
|
13469
|
-
|
|
13470
|
-
|
|
14410
|
+
try {
|
|
14411
|
+
const root = createRoot2(container);
|
|
14412
|
+
flushSync2(() => {
|
|
14413
|
+
root.render(
|
|
14414
|
+
/* @__PURE__ */ jsx33(
|
|
14415
|
+
SchedulingWidget,
|
|
14416
|
+
{
|
|
14417
|
+
notifyOnConnect,
|
|
14418
|
+
initialScheduleId: scheduleId,
|
|
14419
|
+
insertAfter: widgetId
|
|
14420
|
+
}
|
|
14421
|
+
)
|
|
14422
|
+
);
|
|
14423
|
+
});
|
|
14424
|
+
} catch (err) {
|
|
14425
|
+
console.error("[ow:scheduling] render threw", err);
|
|
14426
|
+
container.remove();
|
|
14427
|
+
return false;
|
|
14428
|
+
}
|
|
13471
14429
|
const tracker = getSectionsTracker();
|
|
13472
14430
|
let sections = [];
|
|
13473
14431
|
try {
|
|
@@ -13475,10 +14433,12 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
13475
14433
|
} catch {
|
|
13476
14434
|
}
|
|
13477
14435
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
13478
|
-
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter ===
|
|
14436
|
+
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
|
|
13479
14437
|
sections.push({
|
|
13480
14438
|
type: "scheduling",
|
|
13481
|
-
insertAfter:
|
|
14439
|
+
insertAfter: widgetId,
|
|
14440
|
+
anchorId,
|
|
14441
|
+
beforeId: beforeId ?? null,
|
|
13482
14442
|
pagePath: window.location.pathname,
|
|
13483
14443
|
...scheduleId ? { scheduleId } : {}
|
|
13484
14444
|
});
|
|
@@ -13492,7 +14452,8 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
13492
14452
|
for (let i = pending.length - 1; i >= 0; i--) {
|
|
13493
14453
|
const entry = pending[i];
|
|
13494
14454
|
const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
|
|
13495
|
-
|
|
14455
|
+
const { anchorId, beforeId } = resolveEntryAnchor(entry);
|
|
14456
|
+
if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
|
|
13496
14457
|
pending.splice(i, 1);
|
|
13497
14458
|
}
|
|
13498
14459
|
}
|
|
@@ -13640,6 +14601,13 @@ function isInsideLinkEditor(target) {
|
|
|
13640
14601
|
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"]')
|
|
13641
14602
|
);
|
|
13642
14603
|
}
|
|
14604
|
+
function isInsideFloatingPanel(target) {
|
|
14605
|
+
return Boolean(target.closest("[data-ohw-floating-panel]"));
|
|
14606
|
+
}
|
|
14607
|
+
function isPointOverFloatingPanel(clientX, clientY) {
|
|
14608
|
+
const el = document.elementFromPoint(clientX, clientY);
|
|
14609
|
+
return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
|
|
14610
|
+
}
|
|
13643
14611
|
function getHrefKeyFromElement(el) {
|
|
13644
14612
|
if (!el) return null;
|
|
13645
14613
|
const anchor = el.closest("[data-ohw-href-key]");
|
|
@@ -13885,7 +14853,7 @@ function getNavigationSelectionParent(el) {
|
|
|
13885
14853
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
13886
14854
|
return getFooterLinksContainer();
|
|
13887
14855
|
}
|
|
13888
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
14856
|
+
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)) {
|
|
13889
14857
|
return getNavigationRoot(el);
|
|
13890
14858
|
}
|
|
13891
14859
|
return null;
|
|
@@ -14478,6 +15446,45 @@ function StateToggle({
|
|
|
14478
15446
|
);
|
|
14479
15447
|
}
|
|
14480
15448
|
var contentCache = /* @__PURE__ */ new Map();
|
|
15449
|
+
var fetchedContentPaths = /* @__PURE__ */ new Set();
|
|
15450
|
+
var OHW_LOADER_STYLE = {
|
|
15451
|
+
position: "fixed",
|
|
15452
|
+
inset: 0,
|
|
15453
|
+
background: "#fff",
|
|
15454
|
+
zIndex: 2147483646,
|
|
15455
|
+
display: "flex",
|
|
15456
|
+
alignItems: "center",
|
|
15457
|
+
justifyContent: "center"
|
|
15458
|
+
};
|
|
15459
|
+
function OhwLoaderSpinner() {
|
|
15460
|
+
return /* @__PURE__ */ jsxs20("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", "aria-hidden": true, children: [
|
|
15461
|
+
/* @__PURE__ */ jsx33("circle", { cx: "14", cy: "14", r: "11", stroke: "#E7E5E4", strokeWidth: "3" }),
|
|
15462
|
+
/* @__PURE__ */ jsx33(
|
|
15463
|
+
"circle",
|
|
15464
|
+
{
|
|
15465
|
+
cx: "14",
|
|
15466
|
+
cy: "14",
|
|
15467
|
+
r: "11",
|
|
15468
|
+
stroke: "#1C1917",
|
|
15469
|
+
strokeWidth: "3",
|
|
15470
|
+
strokeDasharray: "17 52",
|
|
15471
|
+
strokeLinecap: "round",
|
|
15472
|
+
children: /* @__PURE__ */ jsx33(
|
|
15473
|
+
"animateTransform",
|
|
15474
|
+
{
|
|
15475
|
+
attributeName: "transform",
|
|
15476
|
+
type: "rotate",
|
|
15477
|
+
from: "0 14 14",
|
|
15478
|
+
to: "360 14 14",
|
|
15479
|
+
dur: "0.7s",
|
|
15480
|
+
repeatCount: "indefinite"
|
|
15481
|
+
}
|
|
15482
|
+
)
|
|
15483
|
+
}
|
|
15484
|
+
)
|
|
15485
|
+
] });
|
|
15486
|
+
}
|
|
15487
|
+
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){}})();`;
|
|
14481
15488
|
function resolveSubdomain(subdomainFromQuery) {
|
|
14482
15489
|
if (subdomainFromQuery) return subdomainFromQuery;
|
|
14483
15490
|
if (typeof window !== "undefined") {
|
|
@@ -14500,8 +15507,8 @@ function OhhwellsBridge() {
|
|
|
14500
15507
|
const router = useRouter3();
|
|
14501
15508
|
const searchParams = useSearchParams();
|
|
14502
15509
|
const isEditMode = isEditSessionActive();
|
|
14503
|
-
const [bridgeRoot, setBridgeRoot] =
|
|
14504
|
-
|
|
15510
|
+
const [bridgeRoot, setBridgeRoot] = useState12(null);
|
|
15511
|
+
useEffect13(() => {
|
|
14505
15512
|
const figtreeFontId = "ohw-figtree-font";
|
|
14506
15513
|
if (!document.getElementById(figtreeFontId)) {
|
|
14507
15514
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -14530,86 +15537,150 @@ function OhhwellsBridge() {
|
|
|
14530
15537
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
14531
15538
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
14532
15539
|
useSavedLinkNavigation(isEditMode);
|
|
14533
|
-
const postToParent2 =
|
|
15540
|
+
const postToParent2 = useCallback8((data) => {
|
|
14534
15541
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
14535
15542
|
window.parent.postMessage(data, "*");
|
|
14536
15543
|
}
|
|
14537
15544
|
}, []);
|
|
14538
|
-
const [fetchState, setFetchState] =
|
|
14539
|
-
const autoSaveTimers =
|
|
14540
|
-
const activeElRef =
|
|
14541
|
-
const pointerHeldRef =
|
|
14542
|
-
const selectedElRef =
|
|
14543
|
-
const selectedHrefKeyRef =
|
|
14544
|
-
const selectedFooterColAttrRef =
|
|
14545
|
-
const originalContentRef =
|
|
14546
|
-
const activeStateElRef =
|
|
14547
|
-
const parentScrollRef =
|
|
14548
|
-
const visibleViewportRef =
|
|
14549
|
-
const [dialogPortalContainer, setDialogPortalContainer] =
|
|
14550
|
-
const attachVisibleViewport =
|
|
15545
|
+
const [fetchState, setFetchState] = useState12("idle");
|
|
15546
|
+
const autoSaveTimers = useRef10(/* @__PURE__ */ new Map());
|
|
15547
|
+
const activeElRef = useRef10(null);
|
|
15548
|
+
const pointerHeldRef = useRef10(false);
|
|
15549
|
+
const selectedElRef = useRef10(null);
|
|
15550
|
+
const selectedHrefKeyRef = useRef10(null);
|
|
15551
|
+
const selectedFooterColAttrRef = useRef10(null);
|
|
15552
|
+
const originalContentRef = useRef10(null);
|
|
15553
|
+
const activeStateElRef = useRef10(null);
|
|
15554
|
+
const parentScrollRef = useRef10(null);
|
|
15555
|
+
const visibleViewportRef = useRef10(null);
|
|
15556
|
+
const [dialogPortalContainer, setDialogPortalContainer] = useState12(null);
|
|
15557
|
+
const attachVisibleViewport = useCallback8((node) => {
|
|
14551
15558
|
visibleViewportRef.current = node;
|
|
14552
15559
|
setDialogPortalContainer(node);
|
|
14553
15560
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
14554
15561
|
}, []);
|
|
14555
|
-
const toolbarElRef =
|
|
14556
|
-
const glowElRef =
|
|
14557
|
-
const hoveredImageRef =
|
|
14558
|
-
const hoveredImageHasTextOverlapRef =
|
|
14559
|
-
const dragOverElRef =
|
|
14560
|
-
const [mediaHover, setMediaHover] =
|
|
14561
|
-
const [
|
|
14562
|
-
const
|
|
14563
|
-
const
|
|
14564
|
-
|
|
14565
|
-
|
|
14566
|
-
|
|
14567
|
-
|
|
14568
|
-
|
|
14569
|
-
|
|
14570
|
-
|
|
14571
|
-
|
|
14572
|
-
|
|
14573
|
-
|
|
14574
|
-
|
|
14575
|
-
|
|
14576
|
-
});
|
|
14577
|
-
const
|
|
14578
|
-
|
|
14579
|
-
const
|
|
14580
|
-
|
|
14581
|
-
|
|
14582
|
-
|
|
14583
|
-
|
|
14584
|
-
|
|
14585
|
-
|
|
14586
|
-
|
|
14587
|
-
|
|
14588
|
-
|
|
14589
|
-
|
|
14590
|
-
|
|
14591
|
-
|
|
14592
|
-
|
|
14593
|
-
|
|
14594
|
-
|
|
14595
|
-
|
|
14596
|
-
|
|
14597
|
-
|
|
14598
|
-
|
|
14599
|
-
|
|
14600
|
-
|
|
14601
|
-
|
|
14602
|
-
|
|
14603
|
-
const
|
|
14604
|
-
|
|
14605
|
-
|
|
14606
|
-
|
|
14607
|
-
|
|
14608
|
-
|
|
14609
|
-
|
|
14610
|
-
|
|
14611
|
-
|
|
14612
|
-
|
|
15562
|
+
const toolbarElRef = useRef10(null);
|
|
15563
|
+
const glowElRef = useRef10(null);
|
|
15564
|
+
const hoveredImageRef = useRef10(null);
|
|
15565
|
+
const hoveredImageHasTextOverlapRef = useRef10(false);
|
|
15566
|
+
const dragOverElRef = useRef10(null);
|
|
15567
|
+
const [mediaHover, setMediaHover] = useState12(null);
|
|
15568
|
+
const [selectedMedia, setSelectedMedia] = useState12(null);
|
|
15569
|
+
const selectedMediaElRef = useRef10(null);
|
|
15570
|
+
const clearMediaSelection = useCallback8(() => {
|
|
15571
|
+
const prev = selectedMediaElRef.current;
|
|
15572
|
+
selectedMediaElRef.current = null;
|
|
15573
|
+
setSelectedMedia(null);
|
|
15574
|
+
const sectionEl = prev?.closest("[data-ohw-section]") ?? null;
|
|
15575
|
+
if (sectionEl) {
|
|
15576
|
+
postToParentRef.current({
|
|
15577
|
+
type: "ow:section-selected",
|
|
15578
|
+
sectionId: sectionEl.dataset.ohwSection ?? null,
|
|
15579
|
+
sectionLabel: sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? ""),
|
|
15580
|
+
key: null
|
|
15581
|
+
});
|
|
15582
|
+
}
|
|
15583
|
+
}, []);
|
|
15584
|
+
const clearMediaSelectionRef = useRef10(clearMediaSelection);
|
|
15585
|
+
clearMediaSelectionRef.current = clearMediaSelection;
|
|
15586
|
+
const selectMediaElement = useCallback8((el) => {
|
|
15587
|
+
const r2 = el.getBoundingClientRect();
|
|
15588
|
+
const video = el.dataset.ohwEditable === "video" ? el.querySelector("video") : null;
|
|
15589
|
+
selectedMediaElRef.current = el;
|
|
15590
|
+
setSelectedMedia({
|
|
15591
|
+
key: el.dataset.ohwKey ?? "",
|
|
15592
|
+
rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
|
|
15593
|
+
elementType: el.dataset.ohwEditable ?? "image",
|
|
15594
|
+
hasTextOverlap: false,
|
|
15595
|
+
isDragOver: false,
|
|
15596
|
+
...video ? { videoAutoplay: video.autoplay, videoMuted: video.muted } : {}
|
|
15597
|
+
});
|
|
15598
|
+
const sectionEl = el.closest("[data-ohw-section]");
|
|
15599
|
+
aiSectionApiRef.current?.selectFromElement(el, { report: false });
|
|
15600
|
+
postToParentRef.current({
|
|
15601
|
+
type: "ow:section-selected",
|
|
15602
|
+
sectionId: sectionEl?.dataset.ohwSection ?? null,
|
|
15603
|
+
sectionLabel: sectionEl ? sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? "") : null,
|
|
15604
|
+
key: el.dataset.ohwKey ?? null,
|
|
15605
|
+
// Display name for the pill — the raw key prettifies into fragments ("Img"); the
|
|
15606
|
+
// bridge knows what the node IS, so it names it.
|
|
15607
|
+
keyLabel: el.dataset.ohwEditable === "video" ? "Video" : el.dataset.ohwEditable === "bg-image" ? "Background" : "Image"
|
|
15608
|
+
});
|
|
15609
|
+
}, []);
|
|
15610
|
+
const selectMediaElementRef = useRef10(selectMediaElement);
|
|
15611
|
+
selectMediaElementRef.current = selectMediaElement;
|
|
15612
|
+
useEffect13(() => {
|
|
15613
|
+
if (!selectedMedia) return;
|
|
15614
|
+
const update = () => {
|
|
15615
|
+
const el = selectedMediaElRef.current;
|
|
15616
|
+
if (!el || !el.isConnected) {
|
|
15617
|
+
clearMediaSelection();
|
|
15618
|
+
return;
|
|
15619
|
+
}
|
|
15620
|
+
const r2 = el.getBoundingClientRect();
|
|
15621
|
+
setSelectedMedia(
|
|
15622
|
+
(prev) => prev ? { ...prev, rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } } : prev
|
|
15623
|
+
);
|
|
15624
|
+
};
|
|
15625
|
+
window.addEventListener("scroll", update, true);
|
|
15626
|
+
window.addEventListener("resize", update);
|
|
15627
|
+
return () => {
|
|
15628
|
+
window.removeEventListener("scroll", update, true);
|
|
15629
|
+
window.removeEventListener("resize", update);
|
|
15630
|
+
};
|
|
15631
|
+
}, [selectedMedia !== null]);
|
|
15632
|
+
const [carouselHover, setCarouselHover] = useState12(null);
|
|
15633
|
+
const [uploadingRects, setUploadingRects] = useState12({});
|
|
15634
|
+
const hoveredGapRef = useRef10(null);
|
|
15635
|
+
const imageUnhoverTimerRef = useRef10(null);
|
|
15636
|
+
const imageShowTimerRef = useRef10(null);
|
|
15637
|
+
const editStylesRef = useRef10(null);
|
|
15638
|
+
const activateRef = useRef10(() => {
|
|
15639
|
+
});
|
|
15640
|
+
const deactivateRef = useRef10(() => {
|
|
15641
|
+
});
|
|
15642
|
+
const selectRef = useRef10(() => {
|
|
15643
|
+
});
|
|
15644
|
+
const selectFrameRef = useRef10(() => {
|
|
15645
|
+
});
|
|
15646
|
+
const selectLogoRef = useRef10(() => {
|
|
15647
|
+
});
|
|
15648
|
+
const openLogoSizePanelRef = useRef10(() => {
|
|
15649
|
+
});
|
|
15650
|
+
const deselectRef = useRef10(() => {
|
|
15651
|
+
});
|
|
15652
|
+
const closeFloatingPanelOnlyRef = useRef10(() => {
|
|
15653
|
+
});
|
|
15654
|
+
const reselectNavigationItemRef = useRef10(() => {
|
|
15655
|
+
});
|
|
15656
|
+
const commitNavigationTextEditRef = useRef10(() => {
|
|
15657
|
+
});
|
|
15658
|
+
const handleDeleteSelectedRef = useRef10(() => false);
|
|
15659
|
+
const runPendingDeleteUndoRef = useRef10(() => false);
|
|
15660
|
+
const isFooterFrameSelectionRef = useRef10(false);
|
|
15661
|
+
const refreshActiveCommandsRef = useRef10(() => {
|
|
15662
|
+
});
|
|
15663
|
+
const postToParentRef = useRef10(postToParent2);
|
|
15664
|
+
postToParentRef.current = postToParent2;
|
|
15665
|
+
const aiSectionApiRef = useRef10(null);
|
|
15666
|
+
const sectionsLoadedRef = useRef10(false);
|
|
15667
|
+
const pendingScheduleConfigRequests = useRef10([]);
|
|
15668
|
+
const [toolbarRect, setToolbarRect] = useState12(null);
|
|
15669
|
+
const [formPickRect, setFormPickRect] = useState12(null);
|
|
15670
|
+
const formPickElRef = useRef10(null);
|
|
15671
|
+
const [formViewState, setFormViewStateUi] = useState12("default");
|
|
15672
|
+
const [formPickCount, setFormPickCount] = useState12(null);
|
|
15673
|
+
const [formHoverRect, setFormHoverRect] = useState12(null);
|
|
15674
|
+
const formHoverElRef = useRef10(null);
|
|
15675
|
+
const [fieldPickRect, setFieldPickRect] = useState12(null);
|
|
15676
|
+
const fieldPickElRef = useRef10(null);
|
|
15677
|
+
const [fieldPickState, setFieldPickState] = useState12(null);
|
|
15678
|
+
const [fieldTypePickerOpen, setFieldTypePickerOpen] = useState12(false);
|
|
15679
|
+
const clearFormPick = useCallback8(() => {
|
|
15680
|
+
const form = formPickElRef.current;
|
|
15681
|
+
const editing = fieldPickElRef.current;
|
|
15682
|
+
if (commitPlaceholderEdit(editing) && editing) {
|
|
15683
|
+
const owner = editing.closest('[data-ohw-editable="form"]');
|
|
14613
15684
|
if (owner) persistFieldsRef.current(owner);
|
|
14614
15685
|
}
|
|
14615
15686
|
if (form) {
|
|
@@ -14625,7 +15696,7 @@ function OhhwellsBridge() {
|
|
|
14625
15696
|
formPickElRef.current = null;
|
|
14626
15697
|
setFormPickRect(null);
|
|
14627
15698
|
}, []);
|
|
14628
|
-
const clearFieldPick =
|
|
15699
|
+
const clearFieldPick = useCallback8(() => {
|
|
14629
15700
|
const wrapper = fieldPickElRef.current;
|
|
14630
15701
|
if (commitPlaceholderEdit(wrapper) && wrapper) {
|
|
14631
15702
|
const form = wrapper.closest('[data-ohw-editable="form"]');
|
|
@@ -14635,9 +15706,9 @@ function OhhwellsBridge() {
|
|
|
14635
15706
|
setFieldPickRect(null);
|
|
14636
15707
|
setFieldPickState(null);
|
|
14637
15708
|
}, []);
|
|
14638
|
-
const persistFieldsRef =
|
|
15709
|
+
const persistFieldsRef = useRef10(() => {
|
|
14639
15710
|
});
|
|
14640
|
-
const persistFields =
|
|
15711
|
+
const persistFields = useCallback8(
|
|
14641
15712
|
(form) => {
|
|
14642
15713
|
const key = formKeyOf(form);
|
|
14643
15714
|
if (!key) return;
|
|
@@ -14648,7 +15719,7 @@ function OhhwellsBridge() {
|
|
|
14648
15719
|
[]
|
|
14649
15720
|
);
|
|
14650
15721
|
persistFieldsRef.current = persistFields;
|
|
14651
|
-
const selectField =
|
|
15722
|
+
const selectField = useCallback8((wrapper) => {
|
|
14652
15723
|
if (fieldPickElRef.current && fieldPickElRef.current !== wrapper) {
|
|
14653
15724
|
commitPlaceholderEdit(fieldPickElRef.current);
|
|
14654
15725
|
}
|
|
@@ -14661,7 +15732,7 @@ function OhhwellsBridge() {
|
|
|
14661
15732
|
setFieldPickState({ type: fieldTypeOf(wrapper), required: isFieldRequired(wrapper) });
|
|
14662
15733
|
setFieldTypePickerOpen(false);
|
|
14663
15734
|
}, []);
|
|
14664
|
-
const withSelectedField =
|
|
15735
|
+
const withSelectedField = useCallback8(
|
|
14665
15736
|
(run) => {
|
|
14666
15737
|
const wrapper = fieldPickElRef.current;
|
|
14667
15738
|
const form = formPickElRef.current;
|
|
@@ -14674,28 +15745,28 @@ function OhhwellsBridge() {
|
|
|
14674
15745
|
},
|
|
14675
15746
|
[persistFields]
|
|
14676
15747
|
);
|
|
14677
|
-
const handleFieldTypeChange =
|
|
15748
|
+
const handleFieldTypeChange = useCallback8(
|
|
14678
15749
|
(type) => withSelectedField((_form, wrapper) => {
|
|
14679
15750
|
applyFieldType(wrapper, type);
|
|
14680
15751
|
selectField(wrapper);
|
|
14681
15752
|
}),
|
|
14682
15753
|
[selectField, withSelectedField]
|
|
14683
15754
|
);
|
|
14684
|
-
const handleFieldRequiredToggle =
|
|
15755
|
+
const handleFieldRequiredToggle = useCallback8(
|
|
14685
15756
|
() => withSelectedField((_form, wrapper) => {
|
|
14686
15757
|
setFieldRequired(wrapper, !isFieldRequired(wrapper));
|
|
14687
15758
|
selectField(wrapper);
|
|
14688
15759
|
}),
|
|
14689
15760
|
[selectField, withSelectedField]
|
|
14690
15761
|
);
|
|
14691
|
-
const handleFieldDuplicate =
|
|
15762
|
+
const handleFieldDuplicate = useCallback8(
|
|
14692
15763
|
() => withSelectedField((form, wrapper) => {
|
|
14693
15764
|
const copy = duplicateField(form, wrapper);
|
|
14694
15765
|
selectField(copy);
|
|
14695
15766
|
}),
|
|
14696
15767
|
[selectField, withSelectedField]
|
|
14697
15768
|
);
|
|
14698
|
-
const handleFieldDelete =
|
|
15769
|
+
const handleFieldDelete = useCallback8(
|
|
14699
15770
|
() => withSelectedField((_form, wrapper) => {
|
|
14700
15771
|
removeField(wrapper);
|
|
14701
15772
|
clearFieldPick();
|
|
@@ -14703,7 +15774,7 @@ function OhhwellsBridge() {
|
|
|
14703
15774
|
}),
|
|
14704
15775
|
[clearFieldPick, withSelectedField]
|
|
14705
15776
|
);
|
|
14706
|
-
const handleAddField =
|
|
15777
|
+
const handleAddField = useCallback8(
|
|
14707
15778
|
(type) => {
|
|
14708
15779
|
const form = formPickElRef.current;
|
|
14709
15780
|
if (!form) return;
|
|
@@ -14719,8 +15790,8 @@ function OhhwellsBridge() {
|
|
|
14719
15790
|
},
|
|
14720
15791
|
[persistFields, selectField]
|
|
14721
15792
|
);
|
|
14722
|
-
const fieldDragRef =
|
|
14723
|
-
const buildFieldDropSlots =
|
|
15793
|
+
const fieldDragRef = useRef10(null);
|
|
15794
|
+
const buildFieldDropSlots = useCallback8((form, draggedKey) => {
|
|
14724
15795
|
const others = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== draggedKey);
|
|
14725
15796
|
const slots = others.map((el) => {
|
|
14726
15797
|
const rect = el.getBoundingClientRect();
|
|
@@ -14733,7 +15804,7 @@ function OhhwellsBridge() {
|
|
|
14733
15804
|
}
|
|
14734
15805
|
return slots;
|
|
14735
15806
|
}, []);
|
|
14736
|
-
const handleFieldDragStart =
|
|
15807
|
+
const handleFieldDragStart = useCallback8(() => {
|
|
14737
15808
|
const wrapper = fieldPickElRef.current;
|
|
14738
15809
|
const form = formPickElRef.current;
|
|
14739
15810
|
if (!wrapper || !form) return;
|
|
@@ -14742,18 +15813,18 @@ function OhhwellsBridge() {
|
|
|
14742
15813
|
setFieldDragging(true);
|
|
14743
15814
|
setFieldDropSlots(buildFieldDropSlots(form, key));
|
|
14744
15815
|
}, [buildFieldDropSlots]);
|
|
14745
|
-
const handleFieldDragEnd =
|
|
15816
|
+
const handleFieldDragEnd = useCallback8(() => {
|
|
14746
15817
|
fieldDragRef.current = null;
|
|
14747
15818
|
setFieldDropIndex(null);
|
|
14748
15819
|
setFieldDropSlots([]);
|
|
14749
15820
|
setFieldDragging(false);
|
|
14750
15821
|
}, []);
|
|
14751
|
-
const [fieldDropIndex, setFieldDropIndex] =
|
|
14752
|
-
const [fieldDropSlots, setFieldDropSlots] =
|
|
14753
|
-
const [fieldDragging, setFieldDragging] =
|
|
14754
|
-
const clearFormPickRef =
|
|
15822
|
+
const [fieldDropIndex, setFieldDropIndex] = useState12(null);
|
|
15823
|
+
const [fieldDropSlots, setFieldDropSlots] = useState12([]);
|
|
15824
|
+
const [fieldDragging, setFieldDragging] = useState12(false);
|
|
15825
|
+
const clearFormPickRef = useRef10(clearFormPick);
|
|
14755
15826
|
clearFormPickRef.current = clearFormPick;
|
|
14756
|
-
|
|
15827
|
+
useEffect13(() => {
|
|
14757
15828
|
const el = fieldPickElRef.current;
|
|
14758
15829
|
if (!el || fieldPickRect === null) return;
|
|
14759
15830
|
const observer = new ResizeObserver(() => {
|
|
@@ -14762,7 +15833,7 @@ function OhhwellsBridge() {
|
|
|
14762
15833
|
observer.observe(el);
|
|
14763
15834
|
return () => observer.disconnect();
|
|
14764
15835
|
}, [fieldPickRect !== null, fieldPickState]);
|
|
14765
|
-
|
|
15836
|
+
useEffect13(() => {
|
|
14766
15837
|
const el = formPickElRef.current;
|
|
14767
15838
|
if (!el || formPickRect === null) return;
|
|
14768
15839
|
const observer = new ResizeObserver(() => {
|
|
@@ -14771,25 +15842,25 @@ function OhhwellsBridge() {
|
|
|
14771
15842
|
observer.observe(el);
|
|
14772
15843
|
return () => observer.disconnect();
|
|
14773
15844
|
}, [formPickRect !== null, formViewState]);
|
|
14774
|
-
const [toolbarVariant, setToolbarVariant] =
|
|
14775
|
-
const toolbarVariantRef =
|
|
15845
|
+
const [toolbarVariant, setToolbarVariant] = useState12("none");
|
|
15846
|
+
const toolbarVariantRef = useRef10("none");
|
|
14776
15847
|
toolbarVariantRef.current = toolbarVariant;
|
|
14777
|
-
const [selectedIsCta, setSelectedIsCta] =
|
|
14778
|
-
const [selectedIsSocial, setSelectedIsSocial] =
|
|
14779
|
-
const [selectedIsSocialsRow, setSelectedIsSocialsRow] =
|
|
14780
|
-
const [reorderHrefKey, setReorderHrefKey] =
|
|
14781
|
-
const [reorderDragDisabled, setReorderDragDisabled] =
|
|
14782
|
-
const [toggleState, setToggleState] =
|
|
14783
|
-
const [maxBadge, setMaxBadge] =
|
|
14784
|
-
const [activeCommands, setActiveCommands] =
|
|
14785
|
-
const [sectionGap, setSectionGap] =
|
|
14786
|
-
const [toolbarShowEditLink, setToolbarShowEditLink] =
|
|
14787
|
-
const hoveredNavContainerRef =
|
|
14788
|
-
const [hoveredNavContainerRect, setHoveredNavContainerRect] =
|
|
14789
|
-
const hoveredItemElRef =
|
|
14790
|
-
const [hoveredItemRect, setHoveredItemRect] =
|
|
14791
|
-
const [hoveredTextRect, setHoveredTextRect] =
|
|
14792
|
-
|
|
15848
|
+
const [selectedIsCta, setSelectedIsCta] = useState12(false);
|
|
15849
|
+
const [selectedIsSocial, setSelectedIsSocial] = useState12(false);
|
|
15850
|
+
const [selectedIsSocialsRow, setSelectedIsSocialsRow] = useState12(false);
|
|
15851
|
+
const [reorderHrefKey, setReorderHrefKey] = useState12(null);
|
|
15852
|
+
const [reorderDragDisabled, setReorderDragDisabled] = useState12(false);
|
|
15853
|
+
const [toggleState, setToggleState] = useState12(null);
|
|
15854
|
+
const [maxBadge, setMaxBadge] = useState12(null);
|
|
15855
|
+
const [activeCommands, setActiveCommands] = useState12(/* @__PURE__ */ new Set());
|
|
15856
|
+
const [sectionGap, setSectionGap] = useState12(null);
|
|
15857
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = useState12(false);
|
|
15858
|
+
const hoveredNavContainerRef = useRef10(null);
|
|
15859
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState12(null);
|
|
15860
|
+
const hoveredItemElRef = useRef10(null);
|
|
15861
|
+
const [hoveredItemRect, setHoveredItemRect] = useState12(null);
|
|
15862
|
+
const [hoveredTextRect, setHoveredTextRect] = useState12(null);
|
|
15863
|
+
useEffect13(() => {
|
|
14793
15864
|
const sync = () => {
|
|
14794
15865
|
const el = document.querySelector(
|
|
14795
15866
|
'[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]):not([data-ohw-editable="form"] *)'
|
|
@@ -14810,43 +15881,56 @@ function OhhwellsBridge() {
|
|
|
14810
15881
|
});
|
|
14811
15882
|
return () => observer.disconnect();
|
|
14812
15883
|
}, []);
|
|
14813
|
-
const siblingHintElRef =
|
|
14814
|
-
const [siblingHintRect, setSiblingHintRect] =
|
|
14815
|
-
const [siblingHintRects, setSiblingHintRects] =
|
|
14816
|
-
const [isItemDragging, setIsItemDragging] =
|
|
14817
|
-
const [isFooterFrameSelection, setIsFooterFrameSelection] =
|
|
15884
|
+
const siblingHintElRef = useRef10(null);
|
|
15885
|
+
const [siblingHintRect, setSiblingHintRect] = useState12(null);
|
|
15886
|
+
const [siblingHintRects, setSiblingHintRects] = useState12([]);
|
|
15887
|
+
const [isItemDragging, setIsItemDragging] = useState12(false);
|
|
15888
|
+
const [isFooterFrameSelection, setIsFooterFrameSelection] = useState12(false);
|
|
14818
15889
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
14819
|
-
const [
|
|
14820
|
-
const
|
|
14821
|
-
|
|
14822
|
-
const [
|
|
14823
|
-
const [
|
|
14824
|
-
const [
|
|
14825
|
-
const
|
|
14826
|
-
const
|
|
14827
|
-
const
|
|
14828
|
-
const
|
|
14829
|
-
const
|
|
14830
|
-
const
|
|
14831
|
-
const
|
|
14832
|
-
const
|
|
14833
|
-
const
|
|
14834
|
-
const
|
|
14835
|
-
const
|
|
14836
|
-
const
|
|
14837
|
-
const
|
|
14838
|
-
const
|
|
14839
|
-
const
|
|
14840
|
-
const
|
|
14841
|
-
const [
|
|
14842
|
-
const [
|
|
14843
|
-
const
|
|
14844
|
-
const
|
|
14845
|
-
const
|
|
14846
|
-
const
|
|
14847
|
-
const
|
|
15890
|
+
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState12(null);
|
|
15891
|
+
const [footerHeadingVisible, setFooterHeadingVisible] = useState12(null);
|
|
15892
|
+
const footerDragRef = useRef10(null);
|
|
15893
|
+
const [footerDropSlots, setFooterDropSlots] = useState12([]);
|
|
15894
|
+
const [activeFooterDropIndex, setActiveFooterDropIndex] = useState12(null);
|
|
15895
|
+
const [draggedItemRect, setDraggedItemRect] = useState12(null);
|
|
15896
|
+
const footerPointerDragRef = useRef10(null);
|
|
15897
|
+
const suppressNextClickRef = useRef10(false);
|
|
15898
|
+
const suppressClickUntilRef = useRef10(0);
|
|
15899
|
+
const [linkPopover, setLinkPopover] = useState12(null);
|
|
15900
|
+
const linkPopoverSessionRef = useRef10(null);
|
|
15901
|
+
const addNavAfterAnchorRef = useRef10(null);
|
|
15902
|
+
const editContentRef = useRef10({});
|
|
15903
|
+
const aiSectionsRef = useRef10("");
|
|
15904
|
+
const brandKitRef = useRef10("");
|
|
15905
|
+
const stylesRef = useRef10("");
|
|
15906
|
+
const pendingDeleteUndoRef = useRef10(null);
|
|
15907
|
+
const [floatingPanel, setFloatingPanel] = useState12(null);
|
|
15908
|
+
const floatingPanelOpenRef = useRef10(false);
|
|
15909
|
+
const setFloatingPanelRef = useRef10(setFloatingPanel);
|
|
15910
|
+
const [floatingPanelPos, setFloatingPanelPos] = useState12(null);
|
|
15911
|
+
const [logoSizeDraft, setLogoSizeDraft] = useState12(null);
|
|
15912
|
+
const [editorViewport, setEditorViewport] = useState12("desktop");
|
|
15913
|
+
const [parentScrollSnap, setParentScrollSnap] = useState12(null);
|
|
15914
|
+
const [sitePages, setSitePages] = useState12([]);
|
|
15915
|
+
const [sectionsByPath, setSectionsByPath] = useState12({});
|
|
15916
|
+
const sectionsPrefetchGenRef = useRef10(0);
|
|
15917
|
+
const setLinkPopoverRef = useRef10(setLinkPopover);
|
|
15918
|
+
const linkPopoverPanelRef = useRef10(null);
|
|
15919
|
+
const linkPopoverOpenRef = useRef10(false);
|
|
15920
|
+
const linkPopoverGraceUntilRef = useRef10(0);
|
|
14848
15921
|
setLinkPopoverRef.current = setLinkPopover;
|
|
15922
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
14849
15923
|
linkPopoverSessionRef.current = linkPopover;
|
|
15924
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
15925
|
+
useEffect13(() => {
|
|
15926
|
+
const syncViewport = () => {
|
|
15927
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
15928
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
15929
|
+
};
|
|
15930
|
+
syncViewport();
|
|
15931
|
+
window.addEventListener("resize", syncViewport);
|
|
15932
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
15933
|
+
}, []);
|
|
14850
15934
|
const {
|
|
14851
15935
|
navDragRef,
|
|
14852
15936
|
navDropSlots,
|
|
@@ -14879,10 +15963,20 @@ function OhhwellsBridge() {
|
|
|
14879
15963
|
getNavigationItemAnchor,
|
|
14880
15964
|
isDragHandleDisabled
|
|
14881
15965
|
});
|
|
15966
|
+
const { sectionDropSlots, activeSectionDropIndex, isSectionDragging } = useSectionDrag({
|
|
15967
|
+
isEditMode,
|
|
15968
|
+
editContentRef,
|
|
15969
|
+
postToParentRef,
|
|
15970
|
+
parentScrollRef,
|
|
15971
|
+
navDragRef,
|
|
15972
|
+
footerDragRef,
|
|
15973
|
+
suppressNextClickRef,
|
|
15974
|
+
suppressClickUntilRef
|
|
15975
|
+
});
|
|
14882
15976
|
const bumpLinkPopoverGrace = () => {
|
|
14883
15977
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
14884
15978
|
};
|
|
14885
|
-
const runSectionsPrefetch =
|
|
15979
|
+
const runSectionsPrefetch = useCallback8((pages) => {
|
|
14886
15980
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
14887
15981
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
14888
15982
|
const paths = pages.map((p) => p.path);
|
|
@@ -14901,9 +15995,9 @@ function OhhwellsBridge() {
|
|
|
14901
15995
|
);
|
|
14902
15996
|
});
|
|
14903
15997
|
}, [isEditMode, pathname]);
|
|
14904
|
-
const runSectionsPrefetchRef =
|
|
15998
|
+
const runSectionsPrefetchRef = useRef10(runSectionsPrefetch);
|
|
14905
15999
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
14906
|
-
|
|
16000
|
+
useEffect13(() => {
|
|
14907
16001
|
if (!linkPopover) {
|
|
14908
16002
|
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
14909
16003
|
return;
|
|
@@ -14931,7 +16025,7 @@ function OhhwellsBridge() {
|
|
|
14931
16025
|
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
14932
16026
|
};
|
|
14933
16027
|
}, [linkPopover, postToParent2]);
|
|
14934
|
-
|
|
16028
|
+
useEffect13(() => {
|
|
14935
16029
|
if (!isEditMode) return;
|
|
14936
16030
|
const useFixtures = shouldUseDevFixtures();
|
|
14937
16031
|
if (useFixtures) {
|
|
@@ -14955,14 +16049,14 @@ function OhhwellsBridge() {
|
|
|
14955
16049
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
14956
16050
|
return () => window.removeEventListener("message", onSitePages);
|
|
14957
16051
|
}, [isEditMode, postToParent2]);
|
|
14958
|
-
|
|
16052
|
+
useEffect13(() => {
|
|
14959
16053
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
14960
16054
|
void loadAllSectionsManifest().then((manifest) => {
|
|
14961
16055
|
if (Object.keys(manifest).length === 0) return;
|
|
14962
16056
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
14963
16057
|
});
|
|
14964
16058
|
}, [isEditMode]);
|
|
14965
|
-
|
|
16059
|
+
useEffect13(() => {
|
|
14966
16060
|
const update = () => {
|
|
14967
16061
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
14968
16062
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -14986,10 +16080,10 @@ function OhhwellsBridge() {
|
|
|
14986
16080
|
vvp.removeEventListener("resize", update);
|
|
14987
16081
|
};
|
|
14988
16082
|
}, []);
|
|
14989
|
-
const refreshStateRules =
|
|
16083
|
+
const refreshStateRules = useCallback8(() => {
|
|
14990
16084
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
14991
16085
|
}, []);
|
|
14992
|
-
const processConfigRequest =
|
|
16086
|
+
const processConfigRequest = useCallback8((insertAfterVal) => {
|
|
14993
16087
|
const tracker = getSectionsTracker();
|
|
14994
16088
|
let entries = [];
|
|
14995
16089
|
try {
|
|
@@ -15012,7 +16106,7 @@ function OhhwellsBridge() {
|
|
|
15012
16106
|
}
|
|
15013
16107
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
15014
16108
|
}, [isEditMode]);
|
|
15015
|
-
const deactivate =
|
|
16109
|
+
const deactivate = useCallback8(() => {
|
|
15016
16110
|
const el = activeElRef.current;
|
|
15017
16111
|
if (!el) return;
|
|
15018
16112
|
const isFormBlock = el.dataset.ohwEditable === "form";
|
|
@@ -15053,12 +16147,12 @@ function OhhwellsBridge() {
|
|
|
15053
16147
|
setToolbarShowEditLink(false);
|
|
15054
16148
|
postToParent2({ type: "ow:exit-edit" });
|
|
15055
16149
|
}, [postToParent2]);
|
|
15056
|
-
const clearSelectedAttr =
|
|
16150
|
+
const clearSelectedAttr = useCallback8(() => {
|
|
15057
16151
|
document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
|
|
15058
16152
|
el.removeAttribute("data-ohw-selected");
|
|
15059
16153
|
});
|
|
15060
16154
|
}, []);
|
|
15061
|
-
const deselect =
|
|
16155
|
+
const deselect = useCallback8(() => {
|
|
15062
16156
|
clearSelectedAttr();
|
|
15063
16157
|
selectedElRef.current = null;
|
|
15064
16158
|
selectedHrefKeyRef.current = null;
|
|
@@ -15087,11 +16181,12 @@ function OhhwellsBridge() {
|
|
|
15087
16181
|
setToolbarVariant("none");
|
|
15088
16182
|
}
|
|
15089
16183
|
}, [clearSelectedAttr]);
|
|
15090
|
-
const markSelected =
|
|
16184
|
+
const markSelected = useCallback8((el) => {
|
|
15091
16185
|
clearSelectedAttr();
|
|
16186
|
+
el.removeAttribute("data-ohw-hovered");
|
|
15092
16187
|
el.setAttribute("data-ohw-selected", "");
|
|
15093
16188
|
}, [clearSelectedAttr]);
|
|
15094
|
-
const resolveHrefKeyElement =
|
|
16189
|
+
const resolveHrefKeyElement = useCallback8((hrefKey) => {
|
|
15095
16190
|
if (isFooterHrefKey(hrefKey)) {
|
|
15096
16191
|
return document.querySelector(
|
|
15097
16192
|
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
@@ -15106,7 +16201,7 @@ function OhhwellsBridge() {
|
|
|
15106
16201
|
`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
15107
16202
|
);
|
|
15108
16203
|
}, []);
|
|
15109
|
-
const resyncSelectedNavigationItem =
|
|
16204
|
+
const resyncSelectedNavigationItem = useCallback8(() => {
|
|
15110
16205
|
const hrefKey = selectedHrefKeyRef.current;
|
|
15111
16206
|
if (hrefKey) {
|
|
15112
16207
|
const link = resolveHrefKeyElement(hrefKey);
|
|
@@ -15144,7 +16239,7 @@ function OhhwellsBridge() {
|
|
|
15144
16239
|
);
|
|
15145
16240
|
}
|
|
15146
16241
|
}, [resolveHrefKeyElement]);
|
|
15147
|
-
const reselectNavigationItem =
|
|
16242
|
+
const reselectNavigationItem = useCallback8((navAnchor) => {
|
|
15148
16243
|
selectedElRef.current = navAnchor;
|
|
15149
16244
|
selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
|
|
15150
16245
|
selectedFooterColAttrRef.current = null;
|
|
@@ -15175,7 +16270,7 @@ function OhhwellsBridge() {
|
|
|
15175
16270
|
setToolbarShowEditLink(false);
|
|
15176
16271
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
15177
16272
|
}, [markSelected]);
|
|
15178
|
-
const commitNavigationTextEdit =
|
|
16273
|
+
const commitNavigationTextEdit = useCallback8((navAnchor) => {
|
|
15179
16274
|
const el = activeElRef.current;
|
|
15180
16275
|
if (!el) return;
|
|
15181
16276
|
const key = el.dataset.ohwKey;
|
|
@@ -15208,7 +16303,7 @@ function OhhwellsBridge() {
|
|
|
15208
16303
|
postToParent2({ type: "ow:exit-edit" });
|
|
15209
16304
|
reselectNavigationItem(navAnchor);
|
|
15210
16305
|
}, [postToParent2, reselectNavigationItem]);
|
|
15211
|
-
const handleAddTopLevelNavItem =
|
|
16306
|
+
const handleAddTopLevelNavItem = useCallback8(() => {
|
|
15212
16307
|
const items = listNavbarRootItems();
|
|
15213
16308
|
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
15214
16309
|
deselectRef.current();
|
|
@@ -15220,7 +16315,7 @@ function OhhwellsBridge() {
|
|
|
15220
16315
|
intent: "add-nav"
|
|
15221
16316
|
});
|
|
15222
16317
|
}, []);
|
|
15223
|
-
const maybeWarnNavLinkDropdownConflict =
|
|
16318
|
+
const maybeWarnNavLinkDropdownConflict = useCallback8(
|
|
15224
16319
|
(anchor) => {
|
|
15225
16320
|
if (!isNavbarHrefKey(anchor.getAttribute("data-ohw-href-key"))) return;
|
|
15226
16321
|
if (!navDropdownsOpenOnClick()) return;
|
|
@@ -15233,7 +16328,7 @@ function OhhwellsBridge() {
|
|
|
15233
16328
|
},
|
|
15234
16329
|
[postToParent2]
|
|
15235
16330
|
);
|
|
15236
|
-
const handleNavDropdownOpenChange =
|
|
16331
|
+
const handleNavDropdownOpenChange = useCallback8((open) => {
|
|
15237
16332
|
const selected = selectedElRef.current;
|
|
15238
16333
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
15239
16334
|
setNavGroupForceOpen(selected, open);
|
|
@@ -15245,7 +16340,7 @@ function OhhwellsBridge() {
|
|
|
15245
16340
|
}
|
|
15246
16341
|
});
|
|
15247
16342
|
}, []);
|
|
15248
|
-
const handleFooterHeadingVisibleChange =
|
|
16343
|
+
const handleFooterHeadingVisibleChange = useCallback8(
|
|
15249
16344
|
(visible) => {
|
|
15250
16345
|
const selected = selectedElRef.current;
|
|
15251
16346
|
if (!selected || !isFooterFrameSelectionRef.current) return;
|
|
@@ -15269,7 +16364,7 @@ function OhhwellsBridge() {
|
|
|
15269
16364
|
},
|
|
15270
16365
|
[postToParent2]
|
|
15271
16366
|
);
|
|
15272
|
-
const enterEditOnNewItem =
|
|
16367
|
+
const enterEditOnNewItem = useCallback8((anchor) => {
|
|
15273
16368
|
const label = anchor.querySelector('[data-ohw-editable="text"]');
|
|
15274
16369
|
if (!label) {
|
|
15275
16370
|
selectRef.current(anchor);
|
|
@@ -15278,7 +16373,7 @@ function OhhwellsBridge() {
|
|
|
15278
16373
|
setNavGroupForceOpen(anchor, true);
|
|
15279
16374
|
activateRef.current(label);
|
|
15280
16375
|
}, []);
|
|
15281
|
-
const handleAddChildItem =
|
|
16376
|
+
const handleAddChildItem = useCallback8(() => {
|
|
15282
16377
|
const selected = selectedElRef.current;
|
|
15283
16378
|
if (!selected) return;
|
|
15284
16379
|
const socialsRow = isSocialsRow(selected) ? selected : findSocialsRow(selected);
|
|
@@ -15390,7 +16485,7 @@ function OhhwellsBridge() {
|
|
|
15390
16485
|
enterEditOnNewItem(result.anchor);
|
|
15391
16486
|
});
|
|
15392
16487
|
}, [enterEditOnNewItem, isFooterFrameSelection, maybeWarnNavLinkDropdownConflict, postToParent2]);
|
|
15393
|
-
const handleAddFooterColumn =
|
|
16488
|
+
const handleAddFooterColumn = useCallback8(() => {
|
|
15394
16489
|
if (!canAddFooterColumn()) {
|
|
15395
16490
|
postToParent2({
|
|
15396
16491
|
type: "ow:toast",
|
|
@@ -15411,7 +16506,7 @@ function OhhwellsBridge() {
|
|
|
15411
16506
|
selectRef.current(result.firstLink);
|
|
15412
16507
|
});
|
|
15413
16508
|
}, [postToParent2]);
|
|
15414
|
-
const clearFooterDragVisuals =
|
|
16509
|
+
const clearFooterDragVisuals = useCallback8(() => {
|
|
15415
16510
|
footerDragRef.current = null;
|
|
15416
16511
|
setSiblingHintRects([]);
|
|
15417
16512
|
setFooterDropSlots([]);
|
|
@@ -15420,7 +16515,7 @@ function OhhwellsBridge() {
|
|
|
15420
16515
|
setIsItemDragging(false);
|
|
15421
16516
|
unlockFooterDragInteraction();
|
|
15422
16517
|
}, []);
|
|
15423
|
-
const refreshFooterDragVisuals =
|
|
16518
|
+
const refreshFooterDragVisuals = useCallback8((session, activeSlot, clientX, clientY) => {
|
|
15424
16519
|
const dragged = session.draggedEl;
|
|
15425
16520
|
setDraggedItemRect(dragged.getBoundingClientRect());
|
|
15426
16521
|
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
@@ -15452,13 +16547,13 @@ function OhhwellsBridge() {
|
|
|
15452
16547
|
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
15453
16548
|
setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
15454
16549
|
}, []);
|
|
15455
|
-
const refreshFooterDragVisualsRef =
|
|
16550
|
+
const refreshFooterDragVisualsRef = useRef10(refreshFooterDragVisuals);
|
|
15456
16551
|
refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
|
|
15457
|
-
const commitFooterDragRef =
|
|
16552
|
+
const commitFooterDragRef = useRef10(() => {
|
|
15458
16553
|
});
|
|
15459
|
-
const beginFooterDragRef =
|
|
16554
|
+
const beginFooterDragRef = useRef10(() => {
|
|
15460
16555
|
});
|
|
15461
|
-
const beginFooterDrag =
|
|
16556
|
+
const beginFooterDrag = useCallback8(
|
|
15462
16557
|
(session) => {
|
|
15463
16558
|
const rect = session.draggedEl.getBoundingClientRect();
|
|
15464
16559
|
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
@@ -15478,7 +16573,7 @@ function OhhwellsBridge() {
|
|
|
15478
16573
|
[refreshFooterDragVisuals]
|
|
15479
16574
|
);
|
|
15480
16575
|
beginFooterDragRef.current = beginFooterDrag;
|
|
15481
|
-
const commitFooterDrag =
|
|
16576
|
+
const commitFooterDrag = useCallback8(
|
|
15482
16577
|
(clientX, clientY) => {
|
|
15483
16578
|
const session = footerDragRef.current;
|
|
15484
16579
|
if (!session) {
|
|
@@ -15606,7 +16701,7 @@ function OhhwellsBridge() {
|
|
|
15606
16701
|
[clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
|
|
15607
16702
|
);
|
|
15608
16703
|
commitFooterDragRef.current = commitFooterDrag;
|
|
15609
|
-
const startFooterLinkDrag =
|
|
16704
|
+
const startFooterLinkDrag = useCallback8(
|
|
15610
16705
|
(anchor, clientX, clientY, wasSelected) => {
|
|
15611
16706
|
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
15612
16707
|
if (!hrefKey) return false;
|
|
@@ -15642,7 +16737,7 @@ function OhhwellsBridge() {
|
|
|
15642
16737
|
},
|
|
15643
16738
|
[beginFooterDrag]
|
|
15644
16739
|
);
|
|
15645
|
-
const startFooterColumnDrag =
|
|
16740
|
+
const startFooterColumnDrag = useCallback8(
|
|
15646
16741
|
(columnEl, clientX, clientY, wasSelected) => {
|
|
15647
16742
|
const columns = listFooterColumns();
|
|
15648
16743
|
const idx = columns.indexOf(columnEl);
|
|
@@ -15662,7 +16757,7 @@ function OhhwellsBridge() {
|
|
|
15662
16757
|
},
|
|
15663
16758
|
[beginFooterDrag]
|
|
15664
16759
|
);
|
|
15665
|
-
const handleItemDragStart =
|
|
16760
|
+
const handleItemDragStart = useCallback8(
|
|
15666
16761
|
(e) => {
|
|
15667
16762
|
const selected = selectedElRef.current;
|
|
15668
16763
|
if (!selected) {
|
|
@@ -15682,7 +16777,7 @@ function OhhwellsBridge() {
|
|
|
15682
16777
|
},
|
|
15683
16778
|
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
|
|
15684
16779
|
);
|
|
15685
|
-
const handleItemDragEnd =
|
|
16780
|
+
const handleItemDragEnd = useCallback8(
|
|
15686
16781
|
(e) => {
|
|
15687
16782
|
if (footerDragRef.current) {
|
|
15688
16783
|
const x = e?.clientX;
|
|
@@ -15708,7 +16803,7 @@ function OhhwellsBridge() {
|
|
|
15708
16803
|
},
|
|
15709
16804
|
[commitFooterDrag, commitNavDrag, navDragRef]
|
|
15710
16805
|
);
|
|
15711
|
-
const handleItemChromePointerDown =
|
|
16806
|
+
const handleItemChromePointerDown = useCallback8((e) => {
|
|
15712
16807
|
if (e.button !== 0) return;
|
|
15713
16808
|
const selected = selectedElRef.current;
|
|
15714
16809
|
if (!selected) return;
|
|
@@ -15739,7 +16834,7 @@ function OhhwellsBridge() {
|
|
|
15739
16834
|
}
|
|
15740
16835
|
if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
|
|
15741
16836
|
}, [armNavPressFromChrome]);
|
|
15742
|
-
const handleItemChromeClick =
|
|
16837
|
+
const handleItemChromeClick = useCallback8((clientX, clientY) => {
|
|
15743
16838
|
if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
|
|
15744
16839
|
suppressNextClickRef.current = false;
|
|
15745
16840
|
return;
|
|
@@ -15752,7 +16847,7 @@ function OhhwellsBridge() {
|
|
|
15752
16847
|
}, []);
|
|
15753
16848
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
15754
16849
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
15755
|
-
const select =
|
|
16850
|
+
const select = useCallback8((anchor) => {
|
|
15756
16851
|
if (!isNavigationItem2(anchor)) return;
|
|
15757
16852
|
if (activeElRef.current) deactivate();
|
|
15758
16853
|
aiSectionApiRef.current?.selectFromElement(anchor);
|
|
@@ -15795,7 +16890,7 @@ function OhhwellsBridge() {
|
|
|
15795
16890
|
setFloatingPanel(null);
|
|
15796
16891
|
setLogoSizeDraft(null);
|
|
15797
16892
|
}, [deactivate, markSelected]);
|
|
15798
|
-
const selectFrame =
|
|
16893
|
+
const selectFrame = useCallback8((el) => {
|
|
15799
16894
|
if (!isNavigationContainer(el)) return;
|
|
15800
16895
|
if (activeElRef.current) deactivate();
|
|
15801
16896
|
aiSectionApiRef.current?.selectFromElement(el);
|
|
@@ -15846,7 +16941,7 @@ function OhhwellsBridge() {
|
|
|
15846
16941
|
setFloatingPanel(null);
|
|
15847
16942
|
setLogoSizeDraft(null);
|
|
15848
16943
|
}, [deactivate, markSelected, postToParent2]);
|
|
15849
|
-
const selectLogo =
|
|
16944
|
+
const selectLogo = useCallback8(
|
|
15850
16945
|
(logoEl) => {
|
|
15851
16946
|
if (activeElRef.current) deactivate();
|
|
15852
16947
|
selectedElRef.current = logoEl;
|
|
@@ -15875,7 +16970,7 @@ function OhhwellsBridge() {
|
|
|
15875
16970
|
},
|
|
15876
16971
|
[deactivate, markSelected]
|
|
15877
16972
|
);
|
|
15878
|
-
const openLogoSizePanel =
|
|
16973
|
+
const openLogoSizePanel = useCallback8((logoEl) => {
|
|
15879
16974
|
const placement = getLogoPlacement(logoEl);
|
|
15880
16975
|
const draft = readLogoSizeState(editContentRef.current, placement);
|
|
15881
16976
|
setLogoSizeDraft(draft);
|
|
@@ -15888,7 +16983,7 @@ function OhhwellsBridge() {
|
|
|
15888
16983
|
placement
|
|
15889
16984
|
});
|
|
15890
16985
|
}, []);
|
|
15891
|
-
const openSocialsDisplayPanel =
|
|
16986
|
+
const openSocialsDisplayPanel = useCallback8((row) => {
|
|
15892
16987
|
setParentScrollSnap(parentScrollRef.current);
|
|
15893
16988
|
setFloatingPanel({
|
|
15894
16989
|
key: "socials-display",
|
|
@@ -15898,7 +16993,7 @@ function OhhwellsBridge() {
|
|
|
15898
16993
|
row
|
|
15899
16994
|
});
|
|
15900
16995
|
}, []);
|
|
15901
|
-
const changeSocialsDisplay =
|
|
16996
|
+
const changeSocialsDisplay = useCallback8(
|
|
15902
16997
|
(row, next) => {
|
|
15903
16998
|
if (next.icon) {
|
|
15904
16999
|
const missing = socialsMissingIcons(row);
|
|
@@ -15921,17 +17016,17 @@ function OhhwellsBridge() {
|
|
|
15921
17016
|
},
|
|
15922
17017
|
[]
|
|
15923
17018
|
);
|
|
15924
|
-
const closeFloatingPanelOnly =
|
|
17019
|
+
const closeFloatingPanelOnly = useCallback8(() => {
|
|
15925
17020
|
setFloatingPanel(null);
|
|
15926
17021
|
setLogoSizeDraft(null);
|
|
15927
17022
|
}, []);
|
|
15928
17023
|
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
15929
|
-
const closeFloatingPanelAndDeselect =
|
|
17024
|
+
const closeFloatingPanelAndDeselect = useCallback8(() => {
|
|
15930
17025
|
setFloatingPanel(null);
|
|
15931
17026
|
setLogoSizeDraft(null);
|
|
15932
17027
|
deselectRef.current();
|
|
15933
17028
|
}, []);
|
|
15934
|
-
|
|
17029
|
+
useEffect13(() => {
|
|
15935
17030
|
const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
|
|
15936
17031
|
if (!session || !logoSizeDraft) {
|
|
15937
17032
|
postToParentRef.current({ type: "ow:logo-size-panel", open: false });
|
|
@@ -15950,7 +17045,7 @@ function OhhwellsBridge() {
|
|
|
15950
17045
|
max: LOGO_SIZE_MAX
|
|
15951
17046
|
});
|
|
15952
17047
|
}, [floatingPanel, logoSizeDraft, editorViewport]);
|
|
15953
|
-
const persistLogoSizeDraft =
|
|
17048
|
+
const persistLogoSizeDraft = useCallback8(
|
|
15954
17049
|
(placement, draft) => {
|
|
15955
17050
|
const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
|
|
15956
17051
|
const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
|
|
@@ -15990,7 +17085,7 @@ function OhhwellsBridge() {
|
|
|
15990
17085
|
},
|
|
15991
17086
|
[postToParent2]
|
|
15992
17087
|
);
|
|
15993
|
-
const activate =
|
|
17088
|
+
const activate = useCallback8((el, options) => {
|
|
15994
17089
|
if (activeElRef.current === el) return;
|
|
15995
17090
|
if (isIconEditable(el)) return;
|
|
15996
17091
|
if (el.hasAttribute("data-ohw-social-label")) return;
|
|
@@ -16074,8 +17169,8 @@ function OhhwellsBridge() {
|
|
|
16074
17169
|
openLogoSizePanelRef.current = openLogoSizePanel;
|
|
16075
17170
|
deselectRef.current = deselect;
|
|
16076
17171
|
closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
|
|
16077
|
-
const lastSiteWideScopeRef =
|
|
16078
|
-
|
|
17172
|
+
const lastSiteWideScopeRef = useRef10(null);
|
|
17173
|
+
useEffect13(() => {
|
|
16079
17174
|
if (!isEditMode) {
|
|
16080
17175
|
if (lastSiteWideScopeRef.current !== false) {
|
|
16081
17176
|
lastSiteWideScopeRef.current = false;
|
|
@@ -16108,15 +17203,27 @@ function OhhwellsBridge() {
|
|
|
16108
17203
|
}
|
|
16109
17204
|
const applyContent = (content) => {
|
|
16110
17205
|
const imageLoads = [];
|
|
17206
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
17207
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
17208
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
17209
|
+
}
|
|
16111
17210
|
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
16112
17211
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
16113
17212
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
16114
17213
|
}
|
|
17214
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
17215
|
+
stylesRef.current = content[STYLE_STORE_KEY];
|
|
17216
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
17217
|
+
}
|
|
17218
|
+
applyBrandChrome(content);
|
|
16115
17219
|
for (const [key, val] of Object.entries(content)) {
|
|
16116
17220
|
if (key === "__ohw_sections") continue;
|
|
16117
17221
|
if (key === AI_SECTIONS_KEY) continue;
|
|
16118
17222
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
16119
17223
|
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
17224
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
17225
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17226
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
16120
17227
|
if (applyVideoSettingNode(key, val)) continue;
|
|
16121
17228
|
if (applyCarouselNode(key, val)) continue;
|
|
16122
17229
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -16174,7 +17281,9 @@ function OhhwellsBridge() {
|
|
|
16174
17281
|
let cancelled = false;
|
|
16175
17282
|
setFetchState("loading");
|
|
16176
17283
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
16177
|
-
|
|
17284
|
+
const initialPath = pathname;
|
|
17285
|
+
fetchedContentPaths.add(`${subdomain}::${initialPath}`);
|
|
17286
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
16178
17287
|
if (cancelled) return;
|
|
16179
17288
|
const content = data?.content ?? {};
|
|
16180
17289
|
contentCache.set(subdomain, content);
|
|
@@ -16187,7 +17296,7 @@ function OhhwellsBridge() {
|
|
|
16187
17296
|
cancelled = true;
|
|
16188
17297
|
};
|
|
16189
17298
|
}, [subdomain, isEditMode]);
|
|
16190
|
-
|
|
17299
|
+
useEffect13(() => {
|
|
16191
17300
|
if (!isEditMode) return;
|
|
16192
17301
|
const resolveIndex = (form, clientY) => {
|
|
16193
17302
|
const wrappers = listFieldWrappers(form).filter((el) => fieldKeyOf(el) !== fieldDragRef.current?.key);
|
|
@@ -16228,7 +17337,7 @@ function OhhwellsBridge() {
|
|
|
16228
17337
|
window.removeEventListener("drop", onDrop, true);
|
|
16229
17338
|
};
|
|
16230
17339
|
}, [buildFieldDropSlots, isEditMode, persistFields, selectField]);
|
|
16231
|
-
|
|
17340
|
+
useEffect13(() => {
|
|
16232
17341
|
if (!isEditMode) return;
|
|
16233
17342
|
const mark = () => document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
16234
17343
|
markFormFields(form);
|
|
@@ -16240,7 +17349,7 @@ function OhhwellsBridge() {
|
|
|
16240
17349
|
});
|
|
16241
17350
|
return () => observer.disconnect();
|
|
16242
17351
|
}, [isEditMode, fetchState, pathname]);
|
|
16243
|
-
|
|
17352
|
+
useEffect13(() => {
|
|
16244
17353
|
if (!isEditMode) return;
|
|
16245
17354
|
let saveTimer = null;
|
|
16246
17355
|
const onInput = (e) => {
|
|
@@ -16262,14 +17371,14 @@ function OhhwellsBridge() {
|
|
|
16262
17371
|
document.addEventListener("input", onInput, true);
|
|
16263
17372
|
return () => document.removeEventListener("input", onInput, true);
|
|
16264
17373
|
}, [isEditMode, persistFields]);
|
|
16265
|
-
|
|
17374
|
+
useEffect13(() => {
|
|
16266
17375
|
if (isEditMode || fetchState !== "done") return;
|
|
16267
17376
|
const content = contentCache.get(subdomain) ?? {};
|
|
16268
17377
|
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
16269
17378
|
reconcileFieldsFromContent(form, content);
|
|
16270
17379
|
});
|
|
16271
17380
|
}, [isEditMode, fetchState, subdomain]);
|
|
16272
|
-
|
|
17381
|
+
useEffect13(() => {
|
|
16273
17382
|
if (!isEditMode) return;
|
|
16274
17383
|
const swallow = (e) => {
|
|
16275
17384
|
const target = e.target;
|
|
@@ -16278,12 +17387,12 @@ function OhhwellsBridge() {
|
|
|
16278
17387
|
document.addEventListener("submit", swallow, true);
|
|
16279
17388
|
return () => document.removeEventListener("submit", swallow, true);
|
|
16280
17389
|
}, [isEditMode]);
|
|
16281
|
-
|
|
17390
|
+
useEffect13(() => {
|
|
16282
17391
|
if (isEditMode || fetchState !== "done") return;
|
|
16283
17392
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
16284
17393
|
bindPublishedForms(apiUrl, subdomain, contentCache.get(subdomain) ?? {});
|
|
16285
17394
|
}, [isEditMode, fetchState, subdomain]);
|
|
16286
|
-
|
|
17395
|
+
useEffect13(() => {
|
|
16287
17396
|
if (!subdomain || isEditMode) return;
|
|
16288
17397
|
let debounceTimer = null;
|
|
16289
17398
|
let observer = null;
|
|
@@ -16294,10 +17403,21 @@ function OhhwellsBridge() {
|
|
|
16294
17403
|
initSectionInstancesFromContent(content, window.location.pathname);
|
|
16295
17404
|
observer?.disconnect();
|
|
16296
17405
|
try {
|
|
17406
|
+
applyBrandChrome(content);
|
|
17407
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
17408
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
17409
|
+
}
|
|
17410
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
17411
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
17412
|
+
}
|
|
16297
17413
|
for (const [key, val] of Object.entries(content)) {
|
|
16298
17414
|
if (key === "__ohw_sections") continue;
|
|
16299
17415
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
16300
17416
|
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
17417
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
17418
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17419
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
17420
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
16301
17421
|
if (applyVideoSettingNode(key, val)) continue;
|
|
16302
17422
|
if (applyCarouselNode(key, val)) continue;
|
|
16303
17423
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -16340,6 +17460,17 @@ function OhhwellsBridge() {
|
|
|
16340
17460
|
debounceTimer = setTimeout(applyFromCache, 150);
|
|
16341
17461
|
};
|
|
16342
17462
|
applyFromCache();
|
|
17463
|
+
const pathCacheKey = `${subdomain}::${pathname}`;
|
|
17464
|
+
if (!fetchedContentPaths.has(pathCacheKey)) {
|
|
17465
|
+
fetchedContentPaths.add(pathCacheKey);
|
|
17466
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
17467
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
17468
|
+
if (!data?.content) return;
|
|
17469
|
+
contentCache.set(subdomain, data.content);
|
|
17470
|
+
applyFromCache();
|
|
17471
|
+
}).catch(() => {
|
|
17472
|
+
});
|
|
17473
|
+
}
|
|
16343
17474
|
observer = new MutationObserver(scheduleApply);
|
|
16344
17475
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
16345
17476
|
return () => {
|
|
@@ -16353,10 +17484,10 @@ function OhhwellsBridge() {
|
|
|
16353
17484
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
16354
17485
|
el.style.display = visible ? "flex" : "none";
|
|
16355
17486
|
}, [subdomain, fetchState]);
|
|
16356
|
-
|
|
17487
|
+
useEffect13(() => {
|
|
16357
17488
|
postToParent2({ type: "ow:navigation", path: pathname });
|
|
16358
17489
|
}, [pathname, postToParent2]);
|
|
16359
|
-
|
|
17490
|
+
useEffect13(() => {
|
|
16360
17491
|
if (!isEditMode) return;
|
|
16361
17492
|
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
16362
17493
|
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
@@ -16364,7 +17495,7 @@ function OhhwellsBridge() {
|
|
|
16364
17495
|
deselectRef.current();
|
|
16365
17496
|
deactivateRef.current();
|
|
16366
17497
|
}, [pathname, isEditMode]);
|
|
16367
|
-
|
|
17498
|
+
useEffect13(() => {
|
|
16368
17499
|
const contentForNav = () => {
|
|
16369
17500
|
if (isEditMode) return editContentRef.current;
|
|
16370
17501
|
if (!subdomain) return {};
|
|
@@ -16431,31 +17562,36 @@ function OhhwellsBridge() {
|
|
|
16431
17562
|
observer?.disconnect();
|
|
16432
17563
|
};
|
|
16433
17564
|
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
16434
|
-
|
|
17565
|
+
useEffect13(() => {
|
|
16435
17566
|
if (!isEditMode) return;
|
|
17567
|
+
let lastPosted = 0;
|
|
16436
17568
|
const measure = () => {
|
|
16437
17569
|
const h = document.body.scrollHeight;
|
|
16438
|
-
if (h > 50
|
|
17570
|
+
if (h > 50 && Math.abs(h - lastPosted) > 1) {
|
|
17571
|
+
lastPosted = h;
|
|
17572
|
+
postToParent2({ type: "ow:height", height: h });
|
|
17573
|
+
}
|
|
17574
|
+
};
|
|
17575
|
+
let raf = null;
|
|
17576
|
+
const schedule = () => {
|
|
17577
|
+
if (raf != null) return;
|
|
17578
|
+
raf = requestAnimationFrame(() => {
|
|
17579
|
+
raf = null;
|
|
17580
|
+
measure();
|
|
17581
|
+
});
|
|
16439
17582
|
};
|
|
16440
17583
|
const t1 = setTimeout(measure, 50);
|
|
16441
17584
|
const t2 = setTimeout(measure, 500);
|
|
16442
|
-
|
|
16443
|
-
|
|
16444
|
-
const handleResize = () => {
|
|
16445
|
-
if (window.innerWidth === lastWidth) return;
|
|
16446
|
-
lastWidth = window.innerWidth;
|
|
16447
|
-
if (resizeTimer) clearTimeout(resizeTimer);
|
|
16448
|
-
resizeTimer = setTimeout(measure, 150);
|
|
16449
|
-
};
|
|
16450
|
-
window.addEventListener("resize", handleResize);
|
|
17585
|
+
const ro = new ResizeObserver(schedule);
|
|
17586
|
+
ro.observe(document.body);
|
|
16451
17587
|
return () => {
|
|
16452
17588
|
clearTimeout(t1);
|
|
16453
17589
|
clearTimeout(t2);
|
|
16454
|
-
if (
|
|
16455
|
-
|
|
17590
|
+
if (raf != null) cancelAnimationFrame(raf);
|
|
17591
|
+
ro.disconnect();
|
|
16456
17592
|
};
|
|
16457
17593
|
}, [pathname, isEditMode, postToParent2]);
|
|
16458
|
-
|
|
17594
|
+
useEffect13(() => {
|
|
16459
17595
|
if (!subdomainFromQuery || isEditMode) return;
|
|
16460
17596
|
const handleClick = (e) => {
|
|
16461
17597
|
const anchor = e.target.closest("a");
|
|
@@ -16471,7 +17607,7 @@ function OhhwellsBridge() {
|
|
|
16471
17607
|
document.addEventListener("click", handleClick, true);
|
|
16472
17608
|
return () => document.removeEventListener("click", handleClick, true);
|
|
16473
17609
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
16474
|
-
|
|
17610
|
+
useEffect13(() => {
|
|
16475
17611
|
if (!isEditMode) {
|
|
16476
17612
|
editStylesRef.current?.base.remove();
|
|
16477
17613
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -16633,16 +17769,21 @@ function OhhwellsBridge() {
|
|
|
16633
17769
|
return;
|
|
16634
17770
|
}
|
|
16635
17771
|
const target = e.target;
|
|
17772
|
+
if (target.closest("[data-ohw-ai-review]")) return;
|
|
16636
17773
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
16637
17774
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
16638
17775
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
16639
17776
|
if (isInsideLinkEditor(target)) return;
|
|
17777
|
+
if (isInsideFloatingPanel(target)) return;
|
|
16640
17778
|
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
16641
17779
|
if (target.closest(
|
|
16642
17780
|
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
16643
17781
|
)) {
|
|
16644
17782
|
return;
|
|
16645
17783
|
}
|
|
17784
|
+
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
17785
|
+
clearMediaSelectionRef.current();
|
|
17786
|
+
}
|
|
16646
17787
|
{
|
|
16647
17788
|
const formEl = getFormElement(target);
|
|
16648
17789
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -16790,8 +17931,11 @@ function OhhwellsBridge() {
|
|
|
16790
17931
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
16791
17932
|
e.preventDefault();
|
|
16792
17933
|
e.stopPropagation();
|
|
16793
|
-
|
|
16794
|
-
|
|
17934
|
+
if (selectedMediaElRef.current === editable) {
|
|
17935
|
+
postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
|
|
17936
|
+
} else {
|
|
17937
|
+
selectMediaElementRef.current(editable);
|
|
17938
|
+
}
|
|
16795
17939
|
return;
|
|
16796
17940
|
}
|
|
16797
17941
|
const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
|
|
@@ -16910,10 +18054,12 @@ function OhhwellsBridge() {
|
|
|
16910
18054
|
};
|
|
16911
18055
|
const handleDblClick = (e) => {
|
|
16912
18056
|
const target = e.target;
|
|
18057
|
+
if (target.closest("[data-ohw-ai-review]")) return;
|
|
16913
18058
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
16914
18059
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
16915
18060
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
16916
18061
|
if (isInsideLinkEditor(target)) return;
|
|
18062
|
+
if (isInsideFloatingPanel(target)) return;
|
|
16917
18063
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
16918
18064
|
return;
|
|
16919
18065
|
}
|
|
@@ -16954,11 +18100,14 @@ function OhhwellsBridge() {
|
|
|
16954
18100
|
setSiblingHintRects([]);
|
|
16955
18101
|
return;
|
|
16956
18102
|
}
|
|
16957
|
-
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || target.
|
|
18103
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
|
|
16958
18104
|
hoveredItemElRef.current = null;
|
|
16959
18105
|
setHoveredItemRect(null);
|
|
16960
18106
|
hoveredNavContainerRef.current = null;
|
|
16961
18107
|
setHoveredNavContainerRect(null);
|
|
18108
|
+
siblingHintElRef.current = null;
|
|
18109
|
+
setSiblingHintRect(null);
|
|
18110
|
+
setSiblingHintRects([]);
|
|
16962
18111
|
return;
|
|
16963
18112
|
}
|
|
16964
18113
|
{
|
|
@@ -16976,6 +18125,16 @@ function OhhwellsBridge() {
|
|
|
16976
18125
|
return;
|
|
16977
18126
|
}
|
|
16978
18127
|
}
|
|
18128
|
+
if (allowNavContainerHover) {
|
|
18129
|
+
const socialsRow = isSocialsRow(target) ? target : null;
|
|
18130
|
+
if (socialsRow && !getSocialItem(target) && selected2 !== socialsRow) {
|
|
18131
|
+
hoveredNavContainerRef.current = socialsRow;
|
|
18132
|
+
setHoveredNavContainerRect(socialsRow.getBoundingClientRect());
|
|
18133
|
+
hoveredItemElRef.current = null;
|
|
18134
|
+
setHoveredItemRect(null);
|
|
18135
|
+
return;
|
|
18136
|
+
}
|
|
18137
|
+
}
|
|
16979
18138
|
if (allowFooterLinksHover) {
|
|
16980
18139
|
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
16981
18140
|
if (!navContainer) {
|
|
@@ -17061,13 +18220,12 @@ function OhhwellsBridge() {
|
|
|
17061
18220
|
clearHrefKeyHover(hoverTarget);
|
|
17062
18221
|
hoveredItemElRef.current = hoverTarget;
|
|
17063
18222
|
setHoveredItemRect(hoverTarget.getBoundingClientRect());
|
|
17064
|
-
} else if (!isInsideNavigationItem(editable)) {
|
|
18223
|
+
} else if (!isInsideNavigationItem(editable) && hoverTarget !== selectedElRef.current) {
|
|
17065
18224
|
hoverTarget.setAttribute("data-ohw-hovered", "");
|
|
17066
18225
|
if (editable.closest("footer") || editable.closest('[data-ohw-section="footer"]')) {
|
|
17067
18226
|
hoveredNavContainerRef.current = null;
|
|
17068
18227
|
setHoveredNavContainerRect(null);
|
|
17069
18228
|
hoveredItemElRef.current = editable;
|
|
17070
|
-
setHoveredItemRect(editable.getBoundingClientRect());
|
|
17071
18229
|
}
|
|
17072
18230
|
}
|
|
17073
18231
|
}
|
|
@@ -17364,7 +18522,7 @@ function OhhwellsBridge() {
|
|
|
17364
18522
|
}
|
|
17365
18523
|
};
|
|
17366
18524
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
17367
|
-
if (linkPopoverOpenRef.current) {
|
|
18525
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
17368
18526
|
if (hoveredImageRef.current) {
|
|
17369
18527
|
hoveredImageRef.current = null;
|
|
17370
18528
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -17623,7 +18781,7 @@ function OhhwellsBridge() {
|
|
|
17623
18781
|
}
|
|
17624
18782
|
};
|
|
17625
18783
|
const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
|
|
17626
|
-
if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
18784
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
17627
18785
|
if (activeStateElRef.current) {
|
|
17628
18786
|
activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
|
|
17629
18787
|
activeStateElRef.current = null;
|
|
@@ -17660,6 +18818,35 @@ function OhhwellsBridge() {
|
|
|
17660
18818
|
}
|
|
17661
18819
|
}
|
|
17662
18820
|
};
|
|
18821
|
+
const probeSocialsRowAt = (clientX, clientY, fromParentViewport = false) => {
|
|
18822
|
+
const wasSocialsRow = Boolean(hoveredNavContainerRef.current?.hasAttribute(SOCIALS_ROW_ATTR));
|
|
18823
|
+
const clear = () => {
|
|
18824
|
+
if (!wasSocialsRow) return false;
|
|
18825
|
+
hoveredNavContainerRef.current = null;
|
|
18826
|
+
setHoveredNavContainerRect(null);
|
|
18827
|
+
return false;
|
|
18828
|
+
};
|
|
18829
|
+
if (linkPopoverOpenRef.current || toolbarVariantRef.current === "select-frame") return clear();
|
|
18830
|
+
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
18831
|
+
const SLACK = 6;
|
|
18832
|
+
for (const row of Array.from(document.querySelectorAll(`[${SOCIALS_ROW_ATTR}]`))) {
|
|
18833
|
+
const rect = row.getBoundingClientRect();
|
|
18834
|
+
const inside = x >= rect.left - SLACK && x <= rect.right + SLACK && y >= rect.top - SLACK && y <= rect.bottom + SLACK;
|
|
18835
|
+
if (!inside) continue;
|
|
18836
|
+
if (selectedElRef.current === row) return clear();
|
|
18837
|
+
const overItem = listSocialItems(row).some((item) => {
|
|
18838
|
+
const box = item.getBoundingClientRect();
|
|
18839
|
+
return x >= box.left && x <= box.right && y >= box.top && y <= box.bottom;
|
|
18840
|
+
});
|
|
18841
|
+
if (overItem) return clear();
|
|
18842
|
+
hoveredNavContainerRef.current = row;
|
|
18843
|
+
setHoveredNavContainerRect(rect);
|
|
18844
|
+
hoveredItemElRef.current = null;
|
|
18845
|
+
setHoveredItemRect(null);
|
|
18846
|
+
return true;
|
|
18847
|
+
}
|
|
18848
|
+
return clear();
|
|
18849
|
+
};
|
|
17663
18850
|
const probeSectionGapAt = (clientX, clientY, fromParentViewport = false) => {
|
|
17664
18851
|
if (linkPopoverOpenRef.current) {
|
|
17665
18852
|
if (hoveredGapRef.current) {
|
|
@@ -17669,7 +18856,9 @@ function OhhwellsBridge() {
|
|
|
17669
18856
|
return;
|
|
17670
18857
|
}
|
|
17671
18858
|
const { y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
17672
|
-
const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).
|
|
18859
|
+
const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
18860
|
+
(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
|
|
18861
|
+
).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
|
|
17673
18862
|
const ZONE = 20;
|
|
17674
18863
|
for (let i = 0; i < sections.length; i++) {
|
|
17675
18864
|
const a = sections[i];
|
|
@@ -17698,8 +18887,7 @@ function OhhwellsBridge() {
|
|
|
17698
18887
|
};
|
|
17699
18888
|
const handleMouseMove = (e) => {
|
|
17700
18889
|
const { clientX, clientY } = e;
|
|
17701
|
-
if (
|
|
17702
|
-
if (isOverEditorChrome(clientX, clientY)) {
|
|
18890
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
|
|
17703
18891
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
17704
18892
|
formHoverElRef.current = null;
|
|
17705
18893
|
setFormHoverRect(null);
|
|
@@ -17707,8 +18895,15 @@ function OhhwellsBridge() {
|
|
|
17707
18895
|
setHoveredItemRect(null);
|
|
17708
18896
|
hoveredNavContainerRef.current = null;
|
|
17709
18897
|
setHoveredNavContainerRect(null);
|
|
18898
|
+
siblingHintElRef.current = null;
|
|
18899
|
+
setSiblingHintRect(null);
|
|
18900
|
+
setSiblingHintRects([]);
|
|
18901
|
+
dismissImageHover();
|
|
18902
|
+
clearImageHover();
|
|
18903
|
+
setSectionGap(null);
|
|
17710
18904
|
return;
|
|
17711
18905
|
}
|
|
18906
|
+
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
17712
18907
|
probeSectionGapAt(clientX, clientY);
|
|
17713
18908
|
probeImageAt(clientX, clientY);
|
|
17714
18909
|
probeHoverCardsAt(clientX, clientY);
|
|
@@ -17717,7 +18912,12 @@ function OhhwellsBridge() {
|
|
|
17717
18912
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
17718
18913
|
const { clientX, clientY } = e.data;
|
|
17719
18914
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
17720
|
-
if (
|
|
18915
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
18916
|
+
dismissImageHover();
|
|
18917
|
+
clearImageHover();
|
|
18918
|
+
return;
|
|
18919
|
+
}
|
|
18920
|
+
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
17721
18921
|
probeSectionGapAt(clientX, clientY);
|
|
17722
18922
|
probeImageAt(clientX, clientY);
|
|
17723
18923
|
probeHoverCardsAt(clientX, clientY);
|
|
@@ -17963,10 +19163,19 @@ function OhhwellsBridge() {
|
|
|
17963
19163
|
if (e.data?.type !== "ow:hydrate") return;
|
|
17964
19164
|
const content = e.data.content;
|
|
17965
19165
|
if (!content) return;
|
|
19166
|
+
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
19167
|
+
brandKitRef.current = content[BRAND_KIT_KEY];
|
|
19168
|
+
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
19169
|
+
}
|
|
17966
19170
|
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
17967
19171
|
aiSectionsRef.current = content[AI_SECTIONS_KEY];
|
|
17968
19172
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
17969
19173
|
}
|
|
19174
|
+
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
19175
|
+
stylesRef.current = content[STYLE_STORE_KEY];
|
|
19176
|
+
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
19177
|
+
}
|
|
19178
|
+
applyBrandChrome(content);
|
|
17970
19179
|
let sectionsJson = null;
|
|
17971
19180
|
for (const [key, val] of Object.entries(content)) {
|
|
17972
19181
|
if (key === "__ohw_sections") {
|
|
@@ -17976,6 +19185,9 @@ function OhhwellsBridge() {
|
|
|
17976
19185
|
if (key === AI_SECTIONS_KEY) continue;
|
|
17977
19186
|
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
17978
19187
|
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
19188
|
+
if (key === BRAND_KIT_KEY) continue;
|
|
19189
|
+
if (key === STYLE_STORE_KEY) continue;
|
|
19190
|
+
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
17979
19191
|
if (applyVideoSettingNode(key, val)) continue;
|
|
17980
19192
|
if (applyCarouselNode(key, val)) continue;
|
|
17981
19193
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -17989,6 +19201,8 @@ function OhhwellsBridge() {
|
|
|
17989
19201
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
17990
19202
|
} else if (el.dataset.ohwEditable === "link") {
|
|
17991
19203
|
applyLinkHref(el, val);
|
|
19204
|
+
} else if (el.dataset.ohwEditable === "icon") {
|
|
19205
|
+
applyIconMarkup(el, val);
|
|
17992
19206
|
} else {
|
|
17993
19207
|
el.innerHTML = val;
|
|
17994
19208
|
}
|
|
@@ -18072,12 +19286,21 @@ function OhhwellsBridge() {
|
|
|
18072
19286
|
nodes: collectEditableNodes(editContentRef.current)
|
|
18073
19287
|
});
|
|
18074
19288
|
};
|
|
19289
|
+
const clearInteractionChrome = () => {
|
|
19290
|
+
deactivateRef.current();
|
|
19291
|
+
deselectRef.current();
|
|
19292
|
+
clearMediaSelectionRef.current();
|
|
19293
|
+
};
|
|
18075
19294
|
const handleAiApplyTree = (e) => {
|
|
18076
19295
|
if (e.data?.type !== "ow:ai-apply-tree") return;
|
|
18077
19296
|
const payload = e.data.payload;
|
|
18078
19297
|
if (!payload || typeof payload.id !== "string" || !isRenderableTree(payload.tree)) return;
|
|
19298
|
+
clearInteractionChrome();
|
|
18079
19299
|
const previous = aiSectionsRef.current;
|
|
18080
|
-
const nextState = applyTreeToState(parseAiSectionsState(previous),
|
|
19300
|
+
const nextState = applyTreeToState(parseAiSectionsState(previous), {
|
|
19301
|
+
...payload,
|
|
19302
|
+
path: payload.path ?? window.location.pathname
|
|
19303
|
+
});
|
|
18081
19304
|
const nextValue = serializeAiSectionsState(nextState);
|
|
18082
19305
|
aiSectionsRef.current = nextValue;
|
|
18083
19306
|
applyAiSectionsToDom(nextState);
|
|
@@ -18097,6 +19320,7 @@ function OhhwellsBridge() {
|
|
|
18097
19320
|
if (!sectionId || sectionId === "navbar" || sectionId === "footer") return;
|
|
18098
19321
|
const exists = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
|
|
18099
19322
|
if (!exists) return;
|
|
19323
|
+
clearInteractionChrome();
|
|
18100
19324
|
const previous = aiSectionsRef.current;
|
|
18101
19325
|
const nextState = deleteSectionFromState(parseAiSectionsState(previous), sectionId);
|
|
18102
19326
|
const nextValue = serializeAiSectionsState(nextState);
|
|
@@ -18112,14 +19336,58 @@ function OhhwellsBridge() {
|
|
|
18112
19336
|
const handleAiSetSections = (e) => {
|
|
18113
19337
|
if (e.data?.type !== "ow:ai-set-sections") return;
|
|
18114
19338
|
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
19339
|
+
clearInteractionChrome();
|
|
18115
19340
|
aiSectionsRef.current = value;
|
|
18116
19341
|
applyAiSectionsToDom(parseAiSectionsState(value));
|
|
19342
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
18117
19343
|
const restoredHeight = document.documentElement.scrollHeight;
|
|
18118
19344
|
if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
|
|
18119
19345
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
|
|
18120
19346
|
postAiSectionsChanged();
|
|
18121
19347
|
};
|
|
18122
19348
|
window.addEventListener("message", handleAiSetSections);
|
|
19349
|
+
const handleMoveSection = (e) => {
|
|
19350
|
+
if (e.data?.type !== "ow:move-section") return;
|
|
19351
|
+
const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
|
|
19352
|
+
const direction = e.data.direction === "up" || e.data.direction === "down" ? e.data.direction : null;
|
|
19353
|
+
if (!instanceId || !direction) return;
|
|
19354
|
+
const entries = moveSectionInstance(instanceId, direction, window.location.pathname);
|
|
19355
|
+
if (!entries) return;
|
|
19356
|
+
const orderJson = JSON.stringify(entries);
|
|
19357
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
19358
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
19359
|
+
window.dispatchEvent(new Event("resize"));
|
|
19360
|
+
};
|
|
19361
|
+
window.addEventListener("message", handleMoveSection);
|
|
19362
|
+
const handleAiSetBrand = (e) => {
|
|
19363
|
+
if (e.data?.type !== "ow:ai-set-brand") return;
|
|
19364
|
+
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
19365
|
+
const previous = brandKitRef.current;
|
|
19366
|
+
brandKitRef.current = value;
|
|
19367
|
+
applyBrandToDom(parseBrandKit(value));
|
|
19368
|
+
if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
|
|
19369
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
19370
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
|
|
19371
|
+
postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
|
|
19372
|
+
};
|
|
19373
|
+
window.addEventListener("message", handleAiSetBrand);
|
|
19374
|
+
const handleAiSetStyles = (e) => {
|
|
19375
|
+
if (e.data?.type !== "ow:ai-set-styles") return;
|
|
19376
|
+
const value = typeof e.data.value === "string" ? e.data.value : "";
|
|
19377
|
+
const previous = stylesRef.current;
|
|
19378
|
+
stylesRef.current = value;
|
|
19379
|
+
applyStylesToDom(parseStyleStore(value));
|
|
19380
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
|
|
19381
|
+
postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
|
|
19382
|
+
};
|
|
19383
|
+
window.addEventListener("message", handleAiSetStyles);
|
|
19384
|
+
const handleGetBrand = (e) => {
|
|
19385
|
+
if (e.data?.type !== "ow:get-brand") return;
|
|
19386
|
+
const template = deriveTemplateBrand();
|
|
19387
|
+
const value = brandKitRef.current || (template ? JSON.stringify(template) : "");
|
|
19388
|
+
postToParentRef.current({ type: "ow:brand-value", value });
|
|
19389
|
+
};
|
|
19390
|
+
window.addEventListener("message", handleGetBrand);
|
|
18123
19391
|
const handlePanelDragging = (e) => {
|
|
18124
19392
|
if (e.data?.type !== "ow:panel-dragging") return;
|
|
18125
19393
|
if (e.data.dragging) document.documentElement.setAttribute("data-ohw-panel-dragging", "");
|
|
@@ -18135,8 +19403,15 @@ function OhhwellsBridge() {
|
|
|
18135
19403
|
closeLinkPopoverRef.current();
|
|
18136
19404
|
return;
|
|
18137
19405
|
}
|
|
19406
|
+
if (floatingPanelOpenRef.current) {
|
|
19407
|
+
setFloatingPanelRef.current(null);
|
|
19408
|
+
deselectRef.current();
|
|
19409
|
+
deactivateRef.current();
|
|
19410
|
+
return;
|
|
19411
|
+
}
|
|
18138
19412
|
deselectRef.current();
|
|
18139
19413
|
deactivateRef.current();
|
|
19414
|
+
clearMediaSelectionRef.current();
|
|
18140
19415
|
};
|
|
18141
19416
|
window.addEventListener("message", handleDeactivate);
|
|
18142
19417
|
const handleToastAction = (e) => {
|
|
@@ -18222,6 +19497,10 @@ function OhhwellsBridge() {
|
|
|
18222
19497
|
const handleKeyDown = (e) => {
|
|
18223
19498
|
if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
|
|
18224
19499
|
if (e.key === "Escape" && document.querySelector("[data-ohw-more-menu]")) return;
|
|
19500
|
+
if (e.key === "Escape" && selectedMediaElRef.current) {
|
|
19501
|
+
clearMediaSelectionRef.current();
|
|
19502
|
+
return;
|
|
19503
|
+
}
|
|
18225
19504
|
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
|
|
18226
19505
|
e.preventDefault();
|
|
18227
19506
|
selectAllTextInEditable(activeElRef.current);
|
|
@@ -18381,6 +19660,12 @@ function OhhwellsBridge() {
|
|
|
18381
19660
|
if (aiSectionsRef.current) {
|
|
18382
19661
|
nodes.push({ key: AI_SECTIONS_KEY, type: "sections", text: aiSectionsRef.current });
|
|
18383
19662
|
}
|
|
19663
|
+
if (stylesRef.current) {
|
|
19664
|
+
nodes.push({ key: STYLE_STORE_KEY, type: "styles", text: stylesRef.current });
|
|
19665
|
+
}
|
|
19666
|
+
if (brandKitRef.current) {
|
|
19667
|
+
nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
|
|
19668
|
+
}
|
|
18384
19669
|
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
18385
19670
|
const formKey = formKeyOf(form);
|
|
18386
19671
|
if (!formKey) return;
|
|
@@ -18398,8 +19683,12 @@ function OhhwellsBridge() {
|
|
|
18398
19683
|
if (inserted) {
|
|
18399
19684
|
const tracker = getSectionsTracker();
|
|
18400
19685
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
18401
|
-
const
|
|
18402
|
-
|
|
19686
|
+
const reportHeight = () => {
|
|
19687
|
+
const h = document.body.scrollHeight;
|
|
19688
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
19689
|
+
};
|
|
19690
|
+
reportHeight();
|
|
19691
|
+
setTimeout(reportHeight, 500);
|
|
18403
19692
|
}
|
|
18404
19693
|
};
|
|
18405
19694
|
const handleSwitchSchedule = (e) => {
|
|
@@ -18786,19 +20075,23 @@ function OhhwellsBridge() {
|
|
|
18786
20075
|
window.removeEventListener("message", handleAiApplyTree);
|
|
18787
20076
|
window.removeEventListener("message", handleAiDeleteSection);
|
|
18788
20077
|
window.removeEventListener("message", handleAiSetSections);
|
|
20078
|
+
window.removeEventListener("message", handleMoveSection);
|
|
20079
|
+
window.removeEventListener("message", handleAiSetBrand);
|
|
20080
|
+
window.removeEventListener("message", handleAiSetStyles);
|
|
20081
|
+
window.removeEventListener("message", handleGetBrand);
|
|
18789
20082
|
window.removeEventListener("message", handlePanelDragging);
|
|
18790
20083
|
window.removeEventListener("message", handleDeactivate);
|
|
18791
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
18792
20084
|
window.removeEventListener("message", handleToastAction);
|
|
18793
20085
|
window.removeEventListener("message", handleFormCount);
|
|
18794
20086
|
window.removeEventListener("message", handleUiEscape);
|
|
20087
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
18795
20088
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
18796
20089
|
autoSaveTimers.current.clear();
|
|
18797
20090
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
18798
20091
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
18799
20092
|
};
|
|
18800
20093
|
}, [isEditMode, refreshStateRules]);
|
|
18801
|
-
|
|
20094
|
+
useEffect13(() => {
|
|
18802
20095
|
if (!isEditMode) return;
|
|
18803
20096
|
const THRESHOLD = 10;
|
|
18804
20097
|
const resolveWasSelected = (el) => {
|
|
@@ -18954,7 +20247,7 @@ function OhhwellsBridge() {
|
|
|
18954
20247
|
unlockFooterDragInteraction();
|
|
18955
20248
|
};
|
|
18956
20249
|
}, [isEditMode]);
|
|
18957
|
-
|
|
20250
|
+
useEffect13(() => {
|
|
18958
20251
|
const handler = (e) => {
|
|
18959
20252
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
18960
20253
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -18970,7 +20263,7 @@ function OhhwellsBridge() {
|
|
|
18970
20263
|
window.addEventListener("message", handler);
|
|
18971
20264
|
return () => window.removeEventListener("message", handler);
|
|
18972
20265
|
}, [processConfigRequest]);
|
|
18973
|
-
|
|
20266
|
+
useEffect13(() => {
|
|
18974
20267
|
if (!isEditMode) return;
|
|
18975
20268
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
18976
20269
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -18994,7 +20287,7 @@ function OhhwellsBridge() {
|
|
|
18994
20287
|
postToParent2({
|
|
18995
20288
|
type: "ow:ready",
|
|
18996
20289
|
version: "1",
|
|
18997
|
-
bridgeVersion: "0.1.
|
|
20290
|
+
bridgeVersion: "0.1.69",
|
|
18998
20291
|
path: pathname,
|
|
18999
20292
|
nodes: collectEditableNodes(editContentRef.current),
|
|
19000
20293
|
sections
|
|
@@ -19006,13 +20299,13 @@ function OhhwellsBridge() {
|
|
|
19006
20299
|
clearTimeout(timer);
|
|
19007
20300
|
};
|
|
19008
20301
|
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
19009
|
-
|
|
20302
|
+
useEffect13(() => {
|
|
19010
20303
|
scrollToHashSectionWhenReady();
|
|
19011
20304
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
19012
20305
|
window.addEventListener("hashchange", onHashChange);
|
|
19013
20306
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
19014
20307
|
}, [pathname]);
|
|
19015
|
-
const handleCommand =
|
|
20308
|
+
const handleCommand = useCallback8((cmd) => {
|
|
19016
20309
|
const el = activeElRef.current;
|
|
19017
20310
|
const selBefore = window.getSelection();
|
|
19018
20311
|
let savedOffsets = null;
|
|
@@ -19048,7 +20341,7 @@ function OhhwellsBridge() {
|
|
|
19048
20341
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
19049
20342
|
refreshActiveCommandsRef.current();
|
|
19050
20343
|
}, []);
|
|
19051
|
-
|
|
20344
|
+
useEffect13(() => {
|
|
19052
20345
|
const session = floatingPanel && floatingPanel.kind === "logo-size" ? floatingPanel : null;
|
|
19053
20346
|
if (!session || !logoSizeDraft) return;
|
|
19054
20347
|
const onPanelAction = (e) => {
|
|
@@ -19086,7 +20379,7 @@ function OhhwellsBridge() {
|
|
|
19086
20379
|
window.addEventListener("message", onPanelAction);
|
|
19087
20380
|
return () => window.removeEventListener("message", onPanelAction);
|
|
19088
20381
|
}, [floatingPanel, logoSizeDraft, editorViewport, persistLogoSizeDraft, closeFloatingPanelAndDeselect]);
|
|
19089
|
-
const handleStateChange =
|
|
20382
|
+
const handleStateChange = useCallback8((state) => {
|
|
19090
20383
|
if (!activeStateElRef.current) return;
|
|
19091
20384
|
const el = activeStateElRef.current;
|
|
19092
20385
|
if (state === "Default") {
|
|
@@ -19099,7 +20392,7 @@ function OhhwellsBridge() {
|
|
|
19099
20392
|
}
|
|
19100
20393
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
19101
20394
|
}, [deactivate]);
|
|
19102
|
-
const reselectAfterLinkPopover =
|
|
20395
|
+
const reselectAfterLinkPopover = useCallback8(
|
|
19103
20396
|
(hrefKey) => {
|
|
19104
20397
|
requestAnimationFrame(() => {
|
|
19105
20398
|
const el = resolveHrefKeyElement(hrefKey);
|
|
@@ -19108,7 +20401,7 @@ function OhhwellsBridge() {
|
|
|
19108
20401
|
},
|
|
19109
20402
|
[resolveHrefKeyElement]
|
|
19110
20403
|
);
|
|
19111
|
-
const closeLinkPopover =
|
|
20404
|
+
const closeLinkPopover = useCallback8(() => {
|
|
19112
20405
|
const session = linkPopoverSessionRef.current;
|
|
19113
20406
|
addNavAfterAnchorRef.current = null;
|
|
19114
20407
|
setLinkPopover(null);
|
|
@@ -19116,9 +20409,9 @@ function OhhwellsBridge() {
|
|
|
19116
20409
|
reselectAfterLinkPopover(session.key);
|
|
19117
20410
|
}
|
|
19118
20411
|
}, [reselectAfterLinkPopover]);
|
|
19119
|
-
const closeLinkPopoverRef =
|
|
20412
|
+
const closeLinkPopoverRef = useRef10(closeLinkPopover);
|
|
19120
20413
|
closeLinkPopoverRef.current = closeLinkPopover;
|
|
19121
|
-
const openLinkPopoverForActive =
|
|
20414
|
+
const openLinkPopoverForActive = useCallback8(() => {
|
|
19122
20415
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
19123
20416
|
if (!hrefCtx) return;
|
|
19124
20417
|
bumpLinkPopoverGrace();
|
|
@@ -19129,7 +20422,7 @@ function OhhwellsBridge() {
|
|
|
19129
20422
|
});
|
|
19130
20423
|
deactivate();
|
|
19131
20424
|
}, [deactivate]);
|
|
19132
|
-
const openLinkPopoverForSelected =
|
|
20425
|
+
const openLinkPopoverForSelected = useCallback8(() => {
|
|
19133
20426
|
const anchor = selectedElRef.current;
|
|
19134
20427
|
if (!anchor) return;
|
|
19135
20428
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -19146,7 +20439,7 @@ function OhhwellsBridge() {
|
|
|
19146
20439
|
});
|
|
19147
20440
|
deselect();
|
|
19148
20441
|
}, [deselect]);
|
|
19149
|
-
const handleSelectParent =
|
|
20442
|
+
const handleSelectParent = useCallback8(() => {
|
|
19150
20443
|
const selected = selectedElRef.current;
|
|
19151
20444
|
if (!selected) return;
|
|
19152
20445
|
if (toolbarVariantRef.current === "select-frame") {
|
|
@@ -19173,7 +20466,7 @@ function OhhwellsBridge() {
|
|
|
19173
20466
|
}
|
|
19174
20467
|
deselectRef.current();
|
|
19175
20468
|
}, []);
|
|
19176
|
-
const handleDuplicateSelected =
|
|
20469
|
+
const handleDuplicateSelected = useCallback8(() => {
|
|
19177
20470
|
const selected = selectedElRef.current;
|
|
19178
20471
|
if (!selected || !isNavigationItem2(selected)) return;
|
|
19179
20472
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
@@ -19289,7 +20582,7 @@ function OhhwellsBridge() {
|
|
|
19289
20582
|
});
|
|
19290
20583
|
}
|
|
19291
20584
|
}, [postToParent2]);
|
|
19292
|
-
const runPendingDeleteUndo =
|
|
20585
|
+
const runPendingDeleteUndo = useCallback8(() => {
|
|
19293
20586
|
const pending = pendingDeleteUndoRef.current;
|
|
19294
20587
|
if (!pending) return false;
|
|
19295
20588
|
pendingDeleteUndoRef.current = null;
|
|
@@ -19297,7 +20590,7 @@ function OhhwellsBridge() {
|
|
|
19297
20590
|
enforceLinkHrefs();
|
|
19298
20591
|
return true;
|
|
19299
20592
|
}, []);
|
|
19300
|
-
const handleDeleteSelected =
|
|
20593
|
+
const handleDeleteSelected = useCallback8(() => {
|
|
19301
20594
|
const selected = selectedElRef.current;
|
|
19302
20595
|
if (!selected) return false;
|
|
19303
20596
|
return deleteSelectedNavFooterItem({
|
|
@@ -19318,7 +20611,7 @@ function OhhwellsBridge() {
|
|
|
19318
20611
|
}, [postToParent2]);
|
|
19319
20612
|
handleDeleteSelectedRef.current = handleDeleteSelected;
|
|
19320
20613
|
runPendingDeleteUndoRef.current = runPendingDeleteUndo;
|
|
19321
|
-
const handleLinkPopoverSubmit =
|
|
20614
|
+
const handleLinkPopoverSubmit = useCallback8(
|
|
19322
20615
|
(target) => {
|
|
19323
20616
|
const session = linkPopoverSessionRef.current;
|
|
19324
20617
|
if (!session) return;
|
|
@@ -19384,19 +20677,30 @@ function OhhwellsBridge() {
|
|
|
19384
20677
|
const showEditLink = toolbarShowEditLink;
|
|
19385
20678
|
const currentSections = sectionsByPath[pathname] ?? [];
|
|
19386
20679
|
linkPopoverOpenRef.current = linkPopover !== null;
|
|
19387
|
-
const
|
|
20680
|
+
const handleMediaSelect = useCallback8((key) => {
|
|
20681
|
+
const el = hoveredImageRef.current?.dataset.ohwKey === key ? hoveredImageRef.current : Array.from(document.querySelectorAll(MEDIA_SELECTOR)).find(
|
|
20682
|
+
(m) => (m.dataset.ohwKey ?? "") === key
|
|
20683
|
+
) ?? null;
|
|
20684
|
+
if (!el) return;
|
|
20685
|
+
selectMediaElementRef.current(el);
|
|
20686
|
+
}, []);
|
|
20687
|
+
const handleMediaReplace = useCallback8(
|
|
19388
20688
|
(key) => {
|
|
19389
|
-
postToParent2({
|
|
20689
|
+
postToParent2({
|
|
20690
|
+
type: "ow:image-pick",
|
|
20691
|
+
key,
|
|
20692
|
+
elementType: mediaHover?.elementType ?? selectedMedia?.elementType ?? "image"
|
|
20693
|
+
});
|
|
19390
20694
|
},
|
|
19391
|
-
[postToParent2, mediaHover?.elementType]
|
|
20695
|
+
[postToParent2, mediaHover?.elementType, selectedMedia?.elementType]
|
|
19392
20696
|
);
|
|
19393
|
-
const handleEditCarousel =
|
|
20697
|
+
const handleEditCarousel = useCallback8(
|
|
19394
20698
|
(key) => {
|
|
19395
20699
|
postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
|
|
19396
20700
|
},
|
|
19397
20701
|
[postToParent2]
|
|
19398
20702
|
);
|
|
19399
|
-
const handleMediaFadeOutComplete =
|
|
20703
|
+
const handleMediaFadeOutComplete = useCallback8((key) => {
|
|
19400
20704
|
setUploadingRects((prev) => {
|
|
19401
20705
|
if (!(key in prev)) return prev;
|
|
19402
20706
|
const next = { ...prev };
|
|
@@ -19404,7 +20708,7 @@ function OhhwellsBridge() {
|
|
|
19404
20708
|
return next;
|
|
19405
20709
|
});
|
|
19406
20710
|
}, []);
|
|
19407
|
-
const handleVideoSettingsChange =
|
|
20711
|
+
const handleVideoSettingsChange = useCallback8(
|
|
19408
20712
|
(key, settings) => {
|
|
19409
20713
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
19410
20714
|
const video = getVideoEl2(el);
|
|
@@ -19426,420 +20730,506 @@ function OhhwellsBridge() {
|
|
|
19426
20730
|
},
|
|
19427
20731
|
[postToParent2]
|
|
19428
20732
|
);
|
|
19429
|
-
return
|
|
19430
|
-
/* @__PURE__ */
|
|
19431
|
-
|
|
19432
|
-
|
|
19433
|
-
|
|
19434
|
-
|
|
19435
|
-
{
|
|
19436
|
-
|
|
19437
|
-
|
|
19438
|
-
|
|
19439
|
-
|
|
19440
|
-
|
|
19441
|
-
|
|
19442
|
-
|
|
19443
|
-
|
|
19444
|
-
|
|
19445
|
-
|
|
19446
|
-
|
|
19447
|
-
|
|
19448
|
-
|
|
19449
|
-
onReplace: handleMediaReplace,
|
|
19450
|
-
onVideoSettingsChange: handleVideoSettingsChange
|
|
19451
|
-
}
|
|
19452
|
-
),
|
|
19453
|
-
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
|
|
19454
|
-
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
19455
|
-
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
19456
|
-
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
19457
|
-
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
19458
|
-
"div",
|
|
19459
|
-
{
|
|
19460
|
-
className: "pointer-events-none fixed z-2147483646",
|
|
19461
|
-
style: {
|
|
19462
|
-
left: slot.left,
|
|
19463
|
-
top: slot.top,
|
|
19464
|
-
width: slot.width,
|
|
19465
|
-
height: slot.height
|
|
20733
|
+
return /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
20734
|
+
/* @__PURE__ */ jsx33("div", { id: "ohw-loader", suppressHydrationWarning: true, style: { ...OHW_LOADER_STYLE, display: "none" }, children: /* @__PURE__ */ jsx33(OhwLoaderSpinner, {}) }),
|
|
20735
|
+
/* @__PURE__ */ jsx33("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: OHW_LOADER_PREHYDRATE_SCRIPT } }),
|
|
20736
|
+
bridgeRoot ? createPortal2(
|
|
20737
|
+
/* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
20738
|
+
/* @__PURE__ */ jsx33("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
20739
|
+
isEditMode && /* @__PURE__ */ jsx33(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
|
|
20740
|
+
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
20741
|
+
"div",
|
|
20742
|
+
{
|
|
20743
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
20744
|
+
style: { left: slot.left, top: slot.y, width: slot.width, height: 3, transform: "translateY(-50%)" },
|
|
20745
|
+
children: /* @__PURE__ */ jsx33(
|
|
20746
|
+
DropIndicator,
|
|
20747
|
+
{
|
|
20748
|
+
direction: "horizontal",
|
|
20749
|
+
state: activeSectionDropIndex === i ? "dragActive" : "dragIdle",
|
|
20750
|
+
className: "!h-full !w-full"
|
|
20751
|
+
}
|
|
20752
|
+
)
|
|
19466
20753
|
},
|
|
19467
|
-
|
|
19468
|
-
|
|
19469
|
-
|
|
19470
|
-
|
|
19471
|
-
|
|
19472
|
-
|
|
19473
|
-
|
|
19474
|
-
|
|
19475
|
-
|
|
19476
|
-
|
|
19477
|
-
)),
|
|
19478
|
-
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
19479
|
-
"div",
|
|
19480
|
-
{
|
|
19481
|
-
className: "pointer-events-none fixed z-2147483646",
|
|
19482
|
-
style: {
|
|
19483
|
-
left: slot.left,
|
|
19484
|
-
top: slot.top,
|
|
19485
|
-
width: slot.width,
|
|
19486
|
-
height: slot.height
|
|
20754
|
+
`section-drop-${slot.insertIndex}-${i}`
|
|
20755
|
+
)),
|
|
20756
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx33(
|
|
20757
|
+
MediaOverlay,
|
|
20758
|
+
{
|
|
20759
|
+
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
20760
|
+
isUploading: true,
|
|
20761
|
+
fadingOut,
|
|
20762
|
+
onFadeOutComplete: handleMediaFadeOutComplete,
|
|
20763
|
+
onReplace: handleMediaReplace
|
|
19487
20764
|
},
|
|
19488
|
-
|
|
19489
|
-
|
|
19490
|
-
|
|
19491
|
-
|
|
19492
|
-
|
|
19493
|
-
|
|
19494
|
-
|
|
19495
|
-
|
|
19496
|
-
|
|
19497
|
-
|
|
19498
|
-
|
|
19499
|
-
|
|
19500
|
-
|
|
19501
|
-
|
|
19502
|
-
|
|
19503
|
-
|
|
19504
|
-
|
|
19505
|
-
|
|
19506
|
-
|
|
19507
|
-
|
|
19508
|
-
|
|
19509
|
-
|
|
19510
|
-
|
|
20765
|
+
`uploading-${key}`
|
|
20766
|
+
)),
|
|
20767
|
+
mediaHover && !(mediaHover.key in uploadingRects) && mediaHover.key !== selectedMedia?.key && /* @__PURE__ */ jsx33(
|
|
20768
|
+
MediaOverlay,
|
|
20769
|
+
{
|
|
20770
|
+
hover: mediaHover,
|
|
20771
|
+
isUploading: false,
|
|
20772
|
+
onReplace: handleMediaReplace,
|
|
20773
|
+
onSelect: handleMediaSelect,
|
|
20774
|
+
onVideoSettingsChange: handleVideoSettingsChange
|
|
20775
|
+
}
|
|
20776
|
+
),
|
|
20777
|
+
selectedMedia && !(selectedMedia.key in uploadingRects) && !linkPopover && /* @__PURE__ */ jsx33(
|
|
20778
|
+
MediaOverlay,
|
|
20779
|
+
{
|
|
20780
|
+
hover: selectedMedia,
|
|
20781
|
+
selected: true,
|
|
20782
|
+
hovered: mediaHover?.key === selectedMedia.key,
|
|
20783
|
+
isUploading: false,
|
|
20784
|
+
onReplace: handleMediaReplace,
|
|
20785
|
+
onSelect: handleMediaSelect,
|
|
20786
|
+
onVideoSettingsChange: handleVideoSettingsChange
|
|
20787
|
+
}
|
|
20788
|
+
),
|
|
20789
|
+
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
|
|
20790
|
+
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
20791
|
+
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
20792
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
20793
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
20794
|
+
"div",
|
|
20795
|
+
{
|
|
20796
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
20797
|
+
style: {
|
|
20798
|
+
left: slot.left,
|
|
20799
|
+
top: slot.top,
|
|
20800
|
+
width: slot.width,
|
|
20801
|
+
height: slot.height
|
|
20802
|
+
},
|
|
20803
|
+
children: /* @__PURE__ */ jsx33(
|
|
20804
|
+
DropIndicator,
|
|
20805
|
+
{
|
|
20806
|
+
direction: slot.direction,
|
|
20807
|
+
state: activeFooterDropIndex === i ? "dragActive" : "dragIdle",
|
|
20808
|
+
className: "!h-full !w-full"
|
|
20809
|
+
}
|
|
20810
|
+
)
|
|
20811
|
+
},
|
|
20812
|
+
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
20813
|
+
)),
|
|
20814
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
20815
|
+
"div",
|
|
20816
|
+
{
|
|
20817
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
20818
|
+
style: {
|
|
20819
|
+
left: slot.left,
|
|
20820
|
+
top: slot.top,
|
|
20821
|
+
width: slot.width,
|
|
20822
|
+
height: slot.height
|
|
20823
|
+
},
|
|
20824
|
+
children: /* @__PURE__ */ jsx33(
|
|
20825
|
+
DropIndicator,
|
|
20826
|
+
{
|
|
20827
|
+
direction: slot.direction,
|
|
20828
|
+
state: activeNavDropIndex === i ? "dragActive" : "dragIdle",
|
|
20829
|
+
className: "!h-full !w-full"
|
|
20830
|
+
}
|
|
20831
|
+
)
|
|
20832
|
+
},
|
|
20833
|
+
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
20834
|
+
)),
|
|
20835
|
+
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
20836
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
20837
|
+
hoveredTextRect && !hoveredNavContainerRect && !hoveredItemRect && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: hoveredTextRect, state: "hover" }),
|
|
20838
|
+
formPickRect && !isItemDragging && /* @__PURE__ */ jsx33(
|
|
20839
|
+
ItemInteractionLayer,
|
|
20840
|
+
{
|
|
20841
|
+
rect: formPickRect,
|
|
20842
|
+
state: "active-top",
|
|
20843
|
+
itemDragSurface: false,
|
|
20844
|
+
toolbarAlign: "left",
|
|
20845
|
+
chromeGap: 24,
|
|
20846
|
+
toolbar: fieldPickRect ? void 0 : /* @__PURE__ */ jsxs20(
|
|
20847
|
+
"div",
|
|
20848
|
+
{
|
|
20849
|
+
"data-ohw-form-toolbar": "",
|
|
20850
|
+
className: "pointer-events-auto flex items-center gap-0.5 whitespace-nowrap rounded-lg border border-border bg-background p-1 shadow-md",
|
|
20851
|
+
children: [
|
|
20852
|
+
/* @__PURE__ */ jsx33(
|
|
20853
|
+
"button",
|
|
20854
|
+
{
|
|
20855
|
+
type: "button",
|
|
20856
|
+
"aria-label": "Add field",
|
|
20857
|
+
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
20858
|
+
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
20859
|
+
"data-ohw-add-field": "",
|
|
20860
|
+
children: /* @__PURE__ */ jsx33(Plus4, { size: 15, "aria-hidden": true })
|
|
20861
|
+
}
|
|
20862
|
+
),
|
|
20863
|
+
/* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
20864
|
+
/* @__PURE__ */ jsxs20(
|
|
20865
|
+
"button",
|
|
20866
|
+
{
|
|
20867
|
+
type: "button",
|
|
20868
|
+
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",
|
|
20869
|
+
onClick: () => {
|
|
20870
|
+
const form = formPickElRef.current;
|
|
20871
|
+
if (!form) return;
|
|
20872
|
+
postToParent2({
|
|
20873
|
+
type: "ow:form-pick",
|
|
20874
|
+
formKey: formKeyOf(form),
|
|
20875
|
+
hasLongText: formHasLongText(form)
|
|
20876
|
+
});
|
|
20877
|
+
},
|
|
20878
|
+
children: [
|
|
20879
|
+
/* @__PURE__ */ jsx33(Settings, { size: 14, "aria-hidden": true }),
|
|
20880
|
+
"Form settings",
|
|
20881
|
+
formPickCount ? (
|
|
20882
|
+
// Counter pill, per the design — not a text suffix.
|
|
20883
|
+
/* @__PURE__ */ jsx33(
|
|
20884
|
+
"span",
|
|
20885
|
+
{
|
|
20886
|
+
"data-ohw-form-count": "",
|
|
20887
|
+
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",
|
|
20888
|
+
children: formPickCount
|
|
20889
|
+
}
|
|
20890
|
+
)
|
|
20891
|
+
) : null
|
|
20892
|
+
]
|
|
20893
|
+
}
|
|
20894
|
+
),
|
|
20895
|
+
/* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
20896
|
+
/* @__PURE__ */ jsx33("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ jsx33(
|
|
20897
|
+
"button",
|
|
20898
|
+
{
|
|
20899
|
+
type: "button",
|
|
20900
|
+
"aria-pressed": formViewState === state,
|
|
20901
|
+
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"),
|
|
20902
|
+
onClick: () => {
|
|
20903
|
+
const form = formPickElRef.current;
|
|
20904
|
+
const key = form ? formKeyOf(form) : null;
|
|
20905
|
+
if (!form || !key) return;
|
|
20906
|
+
const initial = successInitialFor(form, key, editContentRef.current);
|
|
20907
|
+
setFormViewState(form, key, state, initial);
|
|
20908
|
+
setFormViewStateUi(state);
|
|
20909
|
+
setFormPickRect(form.getBoundingClientRect());
|
|
20910
|
+
if (state === "success") {
|
|
20911
|
+
const successEl = form.querySelector(`[${SUCCESS_TEXT_ATTR}]`);
|
|
20912
|
+
if (successEl) requestAnimationFrame(() => activateRef.current(successEl));
|
|
20913
|
+
} else {
|
|
20914
|
+
deactivateRef.current();
|
|
20915
|
+
}
|
|
20916
|
+
},
|
|
20917
|
+
children: state
|
|
20918
|
+
},
|
|
20919
|
+
state
|
|
20920
|
+
)) })
|
|
20921
|
+
]
|
|
20922
|
+
}
|
|
20923
|
+
)
|
|
20924
|
+
}
|
|
20925
|
+
),
|
|
20926
|
+
formHoverRect && !isItemDragging && /* @__PURE__ */ jsx33(
|
|
20927
|
+
ItemInteractionLayer,
|
|
20928
|
+
{
|
|
20929
|
+
rect: formHoverRect,
|
|
20930
|
+
state: "hover",
|
|
20931
|
+
chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
|
|
20932
|
+
}
|
|
20933
|
+
),
|
|
20934
|
+
fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ jsx33(
|
|
20935
|
+
ItemInteractionLayer,
|
|
20936
|
+
{
|
|
20937
|
+
rect: fieldPickRect,
|
|
20938
|
+
state: fieldDragging ? "dragging" : "active-top",
|
|
20939
|
+
itemDragSurface: false,
|
|
20940
|
+
toolbarAlign: "left",
|
|
20941
|
+
chromeGap: 10,
|
|
20942
|
+
showHandle: true,
|
|
20943
|
+
dragHandleLabel: "Reorder field",
|
|
20944
|
+
onDragHandleDragStart: handleFieldDragStart,
|
|
20945
|
+
onDragHandleDragEnd: handleFieldDragEnd,
|
|
20946
|
+
toolbar: /* @__PURE__ */ jsx33(
|
|
20947
|
+
FormFieldToolbar,
|
|
20948
|
+
{
|
|
20949
|
+
type: fieldPickState.type,
|
|
20950
|
+
required: fieldPickState.required,
|
|
20951
|
+
onTypeChange: handleFieldTypeChange,
|
|
20952
|
+
onRequiredToggle: handleFieldRequiredToggle,
|
|
20953
|
+
onDuplicate: handleFieldDuplicate,
|
|
20954
|
+
onDelete: handleFieldDelete
|
|
20955
|
+
}
|
|
20956
|
+
)
|
|
20957
|
+
}
|
|
20958
|
+
),
|
|
20959
|
+
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
20960
|
+
"div",
|
|
20961
|
+
{
|
|
20962
|
+
className: "pointer-events-none fixed z-[2147483644]",
|
|
20963
|
+
style: { top: slot.top, left: slot.left, width: slot.width },
|
|
20964
|
+
children: /* @__PURE__ */ jsx33(
|
|
20965
|
+
DropIndicator,
|
|
20966
|
+
{
|
|
20967
|
+
direction: "horizontal",
|
|
20968
|
+
state: fieldDropIndex === i ? "dragActive" : "dragIdle",
|
|
20969
|
+
className: "!w-full"
|
|
20970
|
+
}
|
|
20971
|
+
)
|
|
20972
|
+
},
|
|
20973
|
+
`field-drop-${i}`
|
|
20974
|
+
)) : null,
|
|
20975
|
+
fieldTypePickerOpen && formPickRect ? (() => {
|
|
20976
|
+
const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
|
|
20977
|
+
return /* @__PURE__ */ jsx33(
|
|
19511
20978
|
"div",
|
|
19512
20979
|
{
|
|
19513
|
-
"
|
|
19514
|
-
|
|
19515
|
-
|
|
19516
|
-
|
|
19517
|
-
|
|
19518
|
-
|
|
19519
|
-
type: "button",
|
|
19520
|
-
"aria-label": "Add field",
|
|
19521
|
-
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
19522
|
-
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
19523
|
-
"data-ohw-add-field": "",
|
|
19524
|
-
children: /* @__PURE__ */ jsx33(Plus4, { size: 15, "aria-hidden": true })
|
|
19525
|
-
}
|
|
19526
|
-
),
|
|
19527
|
-
/* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
19528
|
-
/* @__PURE__ */ jsxs20(
|
|
19529
|
-
"button",
|
|
19530
|
-
{
|
|
19531
|
-
type: "button",
|
|
19532
|
-
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",
|
|
19533
|
-
onClick: () => {
|
|
19534
|
-
const form = formPickElRef.current;
|
|
19535
|
-
if (!form) return;
|
|
19536
|
-
postToParent2({
|
|
19537
|
-
type: "ow:form-pick",
|
|
19538
|
-
formKey: formKeyOf(form),
|
|
19539
|
-
hasLongText: formHasLongText(form)
|
|
19540
|
-
});
|
|
19541
|
-
},
|
|
19542
|
-
children: [
|
|
19543
|
-
/* @__PURE__ */ jsx33(Settings, { size: 14, "aria-hidden": true }),
|
|
19544
|
-
"Form settings",
|
|
19545
|
-
formPickCount ? (
|
|
19546
|
-
// Counter pill, per the design — not a text suffix.
|
|
19547
|
-
/* @__PURE__ */ jsx33(
|
|
19548
|
-
"span",
|
|
19549
|
-
{
|
|
19550
|
-
"data-ohw-form-count": "",
|
|
19551
|
-
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",
|
|
19552
|
-
children: formPickCount
|
|
19553
|
-
}
|
|
19554
|
-
)
|
|
19555
|
-
) : null
|
|
19556
|
-
]
|
|
19557
|
-
}
|
|
19558
|
-
),
|
|
19559
|
-
/* @__PURE__ */ jsx33("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|
|
19560
|
-
/* @__PURE__ */ jsx33("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ jsx33(
|
|
19561
|
-
"button",
|
|
19562
|
-
{
|
|
19563
|
-
type: "button",
|
|
19564
|
-
"aria-pressed": formViewState === state,
|
|
19565
|
-
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"),
|
|
19566
|
-
onClick: () => {
|
|
19567
|
-
const form = formPickElRef.current;
|
|
19568
|
-
const key = form ? formKeyOf(form) : null;
|
|
19569
|
-
if (!form || !key) return;
|
|
19570
|
-
const initial = successInitialFor(form, key, editContentRef.current);
|
|
19571
|
-
setFormViewState(form, key, state, initial);
|
|
19572
|
-
setFormViewStateUi(state);
|
|
19573
|
-
setFormPickRect(form.getBoundingClientRect());
|
|
19574
|
-
if (state === "success") {
|
|
19575
|
-
const successEl = form.querySelector(`[${SUCCESS_TEXT_ATTR}]`);
|
|
19576
|
-
if (successEl) requestAnimationFrame(() => activateRef.current(successEl));
|
|
19577
|
-
} else {
|
|
19578
|
-
deactivateRef.current();
|
|
19579
|
-
}
|
|
19580
|
-
},
|
|
19581
|
-
children: state
|
|
19582
|
-
},
|
|
19583
|
-
state
|
|
19584
|
-
)) })
|
|
19585
|
-
]
|
|
20980
|
+
className: "pointer-events-none fixed z-[2147483645]",
|
|
20981
|
+
style: {
|
|
20982
|
+
top: toolbar ? toolbar.bottom + 6 : formPickRect.top + 16,
|
|
20983
|
+
left: toolbar ? toolbar.left : formPickRect.left + 24
|
|
20984
|
+
},
|
|
20985
|
+
children: /* @__PURE__ */ jsx33(FieldTypePicker, { onPick: handleAddField })
|
|
19586
20986
|
}
|
|
19587
|
-
)
|
|
19588
|
-
}
|
|
19589
|
-
|
|
19590
|
-
|
|
19591
|
-
|
|
19592
|
-
|
|
19593
|
-
|
|
19594
|
-
|
|
19595
|
-
|
|
19596
|
-
|
|
19597
|
-
|
|
19598
|
-
|
|
19599
|
-
|
|
19600
|
-
|
|
19601
|
-
|
|
19602
|
-
|
|
19603
|
-
|
|
19604
|
-
|
|
19605
|
-
|
|
19606
|
-
|
|
19607
|
-
|
|
19608
|
-
|
|
19609
|
-
|
|
19610
|
-
|
|
19611
|
-
|
|
20987
|
+
);
|
|
20988
|
+
})() : null,
|
|
20989
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ jsx33(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
20990
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx33(
|
|
20991
|
+
FooterContainerChrome,
|
|
20992
|
+
{
|
|
20993
|
+
rect: toolbarRect,
|
|
20994
|
+
onAdd: handleAddFooterColumn,
|
|
20995
|
+
addDisabled: !canAddFooterColumn()
|
|
20996
|
+
}
|
|
20997
|
+
),
|
|
20998
|
+
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ jsx33(
|
|
20999
|
+
ItemInteractionLayer,
|
|
21000
|
+
{
|
|
21001
|
+
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
21002
|
+
toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
|
|
21003
|
+
elRef: glowElRef,
|
|
21004
|
+
state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanelRect(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
21005
|
+
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
21006
|
+
dragDisabled: reorderDragDisabled,
|
|
21007
|
+
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
21008
|
+
onDragHandleDragStart: handleItemDragStart,
|
|
21009
|
+
onDragHandleDragEnd: handleItemDragEnd,
|
|
21010
|
+
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
21011
|
+
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
21012
|
+
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
|
|
21013
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ jsx33(
|
|
21014
|
+
ItemActionToolbar,
|
|
21015
|
+
{
|
|
21016
|
+
onEditLink: openLinkPopoverForSelected,
|
|
21017
|
+
onStyle: () => {
|
|
21018
|
+
const row = selectedElRef.current;
|
|
21019
|
+
if (!row) return;
|
|
21020
|
+
if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
|
|
21021
|
+
else openSocialsDisplayPanel(row);
|
|
21022
|
+
},
|
|
21023
|
+
showStyle: selectedIsSocialsRow,
|
|
21024
|
+
styleActive: floatingPanel?.kind === "socials-display",
|
|
21025
|
+
onAddItem: handleAddChildItem,
|
|
21026
|
+
onSelectParent: handleSelectParent,
|
|
21027
|
+
onDuplicate: handleDuplicateSelected,
|
|
21028
|
+
onDelete: handleDeleteSelected,
|
|
21029
|
+
addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
21030
|
+
const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
|
|
21031
|
+
return row ? !canAddSocialItem(row) : false;
|
|
21032
|
+
})(),
|
|
21033
|
+
editLinkDisabled: false,
|
|
21034
|
+
moreDisabled: false,
|
|
21035
|
+
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
|
|
21036
|
+
showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
|
|
21037
|
+
showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
|
|
21038
|
+
selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
|
|
21039
|
+
),
|
|
21040
|
+
showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
|
|
21041
|
+
dropdownOpen: navDropdownPreviewOpen,
|
|
21042
|
+
onDropdownOpenChange: handleNavDropdownOpenChange,
|
|
21043
|
+
headingVisible: footerHeadingVisible,
|
|
21044
|
+
onHeadingVisibleChange: handleFooterHeadingVisibleChange
|
|
21045
|
+
}
|
|
21046
|
+
) : void 0
|
|
21047
|
+
}
|
|
21048
|
+
),
|
|
21049
|
+
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
21050
|
+
/* @__PURE__ */ jsx33(
|
|
21051
|
+
EditGlowChrome,
|
|
19612
21052
|
{
|
|
19613
|
-
|
|
19614
|
-
|
|
19615
|
-
|
|
19616
|
-
|
|
19617
|
-
|
|
19618
|
-
onDelete: handleFieldDelete
|
|
21053
|
+
rect: toolbarRect,
|
|
21054
|
+
elRef: glowElRef,
|
|
21055
|
+
reorderHrefKey,
|
|
21056
|
+
dragDisabled: reorderDragDisabled,
|
|
21057
|
+
hideHandle: isItemDragging
|
|
19619
21058
|
}
|
|
19620
|
-
)
|
|
19621
|
-
|
|
19622
|
-
|
|
19623
|
-
fieldDragging ? fieldDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
19624
|
-
"div",
|
|
19625
|
-
{
|
|
19626
|
-
className: "pointer-events-none fixed z-[2147483644]",
|
|
19627
|
-
style: { top: slot.top, left: slot.left, width: slot.width },
|
|
19628
|
-
children: /* @__PURE__ */ jsx33(
|
|
19629
|
-
DropIndicator,
|
|
21059
|
+
),
|
|
21060
|
+
/* @__PURE__ */ jsx33(
|
|
21061
|
+
FloatingToolbar,
|
|
19630
21062
|
{
|
|
19631
|
-
|
|
19632
|
-
|
|
19633
|
-
|
|
21063
|
+
rect: toolbarRect,
|
|
21064
|
+
parentScroll: parentScrollRef.current,
|
|
21065
|
+
elRef: toolbarElRef,
|
|
21066
|
+
onCommand: handleCommand,
|
|
21067
|
+
activeCommands,
|
|
21068
|
+
showEditLink,
|
|
21069
|
+
onEditLink: openLinkPopoverForActive
|
|
19634
21070
|
}
|
|
19635
21071
|
)
|
|
19636
|
-
},
|
|
19637
|
-
|
|
19638
|
-
)) : null,
|
|
19639
|
-
fieldTypePickerOpen && formPickRect ? (() => {
|
|
19640
|
-
const toolbar = document.querySelector("[data-ohw-form-toolbar]")?.getBoundingClientRect();
|
|
19641
|
-
return /* @__PURE__ */ jsx33(
|
|
21072
|
+
] }),
|
|
21073
|
+
maxBadge && /* @__PURE__ */ jsxs20(
|
|
19642
21074
|
"div",
|
|
19643
21075
|
{
|
|
19644
|
-
|
|
21076
|
+
"data-ohw-max-badge": "",
|
|
19645
21077
|
style: {
|
|
19646
|
-
|
|
19647
|
-
|
|
21078
|
+
position: "fixed",
|
|
21079
|
+
top: maxBadge.rect.bottom + 4,
|
|
21080
|
+
left: maxBadge.rect.right,
|
|
21081
|
+
transform: "translateX(-100%)",
|
|
21082
|
+
zIndex: 2147483647,
|
|
21083
|
+
background: maxBadge.current > maxBadge.max ? "#FEF2F2" : "#F5F5F4",
|
|
21084
|
+
color: maxBadge.current > maxBadge.max ? "#DC2626" : "#78716C",
|
|
21085
|
+
border: `1px solid ${maxBadge.current > maxBadge.max ? "#FECACA" : "#E7E5E4"}`,
|
|
21086
|
+
borderRadius: 4,
|
|
21087
|
+
padding: "2px 6px",
|
|
21088
|
+
fontSize: 11,
|
|
21089
|
+
fontWeight: 500,
|
|
21090
|
+
pointerEvents: "none"
|
|
19648
21091
|
},
|
|
19649
|
-
children:
|
|
21092
|
+
children: [
|
|
21093
|
+
maxBadge.current,
|
|
21094
|
+
"/",
|
|
21095
|
+
maxBadge.max
|
|
21096
|
+
]
|
|
19650
21097
|
}
|
|
19651
|
-
)
|
|
19652
|
-
|
|
19653
|
-
|
|
19654
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx33(
|
|
19655
|
-
FooterContainerChrome,
|
|
19656
|
-
{
|
|
19657
|
-
rect: toolbarRect,
|
|
19658
|
-
onAdd: handleAddFooterColumn,
|
|
19659
|
-
addDisabled: !canAddFooterColumn()
|
|
19660
|
-
}
|
|
19661
|
-
),
|
|
19662
|
-
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ jsx33(
|
|
19663
|
-
ItemInteractionLayer,
|
|
19664
|
-
{
|
|
19665
|
-
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
19666
|
-
toolbarBelowRect: selectedElRef.current && isNavigationItem2(selectedElRef.current) ? getOpenNavDropdownPanelRect(selectedElRef.current) : null,
|
|
19667
|
-
elRef: glowElRef,
|
|
19668
|
-
state: isItemDragging ? "dragging" : selectedElRef.current && isNavigationItem2(selectedElRef.current) && getOpenNavDropdownPanelRect(selectedElRef.current) ? "active-bottom" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
19669
|
-
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
19670
|
-
dragDisabled: reorderDragDisabled,
|
|
19671
|
-
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
19672
|
-
onDragHandleDragStart: handleItemDragStart,
|
|
19673
|
-
onDragHandleDragEnd: handleItemDragEnd,
|
|
19674
|
-
onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
|
|
19675
|
-
onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
|
|
19676
|
-
itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
|
|
19677
|
-
toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ jsx33(
|
|
19678
|
-
ItemActionToolbar,
|
|
19679
|
-
{
|
|
19680
|
-
onEditLink: openLinkPopoverForSelected,
|
|
19681
|
-
onStyle: () => {
|
|
19682
|
-
const row = selectedElRef.current;
|
|
19683
|
-
if (!row) return;
|
|
19684
|
-
if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
|
|
19685
|
-
else openSocialsDisplayPanel(row);
|
|
19686
|
-
},
|
|
19687
|
-
showStyle: selectedIsSocialsRow,
|
|
19688
|
-
styleActive: floatingPanel?.kind === "socials-display",
|
|
19689
|
-
onAddItem: handleAddChildItem,
|
|
19690
|
-
onSelectParent: handleSelectParent,
|
|
19691
|
-
onDuplicate: handleDuplicateSelected,
|
|
19692
|
-
onDelete: handleDeleteSelected,
|
|
19693
|
-
addItemDisabled: isFooterFrameSelection && isFooterAddItemDisabled(selectedElRef.current) || selectedElRef.current !== null && (() => {
|
|
19694
|
-
const row = isSocialsRow(selectedElRef.current) ? selectedElRef.current : findSocialsRow(selectedElRef.current);
|
|
19695
|
-
return row ? !canAddSocialItem(row) : false;
|
|
19696
|
-
})(),
|
|
19697
|
-
editLinkDisabled: false,
|
|
19698
|
-
moreDisabled: false,
|
|
19699
|
-
duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
|
|
19700
|
-
showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
|
|
19701
|
-
showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
|
|
19702
|
-
selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
|
|
19703
|
-
),
|
|
19704
|
-
showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
|
|
19705
|
-
dropdownOpen: navDropdownPreviewOpen,
|
|
19706
|
-
onDropdownOpenChange: handleNavDropdownOpenChange,
|
|
19707
|
-
headingVisible: footerHeadingVisible,
|
|
19708
|
-
onHeadingVisibleChange: handleFooterHeadingVisibleChange
|
|
19709
|
-
}
|
|
19710
|
-
) : void 0
|
|
19711
|
-
}
|
|
19712
|
-
),
|
|
19713
|
-
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
19714
|
-
/* @__PURE__ */ jsx33(
|
|
19715
|
-
EditGlowChrome,
|
|
21098
|
+
),
|
|
21099
|
+
toggleState && !linkPopover && /* @__PURE__ */ jsx33(
|
|
21100
|
+
StateToggle,
|
|
19716
21101
|
{
|
|
19717
|
-
rect:
|
|
19718
|
-
|
|
19719
|
-
|
|
19720
|
-
|
|
19721
|
-
hideHandle: isItemDragging
|
|
21102
|
+
rect: toggleState.rect,
|
|
21103
|
+
activeState: toggleState.activeState,
|
|
21104
|
+
states: toggleState.states,
|
|
21105
|
+
onStateChange: handleStateChange
|
|
19722
21106
|
}
|
|
19723
21107
|
),
|
|
19724
|
-
/* @__PURE__ */
|
|
19725
|
-
|
|
21108
|
+
sectionGap && !linkPopover && /* @__PURE__ */ jsxs20(
|
|
21109
|
+
"div",
|
|
19726
21110
|
{
|
|
19727
|
-
|
|
19728
|
-
|
|
19729
|
-
|
|
19730
|
-
|
|
19731
|
-
|
|
19732
|
-
|
|
19733
|
-
|
|
21111
|
+
"data-ohw-section-insert-line": "",
|
|
21112
|
+
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
21113
|
+
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
21114
|
+
children: [
|
|
21115
|
+
/* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
21116
|
+
/* @__PURE__ */ jsx33(
|
|
21117
|
+
Badge,
|
|
21118
|
+
{
|
|
21119
|
+
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",
|
|
21120
|
+
onClick: () => {
|
|
21121
|
+
window.parent.postMessage(
|
|
21122
|
+
{
|
|
21123
|
+
type: "ow:add-section",
|
|
21124
|
+
insertAfter: sectionGap.insertAfter,
|
|
21125
|
+
insertBefore: sectionGap.insertBefore
|
|
21126
|
+
},
|
|
21127
|
+
"*"
|
|
21128
|
+
);
|
|
21129
|
+
},
|
|
21130
|
+
children: "Add Section"
|
|
21131
|
+
}
|
|
21132
|
+
),
|
|
21133
|
+
/* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
21134
|
+
]
|
|
19734
21135
|
}
|
|
19735
|
-
)
|
|
19736
|
-
|
|
19737
|
-
|
|
19738
|
-
|
|
19739
|
-
|
|
19740
|
-
|
|
19741
|
-
|
|
19742
|
-
|
|
19743
|
-
|
|
19744
|
-
|
|
19745
|
-
|
|
19746
|
-
|
|
19747
|
-
|
|
19748
|
-
|
|
19749
|
-
|
|
19750
|
-
borderRadius: 4,
|
|
19751
|
-
padding: "2px 6px",
|
|
19752
|
-
fontSize: 11,
|
|
19753
|
-
fontWeight: 500,
|
|
19754
|
-
pointerEvents: "none"
|
|
21136
|
+
),
|
|
21137
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx33(
|
|
21138
|
+
LinkPopover,
|
|
21139
|
+
{
|
|
21140
|
+
panelRef: linkPopoverPanelRef,
|
|
21141
|
+
portalContainer: dialogPortalContainer,
|
|
21142
|
+
open: true,
|
|
21143
|
+
mode: linkPopover.mode ?? "edit",
|
|
21144
|
+
pages: sitePages,
|
|
21145
|
+
sections: currentSections,
|
|
21146
|
+
sectionsByPath,
|
|
21147
|
+
initialTarget: linkPopover.target,
|
|
21148
|
+
existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
|
|
21149
|
+
onClose: closeLinkPopover,
|
|
21150
|
+
onSubmit: handleLinkPopoverSubmit
|
|
19755
21151
|
},
|
|
19756
|
-
|
|
19757
|
-
|
|
19758
|
-
|
|
19759
|
-
|
|
19760
|
-
|
|
19761
|
-
|
|
19762
|
-
|
|
19763
|
-
|
|
19764
|
-
|
|
19765
|
-
|
|
19766
|
-
|
|
19767
|
-
|
|
19768
|
-
|
|
19769
|
-
|
|
19770
|
-
}
|
|
19771
|
-
),
|
|
19772
|
-
sectionGap && !linkPopover && /* @__PURE__ */ jsxs20(
|
|
19773
|
-
"div",
|
|
19774
|
-
{
|
|
19775
|
-
"data-ohw-section-insert-line": "",
|
|
19776
|
-
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
19777
|
-
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
19778
|
-
children: [
|
|
19779
|
-
/* @__PURE__ */ jsx33("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
19780
|
-
/* @__PURE__ */ jsx33(
|
|
19781
|
-
Badge,
|
|
21152
|
+
linkPopover.key
|
|
21153
|
+
) : null,
|
|
21154
|
+
floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ jsx33(
|
|
21155
|
+
FloatingPanel,
|
|
21156
|
+
{
|
|
21157
|
+
open: true,
|
|
21158
|
+
title: floatingPanel.title,
|
|
21159
|
+
context: floatingPanel.context,
|
|
21160
|
+
position: floatingPanelPos,
|
|
21161
|
+
onPositionChange: setFloatingPanelPos,
|
|
21162
|
+
parentScroll: parentScrollSnap ?? parentScrollRef.current,
|
|
21163
|
+
onClose: closeFloatingPanelOnly,
|
|
21164
|
+
children: /* @__PURE__ */ jsx33(
|
|
21165
|
+
SocialsDisplayPanel,
|
|
19782
21166
|
{
|
|
19783
|
-
|
|
19784
|
-
|
|
19785
|
-
|
|
19786
|
-
|
|
19787
|
-
|
|
19788
|
-
insertAfter: sectionGap.insertAfter,
|
|
19789
|
-
insertBefore: sectionGap.insertBefore
|
|
19790
|
-
},
|
|
19791
|
-
"*"
|
|
19792
|
-
);
|
|
19793
|
-
},
|
|
19794
|
-
children: "Add Section"
|
|
21167
|
+
display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
|
|
21168
|
+
onChange: (next) => {
|
|
21169
|
+
changeSocialsDisplay(floatingPanel.row, next);
|
|
21170
|
+
setFloatingPanel({ ...floatingPanel });
|
|
21171
|
+
}
|
|
19795
21172
|
}
|
|
19796
|
-
)
|
|
19797
|
-
|
|
19798
|
-
|
|
19799
|
-
|
|
19800
|
-
|
|
19801
|
-
|
|
19802
|
-
|
|
19803
|
-
|
|
19804
|
-
|
|
19805
|
-
|
|
19806
|
-
|
|
19807
|
-
|
|
19808
|
-
|
|
19809
|
-
|
|
19810
|
-
|
|
19811
|
-
|
|
19812
|
-
|
|
19813
|
-
|
|
19814
|
-
|
|
21173
|
+
)
|
|
21174
|
+
}
|
|
21175
|
+
) : null
|
|
21176
|
+
] }),
|
|
21177
|
+
bridgeRoot
|
|
21178
|
+
) : null
|
|
21179
|
+
] });
|
|
21180
|
+
}
|
|
21181
|
+
|
|
21182
|
+
// src/ui/EmptySection.tsx
|
|
21183
|
+
import Link3 from "next/link";
|
|
21184
|
+
import { Fragment as Fragment9, jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
21185
|
+
function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
|
|
21186
|
+
return /* @__PURE__ */ jsxs21(Fragment9, { children: [
|
|
21187
|
+
/* @__PURE__ */ jsx34(
|
|
21188
|
+
"p",
|
|
21189
|
+
{
|
|
21190
|
+
style: {
|
|
21191
|
+
fontFamily: "var(--brand-font-body)",
|
|
21192
|
+
fontSize: "0.75rem",
|
|
21193
|
+
fontWeight: 500,
|
|
21194
|
+
letterSpacing: "0.15em",
|
|
21195
|
+
textTransform: "uppercase",
|
|
21196
|
+
color: "var(--brand-accent)",
|
|
21197
|
+
marginBottom: "1.5rem"
|
|
19815
21198
|
},
|
|
19816
|
-
|
|
19817
|
-
|
|
19818
|
-
|
|
19819
|
-
|
|
19820
|
-
|
|
19821
|
-
|
|
19822
|
-
|
|
19823
|
-
|
|
19824
|
-
|
|
19825
|
-
|
|
19826
|
-
|
|
19827
|
-
|
|
19828
|
-
|
|
19829
|
-
|
|
19830
|
-
|
|
19831
|
-
|
|
19832
|
-
|
|
19833
|
-
|
|
19834
|
-
|
|
19835
|
-
|
|
19836
|
-
|
|
19837
|
-
|
|
19838
|
-
|
|
19839
|
-
|
|
19840
|
-
|
|
19841
|
-
|
|
19842
|
-
|
|
21199
|
+
children: /* @__PURE__ */ jsx34(Link3, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ jsx34("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
|
|
21200
|
+
}
|
|
21201
|
+
),
|
|
21202
|
+
/* @__PURE__ */ jsx34(
|
|
21203
|
+
"h1",
|
|
21204
|
+
{
|
|
21205
|
+
style: {
|
|
21206
|
+
fontFamily: "var(--brand-font-heading)",
|
|
21207
|
+
fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
|
|
21208
|
+
lineHeight: 1.1,
|
|
21209
|
+
letterSpacing: "-0.025em",
|
|
21210
|
+
color: "var(--brand-text)",
|
|
21211
|
+
marginBottom: "1rem"
|
|
21212
|
+
},
|
|
21213
|
+
...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
|
|
21214
|
+
children: title
|
|
21215
|
+
}
|
|
21216
|
+
),
|
|
21217
|
+
/* @__PURE__ */ jsx34(
|
|
21218
|
+
"p",
|
|
21219
|
+
{
|
|
21220
|
+
style: {
|
|
21221
|
+
fontFamily: "var(--brand-font-body)",
|
|
21222
|
+
fontSize: "1rem",
|
|
21223
|
+
lineHeight: 1.7,
|
|
21224
|
+
fontWeight: 300,
|
|
21225
|
+
color: "var(--brand-text-muted)",
|
|
21226
|
+
maxWidth: "340px"
|
|
21227
|
+
},
|
|
21228
|
+
...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
|
|
21229
|
+
children: "This page doesn't have any content yet."
|
|
21230
|
+
}
|
|
21231
|
+
)
|
|
21232
|
+
] });
|
|
19843
21233
|
}
|
|
19844
21234
|
export {
|
|
19845
21235
|
AI_DEFAULT_BRAND,
|
|
@@ -19857,6 +21247,7 @@ export {
|
|
|
19857
21247
|
DropdownMenuItem,
|
|
19858
21248
|
DropdownMenuSeparator,
|
|
19859
21249
|
DropdownMenuTrigger,
|
|
21250
|
+
EmptySection,
|
|
19860
21251
|
ItemActionToolbar,
|
|
19861
21252
|
ItemInteractionLayer,
|
|
19862
21253
|
LinkEditorPanel,
|